Motion data#
Motion libraries for WBC tracking live under `data/<robot>/<dataset_name>/`.
Tip
First time? Convert the bundled samples and train with Wbc-G1 — see
Quickstart: install → convert → train → play. Errors like empty npz/:
Troubleshooting.
A small `samples/` folder is version-controlled under each robot (e.g.
g1/samples/) with a few clips from public datasets for smoke tests. All other
dataset folders stay local — download full libraries from Hugging Face (see robot
guides) or convert your own clips.
Only READMEs, samples/, and .gitkeep placeholders are version-controlled;
other clip and bundle files stay gitignored.
Robot guides#
Robot |
Guide |
|---|---|
g1 (in-tree example) |
|
Directory layout#
data/<robot>/<dataset>/
*.csv / *.pkl # source clips (or under raw/)
npz/<clip>.npz # per-clip exports (source of truth for training)
<dataset>.npz # optional cached stack (--cache-motion-bundle)
Put source clips in the dataset folder or in `raw/` — converters prefer
raw/when it contains.csvor.pklfiles.`npz/` and `*.npz` are never committed — run
wbc-mjlab-data-to-npzafter adding source clips.`<dataset>.npz` is optional: written only when you pass `–cache-motion-bundle` on train/play.
`params/motion_library.yaml` is written automatically on play from the loaded motion bundle.
Per-clip NPZ schema#
wbc-mjlab-data-to-npz writes one .npz per source clip under npz/.
MotionCommand / MotionLoader load either a directory of those clips or a
pre-stacked bundle.
Required arrays (time axis T, joints J, bodies B):
Key |
Shape / meaning |
|---|---|
|
Scalar or length-1 array — export rate (default 50 Hz) |
|
|
|
|
|
|
|
|
|
|
|
|
Bodies B follow the robot model body order from FK. Training selects a
keybody subset via MotionCommandCfg.body_names (robot entity / preset).
Optional stacked bundle (--cache-motion-bundle) concatenates clips and stores
segment start/length metadata so RSI can sample across the library.
Sagittal mirroring (--mirror)#
Bilateral humanoids often benefit from left-right mirrored reference motion: it doubles the motion library without new mocap and improves left/right generalization during RSI sampling.
Pass --mirror to wbc-mjlab-data-to-npz to export an extra NPZ per source
clip:
data/g1/samples/npz/
walk1_subject1.npz
walk1_subject1_mirror.npz # sagittal mirror of walk1_subject1
Training discovers both files automatically (npz/*.npz). No train/play flag
is required.
What gets mirrored#
Mirroring runs after FK on the exported arrays (motion/motion_mirror.py):
Channel |
Transform |
|---|---|
|
Swap left/right joint pairs; negate roll/yaw axes (see robot symmetry config) |
|
Swap left/right bodies; flip world y (reflection across the XZ plane) |
|
Swap bodies; negate quaternion x and z |
|
Swap bodies; negate x and z components (axial vector under reflection) |
|
Unchanged |
The robot’s `RobotSymmetryConfig`` defines joint swap pairs and signs.
G1 ships in-tree at robots/g1/symmetry.py. Extension robots register their
own config (see The robot entity and Extension packages).
CLI notes#
--mirrorrequires a symmetry config for--robot; otherwise conversion errors.Mirrored output stem:
<clip_stem><mirror_suffix>(default suffix_mirror).Sources whose stem already ends with the mirror suffix are skipped (avoids
walk_mirror_mirror.npzon re-convert).
uv run wbc-mjlab-data-to-npz --robot g1 --dataset samples --batch-size 8 --mirror
Online mirroring during training (phase 2) will reuse the same symmetry config
inside MotionCommand; offline --mirror is the recommended starting point.
Supported formats#
Source layouts are defined in wbc_mjlab.motion.motion_formats. The converter
infers format from the file extension; pass --format to pick a registered name.
Format key |
Extension |
Role |
|---|---|---|
|
|
LAFAN / retarget CSV (no header, m + quat xyzw + rad) |
|
|
GMR / |
NPZ |
train / play |
Per-clip exports or a pre-stacked training bundle |
Comma-separated rows, no header:
root_pos(3) + root_rot_xyzw(4) + joint_pos(n_dof) # meters, radians
Joint count must match the target robot. Default input rate is 30 Hz unless
--input-fps is set.
Python dict with at least:
fps, root_pos (T×3), root_rot (T×4, xyzw), dof_pos (T×n_dof)
Optional keys: joint_names, dof_joint_names, or joint_order.
Workflow#
# 1. Add clips under data/<robot>/<dataset>/
uv run wbc-mjlab-data-to-npz --robot <robot> --dataset <dataset>
# large libraries: parallel FK on GPU
uv run wbc-mjlab-data-to-npz --robot <robot> --dataset <dataset> --batch-size 8
# optional: sagittal mirror (doubles npz/ — see "Sagittal mirroring" above)
uv run wbc-mjlab-data-to-npz --robot g1 --dataset samples --mirror
# 2. Train
uv run wbc-mjlab-train --task Wbc-<Robot> --dataset <dataset>
# 3. Optional cached bundle
uv run wbc-mjlab-train --task Wbc-<Robot> --dataset <dataset> --cache-motion-bundle
--batch-size N runs N parallel FK workers on GPU. Use --batch-size 1 for --render preview.
Conversion requires `–robot`` (MuJoCo asset). Train/play use `–task`` (robot inferred).
Train / play motion source#
Flag |
Resolves to |
|---|---|
|
|
|
load |
|
that file directly |
|
explicit NPZ path |
|
write/read |
Version control#
Everything under data/ is gitignored except READMEs, samples/, and
.gitkeep files. See the repository .gitignore.