Skip to content

Run keyboard, gamepad and SpaceMouse teleop through Isaac Capture - #8797

Open
rwiltz wants to merge 5 commits into
isaac-sim:mainfrom
rwiltz:rwiltz/keyboard-focus-surfaces
Open

rwiltz wants to merge 5 commits into
isaac-sim:mainfrom
rwiltz:rwiltz/keyboard-focus-surfaces

Conversation

@rwiltz

@rwiltz rwiltz commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Description

Stacked on #8158 (keyboard input from visualizer windows); review that first. This is the controller integration that uses its API.

Keyboard, gamepad and SpaceMouse teleop can now run as Isaac Capture pipelines in isaaclab_teleop, with the same keys and buttons as the isaaclab.devices devices:

  • se2/se3_keyboard_teleop_cfg, se2/se3_gamepad_teleop_cfg and se2/se3_spacemouse_teleop_cfg build an IsaacTeleopCfg for each device. The keyboard is read in process from whichever visualizer
    window has focus (Kit or Newton), with no input group and no keys from other apps; while it is read, the visualizers' keyboard camera movement is turned off. The gamepad and SpaceMouse are read by the
    Isaac Capture gamepad and spacemouse plugins, started with the session. Without --xr they run headset-free on the standalone CloudXR profile.
  • IsaacTeleopDevice starts, pauses and resets teleoperation on B / P / R and resets on the SpaceMouse right button, the bindings the scripts made through a Carb keyboard.
  • device_selection translates an isaaclab.devices keyboard, gamepad or SpaceMouse config into the equivalent pipeline. teleop_se3_agent.py and record_demos.py use it, so --teleop_device and
    environment teleop_devices entries work unchanged. Without the isaacteleop package they keep using the isaaclab.devices devices.

Follow-up: #8798 moves the remaining keyboard scripts (replay, annotate, consolidated Mimic, pick-and-place) and deprecates the isaaclab.devices keyboard, gamepad and SpaceMouse devices.

Fixes # (issue)

Type of change

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

Checklist

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

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with uv run isaaclab --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have validated the changed behavior with focused coverage and applied the test-audit criteria to any test changes
  • 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)
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

@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
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
@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
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
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.
teleop_se3_agent.py and record_demos.py now serve keyboard, gamepad and
SpaceMouse devices through Isaac Capture when the isaacteleop package is
installed, and through the isaaclab.devices devices otherwise (e.g. on
aarch64 or Windows). --teleop_device keeps its meaning: an entry of the
environment's teleop_devices, or a built-in device. Environments need no
changes. The scripts no longer create a Carb keyboard for the B, P and R
control keys, which the device now handles.
…vices

The keyboard, gamepad and SpaceMouse sources and the gamepad and
spacemouse plugins first ship in Isaac Capture 1.7, published as
isaaccapture (isaacteleop renamed; it still provides the isaacteleop
import). The teleop extra now installs isaaccapture~=1.7.44a1 instead of
isaacteleop~=1.4.145. uv.lock adds isaaccapture and cupy-cuda12x and
moves the isaacteleop alias package to the same release. The docs point
the release branch, web client and Haptikos plugin links at 1.7.x.
record_demos.py now applies the R callback's guard to an Isaac Capture
reset: while a successful demo is still recording its post-success
steps, the reset is refused with the same message as for the
isaaclab.devices keyboard. Other resets, including the host reset after
each episode, are handled as before. The session checks for unattached
visualizer windows on every step, not only until the first one
attaches, so a window that initializes later also gets keyboard input.
uv.lock is regenerated from main's lock with uv 0.13.5, which keeps lock
revision 5 and viser's ipywidgets dependency; only isaaccapture,
cupy-cuda12x and the isaacteleop alias package change. The B / P / R
key codes are class constants at the top of IsaacTeleopDevice, and the
device-selection test records the builders the routing table actually
calls rather than names the test supplies.
@rwiltz
rwiltz force-pushed the rwiltz/keyboard-focus-surfaces branch from 4d2e81d to 4ca88da Compare October 24, 2026 12:50

This branch has not been deployed

No deployments
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant