Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/source/device/add_device.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ tensor samples from OpenXR. Implement a concrete tracker class (e.g.
``ITrackerFactory``. The implementation uses double dispatch: call the factory method
specific to your tracker type (e.g.
``factory.create_generic_3axis_pedal_tracker_impl(this)``) and return the resulting
``std::unique_ptr<ITrackerImpl>``. The factory constructs an ``ITrackerImpl`` that holds
``std::unique_ptr<ITrackerImpl>``. The factory constructs an ``ITrackerImpl`` that holds
a ``SchemaTracker``, builds a ``SchemaTrackerConfig`` from the tracker's stored
configuration, and implements ``update(XrTime)`` and
configuration, and implements ``update(int64_t target_monotonic_time_ns)`` and
``serialize_all(channel_index, callback)``.

In the **Impl**:

- **update()** — Call ``m_schema_reader.read_all_samples(pending_records)``. If the
- **update(target_monotonic_time_ns)** — Call ``m_schema_reader.read_all_samples(pending_records)``. If the
collection is not present, clear the tracked state (e.g. set ``m_tracked.data = nullptr``).
Otherwise, deserialize the latest sample (or all samples) into your tracked type and
keep the last one for ``get_data()``.
Expand Down Expand Up @@ -157,7 +157,7 @@ the collection and prints samples. Pattern (see :code-file:`examples/schemaio/pe
2. Get required extensions with ``DeviceIOSession::get_required_extensions(trackers)`` and
create an ``OpenXRSession``.
3. Create a ``DeviceIOSession`` with ``DeviceIOSession::run(trackers, oxr_session->get_handles())``.
4. Loop: call ``session->update()``, then read ``tracker->get_data(*session)``. If
4. Loop: call ``session->update(core::os_monotonic_now_ns())``, then read ``tracker->get_data(*session)``. If
Comment thread
coderabbitai[bot] marked this conversation as resolved.
``tracked.data`` is non-null, use the latest sample; otherwise sleep briefly and repeat.

Use the same ``collection_id`` (and optionally ``tensor_identifier``) as the plugin. See
Expand Down Expand Up @@ -213,5 +213,5 @@ Both exit after 100 samples, or press Ctrl+C to exit early.
``get_data(session)`` returning ``Generic3AxisPedalOutputTrackedT`` via the session’s
``Generic3AxisPedalTrackerImpl``.
- **DeviceIOSession** — Session manager: collects required OpenXR extensions from registered
trackers, creates tracker implementations with session handles, and calls ``update()`` on all
trackers during the update loop.
trackers, creates tracker implementations with session handles, and calls
``update(target_monotonic_time_ns)`` on all trackers during the update loop.
6 changes: 3 additions & 3 deletions examples/lerobot/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def main():
try:
while time.time() - start_time < 10.0:
# Update session and all trackers
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand All @@ -130,13 +130,13 @@ def main():
right_pos = np.zeros(3, dtype=np.float32)

if left_tracked.data is not None and left_tracked.data.joints:
wrist = left_tracked.data.joints.poses(deviceio.JOINT_WRIST)
wrist = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Apply ruff formatting for wrist pose calls to unblock CI.

Pre-commit reports this file is reformatted by ruff format; please commit the formatter output so lint checks pass.

🧹 Formatter-aligned shape
-                        wrist = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST)
+                        wrist = left_tracked.data.joints.poses(
+                            deviceio.HandJoint.WRIST
+                        )

-                        wrist = right_tracked.data.joints.poses(deviceio.HandJoint.WRIST)
+                        wrist = right_tracked.data.joints.poses(
+                            deviceio.HandJoint.WRIST
+                        )

Also applies to: 139-139

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/lerobot/record.py` at line 133, The call to retrieve the wrist pose
(wrist = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST)) needs to be
formatted with ruff to satisfy CI; run the ruff formatter (ruff format) on
examples/lerobot/record.py (and the other occurrence around the call at lines
near the second poses(...) call) and commit the resulting changes so the wrist
pose calls and surrounding code match the project's formatting rules.

if wrist.is_valid:
pos = wrist.pose.position
left_pos = np.array([pos.x, pos.y, pos.z], dtype=np.float32)

if right_tracked.data is not None and right_tracked.data.joints:
wrist = right_tracked.data.joints.poses(deviceio.JOINT_WRIST)
wrist = right_tracked.data.joints.poses(deviceio.HandJoint.WRIST)
if wrist.is_valid:
pos = wrist.pose.position
right_pos = np.array(
Expand Down
6 changes: 4 additions & 2 deletions examples/oxr/cpp/oxr_session_sharing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <deviceio_trackers/hand_tracker.hpp>
#include <deviceio_trackers/head_tracker.hpp>
#include <oxr/oxr_session.hpp>
#include <time_utils/os_time.hpp>

#include <chrono>
#include <iostream>
Expand Down Expand Up @@ -76,13 +77,14 @@ try
for (int i = 0; i < 10; ++i)
{
// Both sessions update using the same underlying OpenXR session
if (!session1->update())
const int64_t now_ns = core::os_monotonic_now_ns();
if (!session1->update(now_ns))
{
std::cerr << "Session 1 update failed" << std::endl;
break;
}

if (!session2->update())
if (!session2->update(now_ns))
{
std::cerr << "Session 2 update failed" << std::endl;
break;
Expand Down
3 changes: 2 additions & 1 deletion examples/oxr/cpp/oxr_simple_api_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <deviceio_trackers/hand_tracker.hpp>
#include <deviceio_trackers/head_tracker.hpp>
#include <oxr/oxr_session.hpp>
#include <time_utils/os_time.hpp>

#include <iostream>
#include <memory>
Expand Down Expand Up @@ -75,7 +76,7 @@ try
for (int i = 0; i < 5; ++i)
{
// Session handles internal update() calls to trackers
if (!session->update())
if (!session->update(core::os_monotonic_now_ns()))
{
std::cerr << "Update failed" << std::endl;
break;
Expand Down
6 changes: 3 additions & 3 deletions examples/oxr/python/modular_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def main():
try:
while time.time() - start_time < 10.0:
# Update session and all trackers
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand All @@ -80,7 +80,7 @@ def main():

if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(
deviceio.JOINT_WRIST
deviceio.HandJoint.WRIST
).pose.position
print(
f" Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]"
Expand All @@ -90,7 +90,7 @@ def main():

if right_tracked.data is not None:
pos = right_tracked.data.joints.poses(
deviceio.JOINT_WRIST
deviceio.HandJoint.WRIST
).pose.position
print(
f" Right wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]"
Expand Down
4 changes: 3 additions & 1 deletion examples/oxr/python/modular_example_with_mcap.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ def main():
start_time = time.time()

while time.time() - start_time < 30.0:
session.update()
if not session.update(time.monotonic_ns()):
print("Session update failed, stopping")
break

# Print every 60 frames (~1 second)
if frame_count % 60 == 0:
Expand Down
4 changes: 2 additions & 2 deletions examples/oxr/python/test_controller_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

# Test 4: Initial update
print("[Test 4] Testing initial data retrieval...")
if not session.update():
if not session.update(time.monotonic_ns()):
print("❌ Update failed")
sys.exit(1)

Expand Down Expand Up @@ -105,7 +105,7 @@ def assert_trackers_consistent(label, ta, tb):

try:
while time.time() - start_time < 10.0:
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand Down
6 changes: 4 additions & 2 deletions examples/oxr/python/test_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
Useful when creating external OpenXR sessions.
"""

import time

import isaacteleop.deviceio as deviceio
import isaacteleop.oxr as oxr

Expand Down Expand Up @@ -87,12 +89,12 @@
print(" ✅ Initialized successfully")

# Quick update test
if session.update():
if session.update(time.monotonic_ns()):
left_tracked = hand.get_left_hand(session)
head_tracked = head.get_head(session)
print(" ✅ Update successful")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(deviceio.JOINT_WRIST).pose.position
pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
print(f" Left wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
Comment on lines +92 to 98
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Formatting issue flagged by CI pipeline.

The changes correctly pass the monotonic timestamp to session.update() and use the new HandJoint.WRIST enum. However, CI indicates that ruff format expects multi-line formatting for the joints.poses(...) call on lines 97-98.

🔧 Suggested fix for formatting
             if left_tracked.data is not None:
-                pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
+                pos = left_tracked.data.joints.poses(
+                    deviceio.HandJoint.WRIST
+                ).pose.position
                 print(f"    Left wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if session.update(time.monotonic_ns()):
left_tracked = hand.get_left_hand(session)
head_tracked = head.get_head(session)
print(" ✅ Update successful")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(deviceio.JOINT_WRIST).pose.position
pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
print(f" Left wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
if session.update(time.monotonic_ns()):
left_tracked = hand.get_left_hand(session)
head_tracked = head.get_head(session)
print(" ✅ Update successful")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(
deviceio.HandJoint.WRIST
).pose.position
print(f" Left wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
🧰 Tools
🪛 GitHub Actions: Run linters using pre-commit

[error] 94-96: ruff format modified formatting in this file (ruff-format reformatted 3 files). Formatter changed joints.poses(...) call to a multi-line form.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/oxr/python/test_extensions.py` around lines 92 - 98, The CI
formatting failure is due to a long chained call on
left_tracked.data.joints.poses(...).pose.position; reformat that expression
across multiple lines to satisfy ruff/black style: break the call arguments and
subsequent attribute accesses into separate indented lines so the call to
joints.poses(deviceio.HandJoint.WRIST) and the subsequent .pose.position access
are on their own lines; update the block around session.update,
hand.get_left_hand, and the retrieval expression
(left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position) to use
the multi-line style.

else:
print(" Left hand: inactive")
Expand Down
4 changes: 2 additions & 2 deletions examples/oxr/python/test_full_body_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

# Test 5: Initial update
print("[Test 5] Testing initial data retrieval...")
if not session.update():
if not session.update(time.monotonic_ns()):
print("❌ Update failed")
sys.exit(1)

Expand Down Expand Up @@ -92,7 +92,7 @@
last_status_print = start_time

while time.time() - start_time < 10.0:
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand Down
2 changes: 1 addition & 1 deletion examples/oxr/python/test_hand_inactive_on_plugin_stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def poll_hands(hand_tracker, deviceio_session):
Raises UpdateFailedError if the underlying DeviceIOSession update fails so
callers can distinguish a session error from genuine hand inactivity.
"""
if not deviceio_session.update():
if not deviceio_session.update(time.monotonic_ns()):
raise UpdateFailedError("deviceio_session.update() returned False")
left = hand_tracker.get_left_hand(deviceio_session)
right = hand_tracker.get_right_hand(deviceio_session)
Expand Down
8 changes: 4 additions & 4 deletions examples/oxr/python/test_modular.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

# Test 4: Update and get data
print("[Test 4] Testing data retrieval...")
if not session.update():
if not session.update(time.monotonic_ns()):
print("❌ Update failed")
sys.exit(1)

Expand All @@ -66,7 +66,7 @@
)

if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(deviceio.JOINT_WRIST).pose.position
pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
print(f" Left wrist position: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
else:
print(" Left hand: inactive")
Expand All @@ -93,7 +93,7 @@

try:
while time.time() - start_time < 5.0:
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand All @@ -104,7 +104,7 @@
print(f" [{elapsed:4.1f}s] Frame {frame_count:3d}:")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(
deviceio.JOINT_WRIST
deviceio.HandJoint.WRIST
).pose.position
print(
f" Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]"
Expand Down
4 changes: 3 additions & 1 deletion examples/oxr/python/test_oak_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ def _run_schema_pusher(

while time.time() - start_time < duration:
plugin.check_health()
session.update()
if not session.update(time.monotonic_ns()):
print("Session update failed, stopping")
break
frame_count += 1

elapsed = time.time() - start_time
Expand Down
7 changes: 4 additions & 3 deletions examples/oxr/python/test_session_sharing.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@
try:
while time.time() - start_time < 5.0:
# Both sessions update using the same underlying OpenXR session
if not session1.update():
now_ns = time.monotonic_ns()
if not session1.update(now_ns):
print("Session 1 update failed")
break

if not session2.update():
if not session2.update(now_ns):
print("Session 2 update failed")
break

Expand All @@ -104,7 +105,7 @@

print(f"[{elapsed:4.1f}s] Frame {frame_count:3d}:")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(deviceio.JOINT_WRIST).pose.position
pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
print(f" Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]")
Comment on lines +108 to 109
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Formatting issue flagged by CI pipeline.

The logic correctly uses deviceio.HandJoint.WRIST, but CI indicates ruff format expects multi-line formatting for this call.

🔧 Suggested fix for formatting
             if left_tracked.data is not None:
-                pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
+                pos = left_tracked.data.joints.poses(
+                    deviceio.HandJoint.WRIST
+                ).pose.position
                 print(f"  Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pos = left_tracked.data.joints.poses(deviceio.HandJoint.WRIST).pose.position
print(f" Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]")
pos = left_tracked.data.joints.poses(
deviceio.HandJoint.WRIST
).pose.position
print(f" Left wrist: [{pos.x:6.3f}, {pos.y:6.3f}, {pos.z:6.3f}]")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/oxr/python/test_session_sharing.py` around lines 108 - 109, CI
flagged a ruff formatting issue: break the long call to
left_tracked.data.joints.poses(deviceio.HandJoint.WRIST) into a multi-line
expression so it conforms to the formatter; update the assignment to span
multiple lines (e.g., call poses( with the enum on its own line and closing
paren on its own line) and keep subsequent .pose.position access on the
following line, referencing left_tracked.data.joints.poses and
deviceio.HandJoint.WRIST to locate the code to change.

else:
print(" Left hand: inactive")
Expand Down
6 changes: 3 additions & 3 deletions examples/oxr/python/test_synthetic_hands.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def run_test():
print(f"Plugin crashed: {e}")
break

if not deviceio_session.update():
if not deviceio_session.update(time.monotonic_ns()):
print(" ✗ Reader session update failed")
break

Expand All @@ -111,14 +111,14 @@ def run_test():
print(f"Frame {frame_count}:")
if left_tracked.data is not None:
pos = left_tracked.data.joints.poses(
deviceio.JOINT_WRIST
deviceio.HandJoint.WRIST
).pose.position
print(f" Left wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
else:
print(" Left hand: inactive")
if right_tracked.data is not None:
pos = right_tracked.data.joints.poses(
deviceio.JOINT_WRIST
deviceio.HandJoint.WRIST
).pose.position
print(f" Right wrist: [{pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f}]")
else:
Expand Down
6 changes: 3 additions & 3 deletions examples/retargeting/python/sources_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def main():

while time.time() - start_time < 10.0:
# Update session and all trackers
if not session.update():
if not session.update(time.monotonic_ns()):
print("Update failed")
break

Expand Down Expand Up @@ -195,7 +195,7 @@ def main():
)
if not left_hand.is_none:
left_positions = left_hand[HandInputIndex.JOINT_POSITIONS]
wrist_idx = deviceio.JOINT_WRIST
wrist_idx = deviceio.HandJoint.WRIST
wrist_pos = left_positions[wrist_idx]
print(
f" Wrist: [{wrist_pos[0]:6.3f}, {wrist_pos[1]:6.3f}, {wrist_pos[2]:6.3f}]"
Expand All @@ -206,7 +206,7 @@ def main():
)
if not right_hand.is_none:
right_positions = right_hand[HandInputIndex.JOINT_POSITIONS]
wrist_idx = deviceio.JOINT_WRIST
wrist_idx = deviceio.HandJoint.WRIST
wrist_pos = right_positions[wrist_idx]
print(
f" Wrist: [{wrist_pos[0]:6.3f}, {wrist_pos[1]:6.3f}, {wrist_pos[2]:6.3f}]"
Expand Down
3 changes: 2 additions & 1 deletion examples/schemaio/frame_metadata_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <deviceio_session/deviceio_session.hpp>
#include <deviceio_trackers/frame_metadata_tracker_oak.hpp>
#include <oxr/oxr_session.hpp>
#include <time_utils/os_time.hpp>

#include <chrono>
#include <iostream>
Expand Down Expand Up @@ -107,7 +108,7 @@ try

while (true)
{
if (!session->update())
if (!session->update(core::os_monotonic_now_ns()))
{
std::cerr << "Update failed" << std::endl;
break;
Expand Down
3 changes: 2 additions & 1 deletion examples/schemaio/pedal_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <deviceio_session/deviceio_session.hpp>
#include <deviceio_trackers/generic_3axis_pedal_tracker.hpp>
#include <oxr/oxr_session.hpp>
#include <time_utils/os_time.hpp>

#include <chrono>
#include <iomanip>
Expand Down Expand Up @@ -69,7 +70,7 @@ try
while (received_count < MAX_SAMPLES)
{
// Update session (this calls update on all trackers)
if (!session->update())
if (!session->update(core::os_monotonic_now_ns()))
{
std::cerr << "Update failed" << std::endl;
break;
Expand Down
5 changes: 4 additions & 1 deletion src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ option(BUILD_PYTHON_BINDINGS "Build Python bindings" ON)
# Generated headers from FlatBuffer schemas with additional utilities.
add_subdirectory(schema)

# Build OXR Utils first - header-only utilities (no dependencies)
# Platform time utilities (no OpenXR dependency)
add_subdirectory(time_utils)

# Build OXR Utils - header-only utilities (depends on time_utils for os_time)
add_subdirectory(oxr_utils)

# Build Plugin Manager
Expand Down
10 changes: 0 additions & 10 deletions src/core/cloudxr/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,3 @@ if(CLOUDXR_NATIVE_AVAILABLE)
add_dependencies(cloudxr_python cloudxr_native_bundle)
endif()
endif()

install(
FILES
__init__.py
__main__.py
env_config.py
runtime.py
wss.py
DESTINATION "python/isaacteleop/cloudxr"
)
Loading
Loading