Timsty's picture
Add files using upload-large-folder tool
700dd75 verified
|
Raw
History Blame Contribute Delete
11.3 kB
# Motion Reference Data
This page describes the motion reference data format used by the C++ deployment stack, how to create your own reference motions, and how to verify and deploy them.
The deployment stack plays back pre-loaded **reference motions** — sequences of joint positions, velocities, and full body kinematics that the policy tracks. These motions are stored as CSV files in a structured folder hierarchy. You can generate them from any source (motion capture, simulation, retargeting pipeline, etc.) as long as the output matches the format described below.
---
## Folder Structure
Each motion dataset is a directory containing one subfolder per motion clip. The C++ reader (`MotionDataReader`) auto-discovers all subfolders at startup.
```
reference/my_motions/
├── motion_name_1/
│ ├── joint_pos.csv # Joint positions
│ ├── joint_vel.csv # Joint velocities
│ ├── body_quat.csv # Body quaternions
│ ├── body_pos.csv # Body positions
│ ├── metadata.txt # Body part indexes
│ ├── body_lin_vel.csv # Body linear velocities
│ ├── body_ang_vel.csv # Body angular velocities
│ ├── smpl_joint.csv # SMPL joint positions
│ ├── smpl_pose.csv # SMPL body poses
│ └── info.txt # Detailed motion information
└── motion_name_2/
└── ...
```
The C++ reader scans the base directory for subfolders, reads each subfolder as one motion, and validates frame-count consistency across all files in that folder.
---
## File Formats
The C++ reader loads whichever files are present and skips missing files gracefully. However, **in practice**, most policies require:
- `joint_pos.csv`, `joint_vel.csv` — for joint-based motion tracking
- `body_quat.csv` — for anchor orientation observations (the control loop will stop if this is missing when gathering observations)
- `body_pos.csv` — for heading computation and VR 3-point observations
- `metadata.txt` — for body part index alignment when body data is present
A motion must have **at least one valid data source** (joint, body, or SMPL) to load at startup.
### `joint_pos.csv`
Joint positions in **IsaacLab order** (29 joints). Each row is one timestep at 50 Hz. The first row is a header.
| Column | Description |
|--------|-------------|
| `joint_0` … `joint_28` | Joint angles in radians (IsaacLab ordering) |
Shape: `(timesteps, 29)`
### `joint_vel.csv`
Joint velocities in **IsaacLab order** (29 joints). Each row is one timestep at 50 Hz. Frame count must match `joint_pos.csv`.
| Column | Description |
|--------|-------------|
| `joint_vel_0` … `joint_vel_28` | Joint angular velocities in rad/s (IsaacLab ordering) |
Shape: `(timesteps, 29)`
### `body_pos.csv`
Body part positions in the **world frame**. Each body contributes 3 columns (x, y, z). The number of bodies varies per motion. Needed for heading computation and VR 3-point observations.
| Column | Description |
|--------|-------------|
| `body_0_x`, `body_0_y`, `body_0_z` | Position of body 0 (root/pelvis) in meters |
| `body_1_x`, `body_1_y`, `body_1_z` | Position of body 1 in meters |
| … | … |
Shape: `(timesteps, num_bodies * 3)`
**We assume the root/pelvis is always at column group 0** (the first 3 columns).
### `body_quat.csv`
Body part orientations as quaternions in the **world frame**. Each body contributes 4 columns. The quaternion ordering is **(w, x, y, z)**. **Required for most policies** — the `motion_anchor_orientation` observation (used by most policies) will fail and stop the control system if this file is missing.
| Column | Description |
|--------|-------------|
| `body_0_w`, `body_0_x`, `body_0_y`, `body_0_z` | Quaternion of body 0 (root/pelvis) |
| `body_1_w`, `body_1_x`, `body_1_y`, `body_1_z` | Quaternion of body 1 |
| … | … |
Shape: `(timesteps, num_bodies * 4)`
**We assume the root/pelvis is always at column group 0** (the first 4 columns).
```{note}
The number of bodies in `body_quat.csv` can differ from `body_pos.csv`. The C++ reader tracks them independently (`num_bodies` vs `num_body_quaternions`). However, the root body (first column group) must be present for heading computation to work. You can use zero if you don't need root pos.
```
### `metadata.txt`
Contains the **body part indexes** array, which maps each column group in `body_pos.csv` / `body_quat.csv` to the corresponding IsaacLab body index. This is needed when body data is present.
```
Metadata for: motion_name
==============================
Body part indexes:
[ 0 4 10 18 5 11 19 9 16 22 28 17 23 29]
Total timesteps: 497
```
The C++ reader parses `Body part indexes:` followed by a line of space-separated integers in brackets. For example, `[0, 4, 10, 18, ...]` means column group 0 → IsaacLab body 0 (pelvis/root), column group 1 → body 4, etc.
For a **root-only** motion (only 1 body), use:
```
Body part indexes:
[0]
```
### `body_lin_vel.csv` / `body_ang_vel.csv`
Body part linear and angular velocities in the world frame. Same layout as `body_pos.csv` (3 columns per body). The number of bodies must match `body_pos.csv`.
### `smpl_joint.csv`
SMPL joint positions (typically 24 joints × 3 coordinates). Each row is one timestep.
Shape: `(timesteps, num_smpl_joints * 3)`
### `smpl_pose.csv`
SMPL body poses in axis-angle representation (typically 21 poses × 3 coordinates). Each row is one timestep.
Shape: `(timesteps, num_smpl_poses * 3)`
```{note}
The **current reference motion tracking pipeline uses joint-based tracking only** (encoder mode 0). To enable SMPL-based reference tracking (encoder mode 2), you would need to modify the code to detect the presence of SMPL data and switch the encoder mode accordingly.
```
### `info.txt`
Human-readable summary with shapes, dtypes, and value ranges. Not read by the C++ stack — purely for documentation.
---
## Creating Your Own Reference Motions
You can generate reference motions from any source — the only requirement is producing CSV files in the format above. Common approaches:
1. **Motion capture retargeting** — retarget human mocap to the G1 model, export joint positions/velocities and body kinematics.
2. **Simulation recording** — record joint states from an IsaacLab or MuJoCo simulation at 50 Hz.
3. **Procedural generation** — programmatically create joint trajectories.
### Minimal Files Needed
The **minimum** set of files to create a working motion for SONIC policy:
1. **`joint_pos.csv`** — 29 joint positions (IsaacLab order), header + one row per timestep
2. **`joint_vel.csv`** — 29 joint velocities (IsaacLab order), header + one row per timestep
3. **`body_quat.csv`** — Root quaternion (w, x, y, z), header + one row per timestep
4. **`body_pos.csv`** — Root position (x, y, z), header + one row per timestep. You can use all zeros if you don't need position tracking.
5. **`metadata.txt`** — Body part indexes (just `[0]` for root-only)
**Example files:**
`joint_pos.csv`:
```
joint_0,joint_1,joint_2,...,joint_28
0.128441,0.102713,0.020116,...,0.045231
0.130124,0.104532,0.021045,...,0.046112
...
```
`joint_vel.csv`:
```
joint_vel_0,joint_vel_1,...,joint_vel_28
0.143671,0.143864,...,0.012345
...
```
`body_quat.csv` (root quaternion only):
```
body_0_w,body_0_x,body_0_y,body_0_z
0.999123,0.000456,0.001234,0.040567
...
```
`body_pos.csv` (root position, can be all zeros):
```
body_0_x,body_0_y,body_0_z
0.000000,0.000000,0.000000
...
```
`metadata.txt`:
```
Metadata for: my_motion
==============================
Body part indexes:
[0]
Total timesteps: 100
```
This gives you a **root-only** motion (1 body = pelvis/root) that most policies can track.
### Provided Conversion Script
A convenience script `reference/convert_motions.py` is included for converting **joblib pickle** (`.pkl`) files to this format. This is just one possible source — you can use any tool or pipeline that produces the correct CSV output.
```bash
cd gear_sonic_deploy
python reference/convert_motions.py <pkl_file> [output_dir]
```
The pickle should be a dictionary where each key is a motion name and each value contains `joint_pos`, `joint_vel`, `body_pos_w`, `body_quat_w`, `body_lin_vel_w`, `body_ang_vel_w`, `_body_indexes`, and `time_step_total`.
---
## Verifying Reference Motions
### MuJoCo Visualization
Use the included visualizer to check that the motion looks correct on the G1 model:
```bash
cd gear_sonic_deploy
python visualize_motion.py --motion_dir reference/my_motions/motion_name_1/
```
**Controls:**
- **Space**: Pause / resume playback
- **R**: Reset to frame 0
- **,** / **.**: Step backward / forward one frame
- **-** / **=**: Previous / next motion (if multiple loaded)
Verify that:
- The robot stands upright and does not clip through the floor
- Joint angles look reasonable (no extreme poses)
- The motion plays smoothly without sudden jumps
- Body positions track the expected trajectory
---
## Using Reference Motions
### With `deploy.sh`
Pass the motion directory via `--motion-data`:
```bash
./deploy.sh --motion-data reference/my_motions/ sim
```
Or use the default motions (configured in `deploy.sh`):
```bash
./deploy.sh sim
```
### At Runtime
Once deployed, use the keyboard or gamepad to browse and play motions:
- **T**: Play current motion
- **N / P**: Next / Previous motion
- **R**: Restart from frame 0
See the [Keyboard tutorial](../tutorials/keyboard.md) for the full control reference.
---
## Validation Rules
The C++ reader enforces the following during loading:
- **Frame count consistency**: All CSV files within a motion folder must have the same number of rows (excluding headers). Mismatches cause the motion to be skipped with an error.
- **Joint count consistency**: `joint_pos.csv` and `joint_vel.csv` must have the same number of columns.
- **Body count consistency**: `body_lin_vel.csv` and `body_ang_vel.csv` must have the same number of body columns as `body_pos.csv`.
- **At least one data source**: A motion must have at least some valid data (joint, body, or SMPL) to be loaded.
- **Metadata parsing**: The `metadata.txt` file must contain a `Body part indexes:` line followed by a bracketed list of integers for the motion to have correct body-part alignment.
If a motion fails validation, it is skipped and a warning is printed. The deployment continues with the remaining valid motions.
---
## Notes
- All data is at **50 Hz** (0.02 s per timestep), matching the control loop frequency.
- Joint ordering follows **IsaacLab convention** (not MuJoCo). The C++ stack handles the conversion internally when sending motor commands.
- Body quaternions use **(w, x, y, z)** ordering.
- The first body (column group 0) must correspond to the root/pelvis for heading computation and anchor orientation observations to work correctly.
- While the C++ reader can load motions without `body_quat.csv`, the control loop will fail during observation gathering if the policy observes `motion_anchor_orientation` (which most policies do).
- CSV files must have a **header row** as the first line — the C++ reader skips the first line of every CSV.
- Values are parsed as `double` precision internally.