Install
Credentials
Both machines need a token and the same room id.Follower
Runs on the machine with the robot. Three methods: what the joints are called, how to read them, and how to write them.follower.py
run() joins the room and paces the loop for you. On every pass it applies
whatever command arrived, and holds position if the leader goes quiet. Ten times
a second it sends the joint positions along with a camera frame.
control_hz is the loop rate and observation_hz the publish rate, so an
observation goes out every third tick here. slew caps how far a joint may move
in one tick. See Configuration for the
rest.
Swap the two dictionary lines for your own driver calls and nothing else
changes.
write_joints() receives values that have already passed the limits
and speed cap in SafetyConfig.Leader
Runs on the machine with the controller. Two methods, and no writes.leader.py
ticks() paces the loop and sends a command on every pass, using whatever
read_joints() returns. observation() gives you the latest from the follower:
a camera frame, and the joint positions from the moment that frame was taken.
Control, arming and the fields on a synced observation are in the
Leader reference.
Run it
Two terminals, both with the token and the room id exported.Output
holding (starvation)is the starting state. The follower applies nothing until the leader claims control.applied 40 <- observation 302pairs each command with the observation the operator was acting on. That pairing is what a recording keeps.joints={}on the first tick means nothing has arrived from the follower yet. It fills in on the next observation.cameras=[]because this run had no camera. With one configured you see its label here, andobs.imagescarries a frame for each.
Seeing
holding (starvation) again mid-run is the watchdog. Commands stopped
arriving for longer than watchdog_timeout_s, so the arm held position until
they resumed. Stop the leader entirely and it stays there.Record a dataset
Add a path and the session is written to disk as you drive.record= attaches a recorder when the session starts, and stop() closes it.
To control that yourself, leave it out and call start_recording() and
stop_recording() instead.
See Recording for the format and the LeRobot export.
Integration quickstarts
If your robot is already on one of these, start there instead.LeRobot
Pass your existing LeRobot robot and teleoperator to the adapters. They
work out the joints and units for you, so there is no class to write.
ROS 2
Run a bridge node on each host, beside the drivers you already have. Your
drivers keep the hardware.
Next steps
Follower
Every constructor argument, callback and method on the robot side.
Leader
Control, arming, and the synced observation.
Safety
The checks a command passes before it reaches the motors.
Custom robot
The full version of what this page showed, including cameras and telemetry.