lerobot extra. These classes implement the LeRobot Robot, Teleoperator and Camera interfaces, so Axol works with any LeRobot training or data-collection pipeline. The collect-data and run-policy commands are built on them.
Use with the stock LeRobot CLIs
Thelerobot_robot_axol plugin on PyPI registers these wrappers with LeRobot, so the stock LeRobot CLIs (lerobot-teleoperate, lerobot-record, lerobot-replay and others) can drive Axol. Installing the plugin also installs almond-axol[lerobot]. Then select the devices by type:
Teleoperation still uses the VR headset: open the VR app and connect to the robot’s computer. For the best data collection performance, use
collect-data and run-policy instead. They add ZED capture in a separate process, NVENC dataset encoding on the Jetson, and video streaming to the headset.
The plugin needs LeRobot 0.6.1, Linux and Python 3.12 or later on the robot’s computer. The hosted installer includes Python 3.13. The
zed camera also needs pyzed (zed.install). To add the plugin to an axol environment from the one-command installer, see the plugin README.AxolRobot
LeRobot Robot that wraps the async Axol hardware driver. A background thread runs an asyncio event loop, so motor telemetry keeps streaming while the synchronous get_observation() and send_action() calls block the calling thread.
AxolRobotConfig fields
Key methods
Frame and state timing
get_observation() picks the camera frames first, then the robot state that matches them. It never waits for a new exposure:
- It finds the newest exposure time that every camera has already delivered.
- For each camera, it takes the stored frame nearest that time. Shared-memory readers keep a short history of frames for this (
latest_capture_ts(),read_nearest(target, tolerance_s)). An in-process reader gives its newest frame. - From the realtime core’s 240 Hz state history, it takes the joint state nearest the frames’ median exposure time. FK, if enabled, runs after this.
- a camera has gone silent (its newest frame is a couple of frame periods old),
- no state samples fall on both sides of the frame time,
- the cameras and the state are too far apart in time.
AxolVRTeleop
LeRobot Teleoperator that wraps VRTeleop. It runs the VR WebSocket server and the IK process on a background thread, so get_action() doesn’t block and is safe to call from any thread.
AxolVRTeleopConfig fields
Key methods
ZedCamera
LeRobot Camera for a ZED camera attached to this computer. It opens the camera by serial number through the ZED SDK and grabs frames on a background thread. It needs pyzed (zed.install).
perf_counter clock:
capture_perf_ts: when the sensor exposed the frame (fromTIME_REFERENCE.IMAGE).receive_perf_ts: when this process retrieved it.
connect(), the camera measures the gap between the two and logs a warning if the average is outside the expected range.
ZedStereoCamera
Wrapper for a stereo ZED X. It opens one SDK connection and gets both eyes from each grab. The eyes are exposed as left_view and right_view, which have the same read methods as ZedCamera, so the rest of the pipeline treats them as ordinary cameras.
AxolRobot camera has stereo=True, its eyes setting decides the observation keys (see AxolRobotConfig.observation_cameras()):
"both": cameraXbecomesX_leftandX_right, and the dataset records both eyes. This is the default for the overhead camera."left"or"right": that eye only, under the plain nameX, so it looks like a mono camera. This is the default for wrist cameras.
stereo or eyes by hand. collect-data and run-policy call AxolRobotConfig.apply_detected_stereo(), which detects a stereo ZED X from its serial and sets eyes to "both" for the overhead camera and "left" for the others.
stream_eyes sets which eyes go to the headset, separately from what is recorded. For example, stream "both" for depth during teleop while recording only "left".
