Skip to content

Replace legacy keyboard, gamepad and SpaceMouse input with Isaac Capture - #8797

Merged
ooctipus merged 17 commits into
isaac-sim:mainfrom
rwiltz:rwiltz/keyboard-focus-surfaces
Oct 26, 2026
Merged

ooctipus merged 17 commits into
isaac-sim:mainfrom
rwiltz:rwiltz/keyboard-focus-surfaces

Conversation

@rwiltz

@rwiltz rwiltz commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Keyboard, gamepad and SpaceMouse input now has one implementation in Isaac Capture. The six old SE(2)/SE(3) implementation classes, their SpaceMouse HID helpers, and the unused hidapi dependency are removed. The old config classes remain as data records deprecated in Isaac Lab 3.2: select_teleop_cfg translates them once into Isaac Capture configs before launch, preserving sensitivities, dead zones, gripper settings, activation and output device. There are no constructor adapters or automatic fallbacks for these devices. Other device types, including native OpenXR hand tracking, retain their own implementation and factory.

All repository callers move in this PR so removing the implementations leaves a working tree. teleop_se3_agent.py, record_demos.py, consolidated Mimic, pick-and-place and the manual keyboard check use Isaac Capture builders directly for their defaults. Replay and annotation use the visualizers' add_key_callbacks for hotkeys without starting a teleop session. Isaac Capture consumers receive their windows explicitly and close the device before the environment. The demo loops handle startup and pause; consolidated Mimic consumes the flat action directly and holds the gripper state while motion is paused.

The SO-101 stacking pipeline also uses the Isaac Capture 1.7 clutch API: the retired fixed orientation offset is removed, and the SDK owns engage-relative orientation seeded from the existing home transform. Its integration test executes real controller snapshots through the graph and checks numeric pose/gripper ordering, release/re-engage and reset.

The six public pipeline builders remain in one flat device_pipelines.py, with shared action packing only where required. This builds on merged #8158 and requires Isaac Capture 1.7 through the Linux teleop extra. It incorporates the remaining-caller migration previously planned for #8798; that follow-up overlaps this change and will need rebasing. There is no dependency on #8798.

Breaking: direct calls such as Se3Keyboard(cfg) are removed. Use se3_keyboard_teleop_cfg(...) (or the corresponding builder), pass the result to create_isaac_teleop_device, and enter the returned context manager. The feature guide documents standalone session setup and config migration. Existing environment config declarations continue to translate with a migration warning; they no longer point to removed constructors.

Validation:

  • 137 focused tests passed with one skip, across 13 files run in separate processes against the pinned Isaac Capture 1.7 packages. Coverage includes real SDK numeric actions/config translation, window/session lifecycle, native factory callbacks, Haply, CLI entry points, replay, and demo startup/pause/cleanup.
  • Seven deliberate regressions were rejected: a retained config constructor target, lost activation, skipped subclass migration, accepted missing Isaac Capture, cleared paused gripper, ignored demo pause, and repeated hotkeys.
  • After the SO-101 compatibility fix, 25 focused pipeline/IK/gripper/selection tests passed. The new graph regression failed on the original constructor argument; deliberate missing-gripper and reordered-quaternion mutations are rejected by numeric output checks.
  • Removed the file-existence assertions requested in review; the real pipeline tests retain config translation, versioned deprecation warnings and numeric output coverage.
  • A centralized file audit confirmed config-only legacy packages, no imports of retired classes, no old constructor targets, no additional script wrapper, and no HID dependency.
  • Full Sphinx HTML build passed with warnings treated as errors. Repository formatting/changelog checks, git diff --check, and uv lock --check --offline passed.

Physical devices and a full CloudXR session were not exercised locally. The legacy OpenXR constructor test could not collect in the bare test container because carb requires the Kit runtime; CI must cover it.

@rwiltz
rwiltz requested a review from a team October 23, 2026 15:01
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels Oct 23, 2026
@rwiltz
rwiltz marked this pull request as draft October 23, 2026 15:02
@greptile-apps

greptile-apps Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] No new blocking defect was established in the changes since the previous review.

Summary

Routes keyboard, gamepad, and SpaceMouse teleoperation through Isaac Capture while keeping the native-device fallback.

  • Kit and Newton visualizers now report keyboard events through a shared input source.
  • Keyboard pipelines now drive SE(2) and SE(3) teleoperation from the focused viewer.
  • Gamepads now drive SE(2) and SE(3) teleoperation through Isaac Capture.
  • SpaceMouse devices now drive SE(2) and SE(3) teleoperation through Isaac Capture.
  • Teleoperation scripts now select matching Isaac Capture pipelines from device requests.

Previous-thread context:

  • rwiltz explained that Isaac Capture tests device behavior upstream. Greptile conceded that broad request; the thread was resolved.
  • The later-window finding is addressed by checking for unattached visualizers on each step. Its thread was manually resolved without an explanatory reply.
  • The recording thread was manually resolved without an explanatory reply. The new guard prevents the direct demo discard, but it does not stop an operator reset from pausing the Capture session before the script checks the guard.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    Config[Device configuration] --> Selection[Select Capture pipeline or native fallback]
    Window[Focused visualizer window] --> Keys[Key events]
    Keys --> Capture[Isaac Capture session]
    Plugins[Gamepad or SpaceMouse plugin] --> Capture
    Selection --> Capture
    Capture --> Device[IsaacTeleopDevice]
    Device --> Scripts[Teleoperation and recording scripts]
Loading

Reviews (4) · Last reviewed commit: "Relock with the repository's uv and tidy..." · Reviewed by Greptile

Comment thread source/isaaclab_teleop/test/test_gamepad_constructors.py Outdated
Comment thread source/isaaclab_teleop/isaaclab_teleop/session_lifecycle.py Outdated
@rwiltz

rwiltz commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

@greptile

Comment thread scripts/tools/record_demos.py Outdated
@rwiltz
rwiltz force-pushed the rwiltz/keyboard-focus-surfaces branch from 1fdb61c to b3f98dc Compare October 23, 2026 15:51

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

Needs attention: Design and architecture (1), Scope and over-engineering (2), Compatibility and deprecation (2), Style consistency (1), Test quality (1). Other reviewed categories look good.

  • PR description: The body omits the isaacteleop-to-isaaccapture dependency and lockfile migration, retains the empty issue placeholder, and provides no validation commands; add these details, while no performance benchmark is required.
  • Design and architecture: TeleopSessionLifecycle retrieves visualizers through SimulationContext.instance() and suppresses lookup failures, hiding keyboard loss; pass owned visualizers from the composition root and remove the broad guard.
  • Scope and over-engineering: Minimal implementation: extend BaseVisualizer, KitVisualizer, NewtonVisualizer, TeleopSessionLifecycle, and both scripts; keep key_event_source, _plugins, device_selection, six builders, six export files, and Kit/Newton sources; conditionally forward SpaceMouse buttons and reuse reset_recording_instance. Suggested PR breakdown: 1) visualizer key API/backends; 2) dependency/lock migration; 3) builders/lifecycle controls; 4) script routing/docs, each with focused package tests.
  • API: API changes look good.
  • Compatibility and deprecation: Breaking changes: explicit device selection silently changes established routing; preserve old routing through a warned, documented deprecation with transition coverage, and regenerate uv.lock using repository uv.
  • Implementation: Implementation looks good.
  • Style consistency: IsaacTeleopDevice places four unannotated class constants among private methods; move them before instance methods and declare them as ClassVar[int].
  • Test quality: The key-source, routing, session, and operator tests protect distinct contracts, but the RTX camera-key row repeats the same inherited GL-viewer path; keep one backend-independent case.

Significant concerns. Posted 7 inline findings.

Automated review; human maintainers own approval decisions.

Comment thread scripts/tools/record_demos.py
Comment thread source/isaaclab_teleop/isaaclab_teleop/device_selection.py Outdated
Comment thread source/isaaclab_teleop/isaaclab_teleop/isaac_teleop_device.py Outdated
Comment thread source/isaaclab_teleop/isaaclab_teleop/session_lifecycle.py
Comment thread source/isaaclab_teleop/isaaclab_teleop/session_lifecycle.py Outdated
Comment thread source/isaaclab_visualizers/test/test_key_event_sources.py Outdated
Comment thread uv.lock Outdated
@rwiltz

rwiltz commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

@greptile

@rwiltz

rwiltz commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 23, 2026
@rwiltz
rwiltz force-pushed the rwiltz/keyboard-focus-surfaces branch from 126aad5 to 4d2e81d Compare October 24, 2026 03:06
ooctipus added a commit that referenced this pull request Oct 24, 2026
# Description
Adds a keyboard input API to visualizers, so code can read the keys
pressed in a visualizer's window, e.g. for keyboard teleoperation or
script hotkeys, independent of Kit/carb.
  
- `BaseVisualizer.key_event_source` returns a `KeyEventSource` for the
visualizer's window, or `None` when it has none (the default; also
before initialization, after close, and headless). It is created
  on first access and closed with the visualizer.
- `KeyEventSource.add_key_listener(on_key, on_focus_lost)` returns a
closable `KeyboardSubscription`. Presses and releases arrive as W3C
`KeyboardEvent.code` strings (`"KeyW"`), forwarded as the window
reports them; `on_focus_lost` runs on blur, when the visualizer's UI
takes the keyboard, and on close. Subscribing, closing and callbacks all
happen on the visualizer's thread.
- `BaseVisualizer.set_camera_keys_enabled(enabled)` lets the caller turn
off keyboard camera movement (Newton WASD/QE and arrow keys) while it
uses those keys; a no-op by default.
- Implemented for Kit (physical keys; Kit visualizers share the app
window, so each reports the same keys) and for Newton GL and Newton RTX
(one pyglet viewer window; US-layout key mapping, presses
typed into the ImGui UI are withheld). Viser, Rerun and headless runs
return `None`.
- Each visualizer closes its keyboard source first in `close()`, while
the window is still open; a failure there is logged and the rest of the
teardown still runs.
 
Opt-in: nothing is hooked until a listener subscribes, and existing
visualizer behavior is unchanged.
  
Used by #8797 (keyboard, gamepad and SpaceMouse teleop through Isaac
Capture) and #8798 (remaining scripts and deprecation of the
`isaaclab.devices` keyboard, gamepad and SpaceMouse devices).

Fixes # (issue)

## Type of change

<!-- As you go through the list, delete the ones that are not
applicable. -->

- New feature (non-breaking change which adds functionality)

## Release backport

- [ ] <!-- backport-active-release --> Backport this pull request to the
active release branch after it merges into `develop`

## Checklist

Docker and GPU tests run on demand. Push the commits you want tested,
then
comment `run-ci` on the pull request.

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`uv run isaaclab --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have validated the changed behavior with focused coverage and
applied the [test-audit
criteria](https://github.com/isaac-sim/IsaacLab/blob/develop/skills/developer/test-audit/SKILL.md)
to any test changes
- [x] I have added a changelog fragment under
`source/<pkg>/changelog.d/` for every touched package (do **not** edit
`CHANGELOG.rst` or bump package versions — CI handles that)
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

---------

Co-authored-by: ooctipus <zhengyuz@nvidia.com>
Add builders for keyboard, gamepad and SpaceMouse SE(2)/SE(3) Isaac
Capture pipelines. The keyboard is read inside the teleop session from
whichever visualizer window has focus (no input group, no keys from other
apps); while a pipeline reads it, the session turns off the visualizers'
keyboard camera movement. The gamepad and SpaceMouse configs start the
Isaac Capture gamepad and spacemouse plugins with the session, which read
/dev/input/jsN and /dev/hidrawN. Like every Isaac Capture session they
open an OpenXR session; without a headset they run on the standalone
CloudXR profile.

IsaacTeleopDevice now starts, pauses and resets teleoperation on the B, P
and R keys typed into a visualizer window and resets on a SpaceMouse
pipeline's right button, the bindings the teleop scripts made themselves
through a Carb keyboard. Each key press is handled once, whatever the
retargeting mode.

device_selection translates an isaaclab.devices keyboard, gamepad or
SpaceMouse config into the equivalent pipeline, so a script can serve
--teleop_device and an environment's teleop_devices entries through Isaac
Capture.
@ooctipus

Copy link
Copy Markdown
Collaborator

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 25, 2026
rwiltz and others added 5 commits October 25, 2026 08:18
isaaccapture publishes Linux aarch64 wheels, so the teleop extra now
installs it on any Linux system instead of x86_64 only. dex-retargeting
stays x86_64 only. uv.lock keeps isaaccapture 1.7.44a1 and adds its
aarch64 wheel.
select_teleop_cfg no longer falls back to the isaaclab.devices keyboard,
gamepad and SpaceMouse when Isaac Capture is missing: it raises an
ImportError naming the teleop extra, as it does for an environment's
declared Isaac Capture pipeline. Devices without a Capture pipeline
(e.g. OpenXR hand tracking) keep their native config and factory.
Restore the prior PR contents so the proposed cleanup can be reviewed as comments.
… docs

Attach the visualizer keyboards at the end of session start, so a start
that fails part way does not leave listeners attached or camera keys
disabled. Update the teleop docs for the isaaccapture 1.7 pin and its
Linux aarch64 install.

Co-authored-by: AntoineRichard <antoiner@nvidia.com>
Signed-off-by: Rafael Wiltz <rwiltz@nvidia.com>

@AntoineRichard AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

From a high-level the changes look good!

Signed-off-by: Rafael Wiltz <rwiltz@nvidia.com>
@ooctipus
ooctipus requested a review from peterd-NV as a code owner October 26, 2026 18:20
@github-actions github-actions Bot added the isaac-mimic Related to Isaac Mimic team label Oct 26, 2026
@ooctipus ooctipus changed the title Run keyboard, gamepad and SpaceMouse teleop through Isaac Capture Replace legacy keyboard, gamepad and SpaceMouse input with Isaac Capture Oct 26, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 26, 2026
@ooctipus
ooctipus requested a review from hujc7 as a code owner October 26, 2026 20:14
@ooctipus

Copy link
Copy Markdown
Collaborator

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 26, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Oct 26, 2026
@ooctipus
ooctipus merged commit 8ea8e9e into isaac-sim:main Oct 26, 2026
59 checks passed
ooctipus pushed a commit that referenced this pull request Oct 26, 2026
# Description
  Depends on #8797; only the last commit is new until it merges.

`teleop_se3_agent.py` and `record_demos.py` set `require_kit = True`
because their input devices and RTX settings used Kit APIs. Since #8797,
keyboard, gamepad and SpaceMouse run through Isaac Capture
and read the visualizer windows, so the scripts no longer set
`require_kit` and let `launch_simulation` decide. `--xr` (the launcher
adds a Kit visualizer for it), PhysX, Isaac RTX cameras and the Kit
visualizer still start Kit. The remaining native devices are XR ones
that need `--xr`, plus Haply, which does not use Kit. The scripts can
now run with kitless visualizers such as `newton_rtx`.

- The RTX/DLSS settings and `record_demos.py`'s instruction window apply
only when Kit is running. Without Kit, recording progress is printed to
the console.
- `IsaacTeleopDevice` failed to start when Isaac Sim was installed but
Kit was not running: `carb` imports, but its settings interface does not
exist. The XR anchor settings and the CloudXR GPU pinning
  now check `has_kit()`.

  Example:
`./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py
--task Isaac-Reach-Franka --teleop_device keyboard --viz newton_rtx
physics=newton_mjwarp presets=diffik`

  ## Type of change

  - New feature (non-breaking change which adds functionality)
  - Bug fix (non-breaking change which fixes an issue)

  ## Testing

  Keyboard teleop with both scripts:
- No Kit, Reach with Newton physics: `--viz newton_rtx`, and `--viz
newton_gl` for `record_demos.py`. Kit stays off and the keyboard
attaches to the Newton window.
- Kit: `--viz kit` on Lift, `--viz newton_gl` on Lift (PhysX still
starts Kit), no `--viz`, and `--xr` (checked that Kit starts; no
headset).

Known issue, not introduced here (reproduces on `main` and without
teleop): with Newton GL and Newton physics, `env.sim.reset()` fails to
redraw command markers (`connecting_line not found`), and the
visualizer is removed. `record_demos.py` calls it by default, so use
`--no-reset_sim_buffer_each_episode` with `newton_gl` until that is
fixed.


## Checklist

Docker and GPU tests run on demand. Push the commits you want tested,
then
comment `run-ci` on the pull request.

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`uv run isaaclab --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have validated the changed behavior with focused coverage and
applied the [test-audit
criteria](https://github.com/isaac-sim/IsaacLab/blob/HEAD/skills/developer/test-audit/SKILL.md)
to any test changes
- [x] I have added a changelog fragment under
`source/<pkg>/changelog.d/` for every touched package (do **not** edit
`CHANGELOG.rst` or bump package versions — CI handles that)
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

Signed-off-by: Rafael Wiltz <rwiltz@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation infrastructure isaac-lab Related to Isaac Lab team isaac-mimic Related to Isaac Mimic team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants