Skip to content

Add haptic feedback support (Manus + OpenXR controllers)#550

Open
rwiltz wants to merge 5 commits into
mainfrom
rwiltz/tactile-force-feedback
Open

Add haptic feedback support (Manus + OpenXR controllers)#550
rwiltz wants to merge 5 commits into
mainfrom
rwiltz/tactile-force-feedback

Conversation

@rwiltz
Copy link
Copy Markdown
Contributor

@rwiltz rwiltz commented May 21, 2026

Adds a backwards data path through the existing Isaac Teleop retargeting
pipeline so simulators can drive haptic devices. Vendor-neutral by design:
a HapticSink retargeter dispatches to any IHapticDevice adapter, with
two v1 integrations:

  • Manus Metagloves Pro Haptic — per-finger vibration via the existing
    plugin singleton.
  • OpenXR motion-controller haptics (Quest, Vive Index, Pico, ...) — a
    tracker extension on LiveControllerTrackerImpl, not a new plugin.
    Haply Inverse3 force feedback is architecturally pre-approved as the next
    integration; no interface changes needed.
    Design doc: IsaacLab/docs/tactile_haptic_feedback_design.md.

Summary by CodeRabbit

  • New Features

    • System-level haptics: OpenXR controller and Manus glove haptic support, vendor‑agnostic haptic device adapters, new tactile→haptic retargeters and haptic tensor types; Python bindings and packaging for haptic adapters; new runtime haptic sinks/sources.
    • New runnable examples: controller and hand‑pinch haptic demos with CLI and terminal visualization.
  • Documentation

    • Comprehensive haptic examples README with overview, pipelines, CLI usage, and quick‑start.
  • Tests

    • Unit and integration tests covering haptic devices, sinks/sources, and retargeting pipelines.

Review Change Stack

@rwiltz rwiltz requested review from nv-mhaselton and nvddr May 21, 2026 16:55
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1878f68a-6219-496c-86e5-1df63fb87060

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds comprehensive haptic feedback support to IsaacTeleop, enabling vibration control for OpenXR motion controllers and Manus haptic gloves. The implementation includes new C++ haptic APIs in the controller tracker, Python device adapters following a vendor-agnostic interface pattern, tactile tensor type schemas, retargeting nodes for sim-to-device mapping, and two end-to-end example scripts with full test coverage.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

The PR spans multiple interdependent subsystems (C++ APIs, Python adapters, retargeters, examples, tests) across diverse file types and requires careful review of the haptic parameter semantics, error handling guarantees (non-throwing on transient hardware failures), per-side logging gating, and tensor type round-tripping contracts.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main addition: haptic feedback support for Manus and OpenXR controllers. It accurately reflects the primary changes across the entire changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rwiltz/tactile-force-feedback

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/haptic_feedback/python/hand_pinch_haptic_example.py`:
- Around line 436-460: The three CLI float validators (_positive_float,
_non_negative_float, _unit_float) currently accept non-finite values like nan
and inf; update each to import and use math.isfinite to reject non-finite inputs
by raising argparse.ArgumentTypeError (e.g., "expected a finite number, got
...") after parsing the float but before range checks in _positive_float and
_non_negative_float, and ensure _unit_float still calls _non_negative_float then
additionally enforces n <= 1.0 while also rejecting non-finite values via the
same check.

In `@examples/haptic_feedback/python/openxr_controller_haptic_example.py`:
- Around line 296-320: The CLI float validators (_positive_float,
_non_negative_float, _unit_float) currently only check numeric ranges and
therefore allow non-finite values (nan/inf); after parsing the float in each
validator call float(value), validate finiteness using math.isfinite and raise
argparse.ArgumentTypeError (with a message mentioning non-finite values like
NaN/Inf) if not finite, then continue the existing range checks (for
_positive_float: ensure >0, for _non_negative_float: ensure >=0, for
_unit_float: ensure <=1).

In `@src/core/live_trackers/cpp/live_controller_tracker_impl.cpp`:
- Around line 480-518: Guard the haptic inputs before constructing
XrHapticVibration: validate amplitude, duration_s, and frequency_hz with
std::isfinite and sanitize NaNs/inf by mapping them to safe defaults (e.g.,
amplitude -> 0.0f or clamped [0,1], frequency_hz -> XR_FREQUENCY_UNSPECIFIED if
non-finite) and treat non-finite or non-positive duration_s as
XR_MIN_HAPTIC_DURATION; when converting duration_s to nanoseconds compute as
double then clamp the result into the representable XrDuration range (avoid
direct float->integer cast of NaN/Inf) before the static_cast<XrDuration>, and
apply std::clamp for amplitude (0.0f..1.0f) after validating finiteness so NaN
cannot slip through; update the code around XrHapticVibration construction
(references: XrHapticVibration, amplitude, duration_s, frequency_hz) to perform
these checks and clamping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9b9430a6-2ab4-4f91-a7c4-9778574ceb7e

📥 Commits

Reviewing files that changed from the base of the PR and between 8b57406 and 88b37f9.

📒 Files selected for processing (35)
  • CMakeLists.txt
  • examples/haptic_feedback/CMakeLists.txt
  • examples/haptic_feedback/python/README.md
  • examples/haptic_feedback/python/hand_pinch_haptic_example.py
  • examples/haptic_feedback/python/openxr_controller_haptic_example.py
  • examples/haptic_feedback/python/pyproject.toml
  • src/core/AGENTS.md
  • src/core/deviceio_base/cpp/inc/deviceio_base/controller_tracker_base.hpp
  • src/core/deviceio_trackers/cpp/controller_tracker.cpp
  • src/core/deviceio_trackers/cpp/inc/deviceio_trackers/controller_tracker.hpp
  • src/core/deviceio_trackers/python/tracker_bindings.cpp
  • src/core/live_trackers/cpp/live_controller_tracker_impl.cpp
  • src/core/live_trackers/cpp/live_controller_tracker_impl.hpp
  • src/core/oxr_utils/cpp/inc/oxr_utils/oxr_funcs.hpp
  • src/core/python/pyproject.toml.in
  • src/core/replay_trackers/cpp/replay_controller_tracker_impl.hpp
  • src/core/retargeting_engine/python/deviceio_source_nodes/__init__.py
  • src/core/retargeting_engine/python/deviceio_source_nodes/haptic_sink.py
  • src/core/retargeting_engine/python/tensor_types/__init__.py
  • src/core/retargeting_engine/python/tensor_types/indices.py
  • src/core/retargeting_engine/python/tensor_types/tactile_types.py
  • src/core/retargeting_engine_tests/python/test_haptic_devices.py
  • src/core/retargeting_engine_tests/python/test_haptic_sink.py
  • src/core/retargeting_engine_tests/python/test_tactile_retargeters.py
  • src/haptic_devices/CMakeLists.txt
  • src/haptic_devices/__init__.py
  • src/haptic_devices/interface.py
  • src/haptic_devices/manus.py
  • src/haptic_devices/openxr_controller.py
  • src/plugins/manus/CMakeLists.txt
  • src/plugins/manus/core/manus_hand_tracking_plugin.cpp
  • src/plugins/manus/inc/core/manus_hand_tracking_plugin.hpp
  • src/plugins/manus/python/CMakeLists.txt
  • src/plugins/manus/python/manus_haptic_bindings.cpp
  • src/retargeters/tactile_retargeters.py

Comment thread examples/haptic_feedback/python/hand_pinch_haptic_example.py
Comment thread examples/haptic_feedback/python/openxr_controller_haptic_example.py
Comment thread src/core/live_trackers/cpp/live_controller_tracker_impl.cpp Outdated
Comment thread examples/haptic_feedback/python/hand_pinch_haptic_example.py Outdated
@rwiltz rwiltz requested a review from jiwenc-nv May 22, 2026 15:06
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/live_trackers/cpp/live_controller_tracker_impl.cpp (1)

463-553: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

CI blocked: run clang-format on this file.

The pipeline is failing with clang-format violations across lines 463-548 (function signature, conditional expressions, std::cerr statements). The logic itself is sound—non-finite sanitization and duration clamping are correctly implemented—but the build won't pass until formatting is fixed.

clang-format -i src/core/live_trackers/cpp/live_controller_tracker_impl.cpp
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/live_trackers/cpp/live_controller_tracker_impl.cpp` around lines 463
- 553, The file fails CI due to clang-format style violations in
LiveControllerTrackerImpl::apply_haptic_feedback (signature, conditional
expressions, and std::cerr lines); fix by running clang-format on the file and
committing the result (e.g., run `clang-format -i
src/core/live_trackers/cpp/live_controller_tracker_impl.cpp`), ensure the
formatted changes cover the function body (references: apply_haptic_feedback,
safe_amplitude/safe_duration_s/safe_frequency_hz sanitization,
vibration.duration/frequency clamping, and the std::cerr error logs) and re-run
CI to verify the style errors are resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/core/live_trackers/cpp/live_controller_tracker_impl.cpp`:
- Around line 463-553: The file fails CI due to clang-format style violations in
LiveControllerTrackerImpl::apply_haptic_feedback (signature, conditional
expressions, and std::cerr lines); fix by running clang-format on the file and
committing the result (e.g., run `clang-format -i
src/core/live_trackers/cpp/live_controller_tracker_impl.cpp`), ensure the
formatted changes cover the function body (references: apply_haptic_feedback,
safe_amplitude/safe_duration_s/safe_frequency_hz sanitization,
vibration.duration/frequency clamping, and the std::cerr error logs) and re-run
CI to verify the style errors are resolved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2d0f31bf-b679-4e9d-afeb-0a6e9bb835dc

📥 Commits

Reviewing files that changed from the base of the PR and between 88b37f9 and 2a127da.

📒 Files selected for processing (5)
  • examples/haptic_feedback/python/hand_pinch_haptic_example.py
  • examples/haptic_feedback/python/openxr_controller_haptic_example.py
  • src/core/live_trackers/cpp/live_controller_tracker_impl.cpp
  • src/core/retargeting_engine_tests/python/test_tactile_retargeters.py
  • src/retargeters/tactile_retargeters.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants