Skip to content
Merged
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
2 changes: 1 addition & 1 deletion source/isaaclab_teleop/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
# Semantic Versioning is used: https://semver.org/
version = "0.3.0"
version = "0.3.1"

# Description
title = "Isaac Lab Teleop"
Expand Down
10 changes: 10 additions & 0 deletions source/isaaclab_teleop/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changelog
---------

0.3.1 (2026-02-26)
~~~~~~~~~~~~~~~~~~~

Fixed
^^^^^

* Add cleanup for Isaac Teleop session when Stop XR button is clicked and when Kit is closed.


0.3.0 (2026-02-26)
~~~~~~~~~~~~~~~~~~~

Expand All @@ -9,6 +18,7 @@ Fixed

* Update Isaac Teleop API usage for querying controller button states.


0.2.0 (2026-02-24)
~~~~~~~~~~~~~~~~~~~

Expand Down
43 changes: 43 additions & 0 deletions source/isaaclab_teleop/isaaclab_teleop/session_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ def __init__(self, cfg: IsaacTeleopCfg):
except (ImportError, ModuleNotFoundError):
logger.info("isaacsim.kit.xr.teleop.bridge not available; IsaacTeleop will create its own OpenXR session")

try:
import carb.settings

# Subscribe to the setting (may not fire when Kit closes; see pre-shutdown below)
self._xr_enabled_subscription = carb.settings.get_settings().subscribe_to_node_change_events(
"/xr/enabled",
self._on_xr_enabled_changed,
)
except (ImportError, ModuleNotFoundError):
logger.info("carb.settings not available; IsaacTeleop will not be able to detect XR enabled state")

try:
import omni.kit.app
from carb.eventdispatcher import get_eventdispatcher

# Subscribe to Kit pre-shutdown so we tear down our session before XRCore
# tears down the OpenXR instance/session (XRCore uses order=0; lowest runs first).
# The /xr/enabled setting often does not fire on close, so this is required.
self._pre_shutdown_subscription = get_eventdispatcher().observe_event(
event_name=omni.kit.app.GLOBAL_EVENT_PRE_SHUTDOWN,
on_event=self._on_pre_shutdown,
observer_name="IsaacTeleop session lifecycle",
order=-100,
)
except (ImportError, ModuleNotFoundError):
logger.info("omni.kit.app/carb.eventdispatcher not available; IsaacTeleop will not clean up on Kit close")

@property
def is_active(self) -> bool:
"""Whether the teleop session is currently running."""
Expand Down Expand Up @@ -190,6 +217,22 @@ def _on_request_required_extensions(self) -> list[str]:
logger.info(f"Required extensions: {required_extensions}")
return required_extensions

def _on_xr_enabled_changed(self, item, event_type):
import carb.settings

enabled = carb.settings.get_settings().get("/xr/enabled")
logger.info(f"XR enabled changed to: {enabled}")

if not enabled:
self._teardown_dead_session()

def _on_pre_shutdown(self, _event):
"""Called when Kit is closing; run full cleanup since the app is exiting."""
logger.info("Shutting down IsaacTeleop session due to Kit close")
self._pre_shutdown_subscription.unsubscribe()
self._pre_shutdown_subscription = None
self.stop()

# ------------------------------------------------------------------
# Deferred session creation
# ------------------------------------------------------------------
Expand Down
Loading