Skip to content

Commit 9fd148e

Browse files
committed
Migrate XrTime to monotonic time in devicetracker API
1 parent a9f4373 commit 9fd148e

25 files changed

Lines changed: 265 additions & 60 deletions

AGENTS.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
-->
5+
6+
<!--
7+
MANDATORY FOR ALL AUTOMATED CODING AGENTS (Cursor, Copilot, etc.):
8+
9+
Before modifying OR creating ANY file under this repository, you MUST use your
10+
file-reading tools to load EVERY AGENTS.md on the directory paths you will touch
11+
(see "CRITICAL — mandatory preflight" below). This is NON-OPTIONAL. Skipping it,
12+
or relying only on chat context without reading those files, is incorrect.
13+
14+
Before you treat work as finished, you MUST run pre-commit as in
15+
"Pre-commit — match CI before you stop" and fix all failures. Declaring the task
16+
done without that run is incorrect.
17+
18+
If pre-commit/CI fails, or the user corrects you, or you repeat the same class of
19+
mistake, you MUST record the lesson in AGENTS.md or source comments per
20+
"Mandatory learning loop" in the same session—not only when the user asks.
21+
22+
Repository owners: keep this block at the top of this file; do not delete it.
23+
-->
24+
25+
# IsaacTeleop — agent notes
26+
27+
## CRITICAL — mandatory preflight (do not skip)
28+
29+
**Hard requirement:** Do **not** edit or add code under `IsaacTeleop/` until you have **read** (e.g. with the Read tool) **every** relevant `AGENTS.md` file as defined below. This is **not** optional, **not** "only for large tasks," and **not** satisfiable by inferring from prior conversation. If you have not read those files in **this** session for **this** task, stop and read them first.
30+
31+
**You must:**
32+
33+
1. List the **directories** you expect to edit or create files under (e.g. `src/core/live_trackers/cpp/`, `src/core/deviceio_base/cpp/inc/…`).
34+
2. For **each** such directory, **read** **`AGENTS.md` in that directory** if it exists.
35+
3. Walk **up** toward the **IsaacTeleop repo root** and **read** **`AGENTS.md` in every ancestor directory** that has one (e.g. `live_trackers/``src/core/`**`IsaacTeleop/AGENTS.md` (this file)**).
36+
37+
**You must not** assume that reading the single "closest" `AGENTS.md` is enough. **Multiple** `AGENTS.md` files can apply to one change (e.g. both `live_trackers` and `deviceio_base`).
38+
39+
**Listing every `AGENTS.md` in this repo** (no curated table here—add new files under the tree without editing this document):
40+
41+
```bash
42+
# Run from the IsaacTeleop repository root (the directory that contains this file):
43+
find . -name AGENTS.md ! -path '*/.git/*' | sort
44+
```
45+
46+
If you cannot run a shell, use your search/glob tools on the pattern `**/AGENTS.md` from the same root. That inventory is for orientation; you must still **read** every file that applies to the directories you will touch (steps 1–3 above).
47+
48+
Optional context index: [`src/core/AGENTS.md`](src/core/AGENTS.md) (also on the ancestor walk—read it when working under `src/core/`).
49+
50+
## Pre-commit — match CI before you stop
51+
52+
- From the **IsaacTeleop repo root** (this directory), run pre-commit and **fix all failures** before you treat a change as finished (do not only rely on “should pass” reasoning).
53+
- **Use the same hook set as GitHub Actions:** `.github/workflows/pre-commit.yaml` runs pre-commit with **`SKIP=check-copyright-year`**. Mirror that locally:
54+
55+
```bash
56+
SKIP=check-copyright-year pre-commit run --all-files
57+
```
58+
59+
- **REUSE:** files covered by the REUSE hook need **`SPDX-FileCopyrightText`** and **`SPDX-License-Identifier`** in the form the repo already uses (for example the HTML comment block at the top of `README.md` also applies to **`AGENTS.md`** and similar docs).
60+
- If a hook failure shows **missing or non-obvious repo policy** (not a one-off typo), you **must** add a **short** reminder under **Mandatory learning loop** rules to the right `AGENTS.md` or adjacent **`//` comments** so the next run does not repeat it—unless it is already documented.
61+
62+
## Mandatory learning loop (AGENTS.md and comments)
63+
64+
**Hard requirement:** When **any** of the following happens, you **must** complete steps 1–3 **before** you end the session or move on as if the work were complete:
65+
66+
1. The **user** is dissatisfied or corrects your approach (wrong layer, scope, style, or a fix that does not stick).
67+
2. **Pre-commit** or **CI** fails on something you or another agent could hit again (linters, REUSE/SPDX, formatting, policy hooks, etc.).
68+
3. You **repeat** the same **category** of error after a correction.
69+
70+
**You must:**
71+
72+
1. **Distill** what went wrong into a **short, reusable pattern** (a rule or boundary, not a chat transcript).
73+
2. **Update** the right artifact in the **same working pass** as the fix: prefer the **most local** `AGENTS.md` for package- or subtree-level rules; use the **repo root** `AGENTS.md` only for expectations that span the whole tree; put **volatile or line-specific** detail in **`//` comments** next to the code.
74+
3. Respect **scope vs `main`** (below): only add `AGENTS.md` bullets for **this branch’s delta** to **`main`** (or the agreed base), not for behavior that already exists on the base branch.
75+
76+
**You must not** skip documentation updates because the user did not say “update AGENTS.md”—failed checks and repeated mistakes **trigger** this loop automatically.
77+
78+
**What belongs in `AGENTS.md`**
79+
80+
- **High-level** expectations: boundaries between layers, what to avoid, naming or structural conventions, CMake/include policy at a glance, “always / never” rules that stay true across refactors.
81+
- **Style of work**: how minimal to keep diffs, when to ask for clarification, how this subsystem should relate to OpenXR/schema/deviceio, etc.
82+
83+
**What does *not* belong in `AGENTS.md`**
84+
85+
- **Low-level or volatile detail**: exact call sequences, field-by-field semantics, long checklists tied to one function, anything that will go stale the next time the code moves.
86+
- Put that in **comments in the source files** where the behavior lives (short `//` notes: intent, invariants, or “do not X because …”).
87+
88+
**Scope — document what *this* branch changes, not main**
89+
90+
- New or updated bullets should capture **learnings from the delta** between **this branch (or commit)** and **`main`** (or whatever long-lived base you are targeting—release branch, parent MR, etc.).
91+
- Do **not** restate facts that already hold on **`main`** just because this branch touches nearby files. If behavior landed in the **base** history, it belongs in **code comments** next to that code or in **main’s** docs—not as “new” guidance in an `AGENTS.md` introduced only to support a smaller follow-up change.
92+
- Example: schema- or API-level choices that merged **before** this branch are **out of scope** for `AGENTS.md` edits tied to this branch; they add churn and read like stale noise after merge.

src/core/AGENTS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
-->
5+
6+
# Agent notes — IsaacTeleop `src/core` (index)
7+
8+
**CRITICAL:** The mandatory multi-file `AGENTS.md` preflight in **[`../../AGENTS.md`](../../AGENTS.md)** applies here too. Before changing anything under `src/core/`, you must have read **this file**, **the repo root `AGENTS.md`**, and **every other `AGENTS.md` on the directory paths you will touch**. Do not skip any of them.
9+
10+
To see **all** `AGENTS.md` files in the IsaacTeleop repo, use the **`find` command (or `**/AGENTS.md` glob) documented in the repo root [`AGENTS.md`](../../AGENTS.md)**—do not rely on a hand-maintained list in this file.
11+
12+
If work under **`src/core/`** went wrong—**user** correction, **pre-commit/CI** failure, or **repeated** same-class mistakes—you **must** follow the repo root **[`AGENTS.md`](../../AGENTS.md)** **Mandatory learning loop**: distill a short rule and **update** the **nearest** relevant `AGENTS.md` (this file or a package file) or **source comments** in the same session (including **delta vs `main`** scope).

src/core/deviceio_base/AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
-->
5+
6+
# Agent notes — `deviceio_base`
7+
8+
**CRITICAL (non-optional):** Before editing this package, complete the mandatory **`AGENTS.md` preflight** in [`../../../AGENTS.md`](../../../AGENTS.md) (read every applicable `AGENTS.md` on your paths, not just this file).
9+
10+
## API
11+
12+
- **`ITrackerImpl::update`** takes **`int64_t monotonic_time_ns`** (system monotonic clock, same domain as `core::os_monotonic_now_ns()`).
13+
- **Do not** use `XrTime`, `<openxr/openxr.h>`, or OpenXR link targets in this library. Keep the tracker abstraction runtime-agnostic.
14+
15+
## CMake
16+
17+
- **`deviceio_base`** is an **INTERFACE** library: list only what the headers actually need (e.g. `isaacteleop_schema`). Do **not** link `OpenXR::headers` or `oxr::oxr_utils` here.
18+
19+
## Fallout for dependents
20+
21+
- Targets that need OpenXR/oxr for compilation must declare those dependencies themselves (they are **not** implied by `deviceio_base`). See e.g. [`../live_trackers/AGENTS.md`](../live_trackers/AGENTS.md). **`deviceio_trackers`** intentionally stays OpenXR-free—see [`../deviceio_trackers/AGENTS.md`](../deviceio_trackers/AGENTS.md).

src/core/deviceio_base/cpp/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ target_include_directories(deviceio_base
1414
target_link_libraries(deviceio_base
1515
INTERFACE
1616
isaacteleop_schema
17-
oxr::oxr_utils
18-
OpenXR::headers
1917
)
2018

2119
add_library(deviceio::deviceio_base ALIAS deviceio_base)

src/core/deviceio_base/cpp/inc/deviceio_base/tracker.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33

44
#pragma once
55

6-
#include <openxr/openxr.h>
7-
6+
#include <cstdint>
87
#include <memory>
98
#include <string>
109
#include <string_view>
1110

1211
namespace core
1312
{
1413

15-
// Forward declarations
16-
struct OpenXRSessionHandles;
17-
1814
// Base interface for tracker implementations.
1915
// The actual worker objects updated each frame by DeviceIOSession.
2016
class ITrackerImpl
@@ -23,13 +19,16 @@ class ITrackerImpl
2319
virtual ~ITrackerImpl() = default;
2420

2521
/**
26-
* @brief Updates tracker state for the specified OpenXR time.
22+
* @brief Updates tracker state for the current frame.
23+
*
24+
* @param monotonic_time_ns Current time from the system monotonic clock, in nanoseconds
25+
* (same domain as core::os_monotonic_now_ns()).
2726
*
2827
* @throws std::runtime_error On critical tracker/runtime failures.
2928
* @note A thrown exception indicates a fatal condition; the application is
3029
* expected to terminate rather than continue running.
3130
*/
32-
virtual void update(XrTime time) = 0;
31+
virtual void update(int64_t monotonic_time_ns) = 0;
3332
};
3433

3534
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
-->
5+
6+
# Agent notes — `deviceio_session`
7+
8+
**CRITICAL (non-optional):** Before editing this package, complete the mandatory **`AGENTS.md` preflight** in [`../../../AGENTS.md`](../../../AGENTS.md) (read every applicable `AGENTS.md` on your paths, not just this file).
9+
10+
## Update loop
11+
12+
- **`DeviceIOSession::update`** reads the clock once with **`core::os_monotonic_now_ns()`** (via `#include <oxr_utils/os_time.hpp>`) and passes that value to **`ITrackerImpl::update(int64_t)`** for every registered impl.
13+
- **No** session-owned **`XrTimeConverter`** is required solely to drive that loop (OpenXR conversion stays inside live impls).
14+
15+
## Implementation / includes
16+
17+
- **`deviceio_session.cpp`**: if the TU uses **`XR_NULL_HANDLE`** or other OpenXR macros, include **`<openxr/openxr.h>`** explicitly after the session header so **`XR_NO_PROTOTYPES`** is already established by **`oxr_utils/oxr_funcs.hpp`** pulled in through **`deviceio_session.hpp`**.
18+
19+
## Related docs
20+
21+
- Tracker interface contract: [`../deviceio_base/AGENTS.md`](../deviceio_base/AGENTS.md)
22+
- Live factory + impls: [`../live_trackers/AGENTS.md`](../live_trackers/AGENTS.md)

src/core/deviceio_session/cpp/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ target_include_directories(deviceio_session
1414
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/inc>
1515
)
1616

17-
# Public headers include oxr_funcs.hpp, which pulls in NVIDIA OpenXR extension
18-
# headers (e.g. XR_NVX1_action_context.h). Propagate Teleop::openxr_extensions so
19-
# consumers (Python bindings, apps) can compile without linking deviceio_trackers.
17+
# Public headers include oxr_funcs.hpp and oxr_session_handles.hpp. Propagate
18+
# oxr::oxr_utils (OpenXR headers + oxr inc/) and Teleop::openxr_extensions (NVIDIA
19+
# extension headers) so consumers (Python bindings, apps) compile without linking
20+
# live_trackers.
2021
target_link_libraries(deviceio_session
2122
PUBLIC
2223
deviceio::deviceio_base
24+
oxr::oxr_utils
2325
Teleop::openxr_extensions
2426
PRIVATE
2527
deviceio::deviceio_trackers

src/core/deviceio_session/cpp/deviceio_session.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include <live_trackers/live_deviceio_factory.hpp>
1111
#include <mcap/writer.hpp>
12+
#include <openxr/openxr.h>
13+
#include <oxr_utils/os_time.hpp>
1214

1315
#include <cassert>
1416
#include <iostream>
@@ -24,7 +26,7 @@ namespace core
2426
DeviceIOSession::DeviceIOSession(const std::vector<std::shared_ptr<ITracker>>& trackers,
2527
const OpenXRSessionHandles& handles,
2628
std::optional<McapRecordingConfig> recording_config)
27-
: handles_(handles), time_converter_(handles)
29+
: handles_(handles)
2830
{
2931
std::vector<std::pair<const ITracker*, std::string>> tracker_names;
3032

@@ -103,11 +105,11 @@ std::unique_ptr<DeviceIOSession> DeviceIOSession::run(const std::vector<std::sha
103105

104106
void DeviceIOSession::update()
105107
{
106-
XrTime current_time = time_converter_.os_monotonic_now();
108+
const int64_t monotonic_ns = os_monotonic_now_ns();
107109

108110
for (auto& kv : tracker_impls_)
109111
{
110-
kv.second->update(current_time);
112+
kv.second->update(monotonic_ns);
111113
}
112114
}
113115

src/core/deviceio_session/cpp/inc/deviceio_session/deviceio_session.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <deviceio_base/tracker.hpp>
77
#include <oxr_utils/oxr_funcs.hpp>
88
#include <oxr_utils/oxr_session_handles.hpp>
9-
#include <oxr_utils/oxr_time.hpp>
109

1110
#include <memory>
1211
#include <optional>
@@ -88,7 +87,6 @@ class DeviceIOSession : public ITrackerSession
8887

8988
const OpenXRSessionHandles handles_;
9089
std::unordered_map<const ITracker*, std::unique_ptr<ITrackerImpl>> tracker_impls_;
91-
XrTimeConverter time_converter_;
9290

9391
// Owned MCAP writer; null when recording is not configured.
9492
std::unique_ptr<mcap::McapWriter> mcap_writer_;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
-->
5+
6+
# Agent notes — `deviceio_trackers`
7+
8+
**CRITICAL (non-optional):** Before editing this package, complete the mandatory **`AGENTS.md` preflight** in [`../../../AGENTS.md`](../../../AGENTS.md) (read every applicable `AGENTS.md` on your paths, not just this file).
9+
10+
## No OpenXR dependency
11+
12+
- **`deviceio_trackers`** must **not** link **`OpenXR::headers`**, **`oxr::oxr_utils`**, or vendor extension targets, and must **not** `#include` OpenXR headers. Public API stays schema + **`deviceio_base`** only.
13+
14+
## Related docs
15+
16+
- Base interface: [`../deviceio_base/AGENTS.md`](../deviceio_base/AGENTS.md)

0 commit comments

Comments
 (0)