Skip to main content

Teleoperation Datasets

Teleoperation datasets are manually recorded sim2real episodes. They synchronize the G1 state, the reference consumed by the motion tracker, optional hand and neck commands, and RealSense RGB video. This format is intended for review and external policy work; it is not a motion dataset for controller training.

Record Episodes

Recording is available only for onboard Pico sim2real deployment with an interactive terminal and a fresh RealSense stream:

pip install -e '.[recording]'
python scripts/run/run_sim2real.py --config-name sim2real_record \
controller.policy_path=policy.onnx

The equivalent manual configuration requires recording.enabled=true, input.provider=pico4, input.video.enabled=true, and input.video.source=realsense.

Use R to start an episode, S to save it, D to discard it, and Q to shut down. STANDING, MOCAP, ARMS, and paused mocap are recordable. Recording does not start without a fresh camera frame. If the camera stays stale for one second during an episode, that episode is discarded; Pico input and G1 control continue, and recording does not restart automatically when video recovers.

Dataset Layout

The recording runtime writes an editable dataset rather than one self-contained HDF5 file:

data/recordings/sim2real_hdf5/
├── schema.json
├── episodes.jsonl
├── data/
│ └── episode_000000.h5
└── videos/
└── d435i_rgb/
└── episode_000000.mp4

schema.json defines the dataset FPS, robot_type, hand_type, neck_type, and every feature's shape, dtype, names, and groups. Hardware types must match the active runtime configuration.

episodes.jsonl is the editable episode manifest. Each line maps one episode to its HDF5 and MP4 files and stores the task prompt. Task text is not copied into HDF5 attributes, so it can be edited without rewriting frame data.

Frame Fields

Each HDF5 file contains only frame-aligned arrays:

FieldShapeMeaning
frame_indexscalarCamera/action frame index
timestampscalarMonotonic timestamp in seconds
observation.state(68,)G1 joint state, base orientation/angular velocity, and projected gravity
observation.state.hand(12,), optionalLeft/right LinkerHand hardware joint readback
observation.state.neck(2,), optionalOpenNeck servo yaw/pitch readback in degrees
observation.modescalarSTANDING, MOCAP, ARMS, or paused mocap code
action(36,)Root pose plus 29-joint reference consumed by the motion tracker
action.hand(12,), optionalLeft/right LinkerHand target when hand control is enabled
action.neck(2,), optionalMechanically clamped OpenNeck yaw/pitch target in degrees

observation.state is ordered as joint_pos(29), joint_vel(29), base_quat_wxyz(4), base_ang_vel(3), and projected_gravity(3). observation.state.hand uses the LinkerHand SDK's 0-255 joint values, ordered as six left-hand channels followed by six right-hand channels. observation.state.neck is [yaw_deg, pitch_deg] returned by OpenNeck read_deg(). observation.mode uses standing=0, mocap=1, arms=2, and pause=3. action is root_pos(3) + root_quat_wxyz(4) + reference_joint_pos(29).

Camera RGB is stored only in the MP4 sidecar; HDF5 does not duplicate raw image frames. Optional state and action fields appear exactly when the corresponding hardware is enabled.

Commit and Recovery Rules

The recorder commits HDF5 and video files before appending the manifest entry. An interrupted, uncommitted episode is removed on the next recording-worker startup and does not consume an episode index. An incompatible existing schema.json stops only the non-critical recording worker, while G1 control continues.

Review Recordings

python scripts/view/view_recording.py \
--recording data/recordings/sim2real_hdf5

The reviewer validates manifest paths, HDF5 shapes, dtypes, finite values, and MP4 alignment before playback. Measured root XYZ is not recorded, so the observed robot is anchored to the reference root position; global root translation cannot be evaluated from this format.