Everything on this page travels follower to leader. The follower reports where it is and what its cameras see, and the leader receives that as a SyncedObservation. What goes the other way is an Action.

Observation

What the follower saw and where it was at one instant: one camera frame per label, plus the joints read on the same tick.
int
Identifies this instant. Counts up and never repeats, and a command carries it back so you can tell which observation the leader was acting on.
dict
One entry per camera label, each carrying that frame’s id and capture time. Identity only, no pixels: the images travel on the video track.
float
When it was captured, in milliseconds.
float
How far apart the cameras were, oldest to newest. 0.0 with fewer than two cameras.
Camera skew is recorded rather than smoothed away, so you can tell whether two cameras really described the same instant.

SyncedObservation

What the leader receives: images and joints describing the same instant, with the joints worked out for the video frame’s own capture time.
dict[str, float]
Where the follower was when that frame was taken.
dict[str, ndarray]
One decoded image per camera label. {} until video is up, which is how you know it is not ready yet.
int | None
Which observation the joints came from.
float | None
When the follower captured that frame, in milliseconds.
float
The gap between the frame and the nearest joint reading, in milliseconds. 0 means one landed on it, and anything larger is how far the joints had to be worked out.
bool
True when interpolated_ms is 0. The joints were measured, not calculated.
Several frames can share one observation_id here, so it identifies where the joints came from, not the row. Do not join a leader recording to a follower recording row by row. See Recording.

RobotState

The follower’s condition on one tick, delivered with every observation.
dict[str, float]
Read fresh every observation.
SafeState
HOLDING, ACTIVE or ESTOPPED, with reason alongside it.
dict[str, float]
Per joint, and only when your telemetry() provides them.
load and temp_c are read once a second by default, so the same value repeats until the next read. They are there to spot a motor straining or overheating, not to track it tick by tick.

Action

What the leader asked for, and what the follower actually wrote.

Sync

How joints and frames are matched to the same instant.