Source code for isaaclab_teleop.control_events

# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""Teleop control events dataclass, polling helper, and well-known channel UUID."""

from __future__ import annotations

import dataclasses
import uuid
from typing import Protocol, runtime_checkable

TELEOP_CONTROL_CHANNEL_UUID: bytes = uuid.uuid5(uuid.NAMESPACE_DNS, "teleop_command").bytes
"""Well-known 16-byte UUID for the teleop control message channel.

Derived deterministically as ``uuid5(NAMESPACE_DNS, "teleop_command")``
so that both the Isaac Lab server and the Quest client can independently
compute the same channel identifier from the string ``"teleop_command"``.

Pass this value as :attr:`~isaaclab_teleop.IsaacTeleopCfg.control_channel_uuid`
when configuring a teleop session with message-channel-based control.
"""


[docs] @dataclasses.dataclass(frozen=True) class ControlEvents: """Result of :func:`poll_control_events`. Attributes: is_active: ``True`` when the teleop state machine is in RUNNING, ``False`` when PAUSED or STOPPED, or ``None`` when no control channel is configured (callers should leave their own active flag unchanged). should_reset: ``True`` when a reset was triggered this frame. """ is_active: bool | None = None should_reset: bool = False
_NO_OP_EVENTS = ControlEvents() """Shared immutable sentinel returned when no control channel is active."""
[docs] @runtime_checkable class SupportsControlEvents(Protocol): """Duck type for teleop devices that expose control events.""" @property def last_control_events(self) -> ControlEvents: ...
def poll_control_events(teleop_interface: SupportsControlEvents | object) -> ControlEvents: """Poll control events from any teleop interface. Safe to call with any device type (keyboard, spacemouse, etc.). Devices that do not expose the message-channel protocol return a no-op :class:`ControlEvents`. Args: teleop_interface: The teleop device to poll. Devices implementing :class:`SupportsControlEvents` provide full type safety; other devices are handled gracefully via duck typing. Returns: A :class:`ControlEvents` with the latest start/stop and reset signals. """ events = getattr(teleop_interface, "last_control_events", None) if events is None: return _NO_OP_EVENTS if isinstance(events, ControlEvents): return events return ControlEvents( is_active=getattr(events, "is_active", None), should_reset=getattr(events, "should_reset", False), )