lerobotteleoperatorrosetta

February 5, 2026 · View on GitHub

LeRobot Teleoperator plugin for ROS2. Captures human input from contract-defined topics for teleoperation and human-in-the-loop training.

Usage

from lerobot_teleoperator_rosetta import RosettaTeleop, RosettaTeleopConfig

teleop = RosettaTeleop(RosettaTeleopConfig(config_path="contract.yaml"))
teleop.connect()

# Get action from human operator
action = teleop.get_action()
# {"leader.position.j1": 0.1, "leader.position.j2": 0.2}

# Check events (buttons, intervention signals)
events = teleop.get_teleop_events()
# {TeleopEvents.IS_INTERVENTION: True, TeleopEvents.SUCCESS: False, ...}

# Send feedback to operator (optional)
teleop.send_feedback({"status": 1.0})

teleop.disconnect()

Or with LeRobot CLI:

lerobot-teleop \
    --robot.type=rosetta --robot.config_path=contract.yaml \
    --teleop.type=rosetta_teleop --teleop.config_path=contract.yaml

Installation

colcon build --packages-select lerobot_teleoperator_rosetta
source install/setup.bash

The package follows LeRobot's lerobot_teleoperator_* naming convention and is auto-discovered.

Configuration

Configure via the teleop section of your contract:

teleop:
  inputs:
    - key: teleop_input
      topic: /leader_arm/joint_states
      type: sensor_msgs/msg/JointState
      selector:
        names: [position.j1, position.j2, position.j3]

  events:
    topic: /joy
    type: sensor_msgs/msg/Joy
    mappings:
      is_intervention: buttons.5   # Human taking over
      success: buttons.0           # Mark success
      terminate_episode: buttons.6 # End episode
      rerecord_episode: buttons.7  # Discard and restart
      failure: buttons.1           # Mark failure

  feedback: []  # Optional publishers for operator feedback

LeRobot Interface

Implements the Teleoperator base class:

Property/MethodDescription
action_featuresDict of action names → types
feedback_featuresDict of feedback names → types
is_connectedTrue when lifecycle node is active
connect()Configure and activate ROS2 subscriptions/publishers
disconnect()Deactivate and cleanup
get_action()Sample current action from input buffers
get_teleop_events()Get current event states (intervention, success, etc.)
send_feedback(feedback)Publish feedback to ROS2 topics

HIL-SERL Integration

from lerobot_robot_rosetta import Rosetta, RosettaConfig
from lerobot_teleoperator_rosetta import RosettaTeleop, RosettaTeleopConfig
from lerobot.teleoperators.utils import TeleopEvents

robot = Rosetta(RosettaConfig(config_path="contract.yaml"))
teleop = RosettaTeleop(RosettaTeleopConfig(config_path="contract.yaml"))

robot.connect()
teleop.connect()

while True:
    events = teleop.get_teleop_events()

    if events[TeleopEvents.IS_INTERVENTION]:
        action = teleop.get_action()  # Human controls
    else:
        obs = robot.get_observation()
        action = policy(obs)          # Policy controls

    robot.send_action(action)

    if events[TeleopEvents.TERMINATE_EPISODE]:
        break

License

Apache-2.0