Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.almond.bot/llms.txt

Use this file to discover all available pages before exploring further.

Data collection runs across two machines on the same network:
  • Main host (the upper computer) — owns the dataset, runs teleop and the recording loop.
  • ZED box (the Jetson sender) — streams the three ZED-X One cameras.
Both machines must agree on the time (via PTP) so each recorded camera frame is aligned with the joint sample taken at the same instant. Each machine therefore runs two long-lived processes, each in its own terminal, that stay up for the entire session.
Start the clock-sync daemon on both machines before launching collect-data. If PTP isn’t running, the receiver’s capture/decode skew check in ZedCamera.connect() warns and recorded camera/joint pairs will not be time-aligned. See zed.sync-clocks for the PTP canary details.

Network setup

The two machines must be able to reach each other over the network. Pick the topology that matches your wiring — it determines whether you let axol assign static IPs or you point it at an existing address.
A single cable between the two NICs, no router in between. Neither machine gets a DHCP address on that link, so axol assigns static IPs for you: the ZED box takes 192.168.10.1 (via --setup-ip) and the main host takes 192.168.10.2 (via --zed_iface). The receiver’s default zed_host is already 192.168.10.1, so no IP flag is needed on collect-data.
Interface names vary by machine — the link might be eth0, enp3s0, eno1, and so on. Run ip link (or ip addr) on each machine to find the interface carrying the link, and substitute it for <iface> in the commands below. In both cases PTP runs over whichever interface carries the link (zed.sync-clocks --iface). If the two machines are not on the same L2 segment (e.g. separated by a router rather than a switch), add --transport udpv4 to the clock-sync commands.

Prerequisites

  • The lerobot extra installed on the main host: uv sync --extra lerobot (see Installation).
  • CAN set up on the main host (can.setup) and motors verified (motor.info).
  • pyzed installed on the ZED box (zed.install) and the three camera serial numbers on hand.
  • A network link between the two machines — either a direct ethernet cable or a shared router/switch (see Network setup).

ZED box (Jetson)

Open two terminals on the ZED box.
1

Start clock sync (slave)

axol zed.sync-clocks --role slave --iface <iface>
Replace <iface> with the ZED box’s link interface (find it with ip link). Leave this running for the whole session. See zed.sync-clocks for transport and timestamping options.
2

Stream the cameras

axol zed.stream \
    --overhead 12345678 \
    --left-arm 23456789 \
    --right-arm 34567890 \
    --setup-ip <iface>
--setup-ip <iface> assigns the sender IP 192.168.10.1/24 to that interface before streaming.
Streams until Ctrl+C. See zed.stream for resolution, fps, and bitrate flags.

Main host (upper computer)

Open two terminals on the main host.
1

Start clock sync (master)

axol zed.sync-clocks --role master --iface <iface>
Replace <iface> with the main host’s link interface (find it with ip link). The master role runs on the long-lived upper computer that owns the dataset. Leave it running for the whole session.
2

Run data collection

axol collect-data \
    --repo_id myorg/pick-place \
    --task "Pick the red cube and place it in the bin" \
    --zed_iface <iface>
--zed_iface <iface> assigns the receiver IP 192.168.10.2/24 to that interface; the cameras are reached at the default zed_host 192.168.10.1.
The robot is driven over VR (accept the TLS certificate first — see the Teleoperation quickstart). See collect-data for the full field list, including --fps, --teleop_hz, stiffness, and --push_to_hub, and Command configuration for the draccus override syntax.

Controller layout

Episodes are driven entirely from the Quest controllers. The movement controls are the same as in teleoperation; data collection adds the A (record) and B (mode) buttons. Quest controller diagram
#ButtonAction
1Left gripPress both grips (1 + 2) together to enable arm tracking; press either alone to disable (toggle, not hold)
2Right gripSee above
3Left triggerActuate left gripper
4Right triggerActuate right gripper
5XReset to rest pose. During a recording, stops and discards the take (re-record); during the start countdown, cancels it
6ARecord: start a take (3-second countdown), or stop and save the current take
7YExit the VR session
8BToggle between Teleop and Data Collection mode (disabled while recording or counting down)

Recording an episode

1

Enter Data Collection mode

Press B to switch from Teleop into Data Collection. You can drive the arms in either mode, but a take can only be started from Data Collection.
2

Start a take

Press A to begin recording — a 3-second countdown runs (the headset stays in Data Collection), then frame capture begins. Press A again during the countdown, or X, to cancel.
3

Finish the take

  • Press A to stop and save the episode.
  • Press X to stop and discard it (re-record).
While the episode is written to disk the headset enters the Saving state and every control except Y (exit) is blocked. When the write completes the headset returns to Data Collection and the arms move back to the rest pose, ready for the next take.
Headset stateMeaning
TeleopDriving the arms; recording not armed
Data CollectionDriving the arms; ready to record
RecordingCapturing frames to the dataset
SavingEpisode being written to disk; controls blocked
Collection resumes from an existing dataset at --root; an aborted session that saved no episodes is cleaned up on shutdown. Press Ctrl+C in the collect-data terminal to finish.
The full controller bindings and headset state machine are maintained in the axol-vr interface repo.

Next steps

Policy Inference

Run a trained policy autonomously across the same two machines.

collect-data reference

Every flag and the dataset capture internals.