Skip to main content
Runs a trained policy autonomously on the robot using locally attached ZED cameras and LeRobot’s async inference (lerobot.async_inference). By default a PolicyServer is launched in a child process on localhost; pass --server_host to use a remote inference-server on a more powerful machine instead. Either way the parent drives a thin RobotClient subclass that streams observations (joint positions + camera frames) to the server and consumes the returned action chunks. Type s on stdin to save the rollout and end the episode, r to discard it — the arms drop limp for hand-repositioning (a failed rollout usually leaves them somewhere they shouldn’t be); clear them, then press Enter to return to rest and re-record — or q to discard and quit. --episode_time_s is a safety cap that falls back to the same [Enter]=save / r / q prompt when no key has been pressed.
For the end-to-end workflow — including offloading inference to a GPU machine — see the Run Policy guide.
This command is configured via draccus. The robot subsystem is exposed as the nested robot_config (cameras, per-joint gains) — nest into it with dots or pass a whole-config file. See Command configuration.
If --repo_id is supplied, each saved episode is appended to a LeRobot-format dataset using the same resume/repair/wipe semantics as collect-data (resume a complete dataset, auto-repair a crash-inconsistent one by truncating to the intact episodes — see the collect-data crash-consistency check — refuse an incomplete one, wipe a leftover empty directory), and with the same per-episode durability: each episode’s parquet footers are flushed to disk the moment it saves, so a killed process costs at most the episode in flight. Between episodes the arms return to the rest pose via a collision-aware IK trajectory planned in a worker subprocess, mirroring the reset path used by collect-data.
Action chunk aggregation defaults to ACT’s Algorithm 2 (temporal_ensemble): every future timestep covered by the buffered chunks is the exponentially-weighted average across those chunks, with the gripper indices snapped to the newest contributing chunk so bang-bang grasp commands aren’t smeared. The control loop and observation send run on separate threads — decoupling the ~60-70 ms ZED-read + gRPC send from the 60 Hz action stream that would otherwise collapse to ~27 Hz on the upstream single-threaded design.