SONIC-K1: whole-body motion tracking for the Booster K1
🌐 Project page & videos · 📄 Paper · ▶ Try it in 2 minutes · 💻 Code · 🤖 Run it on a K1 · 🧱 K1 USD
The first open-weights motion tracker for small humanoids. One policy, thousands of human motions. SONIC-K1 ports NVIDIA's SONIC motion-tracking recipe to the 22-DoF Booster K1. We trained it from scratch on 10K clips with under 1% of SONIC's training compute.
v1.0 (November 2026): tested on a real Booster K1. v1.0 is trained for the real robot: Booster's deploy torque limits on the legs and 0–40 ms of control latency. Under real-robot torque limits and 40 ms of latency it finishes 96.6% of unseen motions (v0.1: 76.7%). It runs on the K1's onboard computer with the open robot app. v0.1 stays available in
v0.1/.
| Tested on hardware | Booster K1, onboard computer, Booster SDK (robot app) |
| Success on 1,985 unseen motions, SONIC's rule (MuJoCo) | 97.4% |
| Same, real-robot torque limits + 40 ms latency | 96.6% (v0.1: 76.7%) |
| PHUMA, SONIC's rule (SONIC on G1: 97.2%) | 92.3%; with 40 ms latency 91.7% (v0.1: 78.0%) |
| Local joint-position error, unseen (MPJPE-L, MuJoCo) | 17.1 mm |
| Training motions | 9,991 Bones-SEED clips, retargeted to K1 (clip list) |
| Compute | ~110 GPU-hours in total (under 1.5% of SONIC's >9,000): 50,000 PPO iterations + a 4,000-iteration real-robot fine-tune |
What's in this repo
| File | What it is |
|---|---|
onnx/policy_g1.onnx |
Start here. Fused robot-motion tracker: K1 reference motion + proprioception → 22 joint actions |
onnx/model_encoder.onnx, onnx/model_decoder.onnx |
The same policy split SONIC-style: encoder → 64-D token → decoder |
onnx/policy_teleop.onnx |
Fused teleop-mode tracker |
onnx/observation_config.yaml |
Exact input layout of every ONNX file |
k1_plant.json |
Joint order (IsaacLab ↔ MuJoCo), PD gains, effort limits, action scales, default pose |
sonic_k1_v1_actor.pt |
Actor-only PyTorch weights, 25.1M params (Isaac Lab eval / fine-tuning) |
config.yaml |
Resolved training config (must sit next to the .pt) |
bones_seed_splits.csv |
The Bones-SEED clips used: 9,991 for training, 1,985 held out for testing (names only, no motion data) |
release.json |
Hashes, git commit, versions, training summary, eval numbers |
v0.1/ |
The first release (iteration 50,000): same file layout |
LICENSE, NOTICE |
CC BY-NC 4.0 for these weights + third-party notices |
Code, training configs, the MuJoCo player and the robot app: github.com/Kyk0/sonic-k1.
Quick start (MuJoCo, no GPU needed)
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 --filter=blob:none --sparse https://github.com/Kyk0/sonic-k1 && cd sonic-k1
git sparse-checkout set gear_sonic/scripts examples/k1 gear_sonic/data/assets/robot_description # ~30 MB instead of ~1 GB
pip install mujoco onnxruntime numpy "imageio[ffmpeg]" huggingface_hub
hf download Kyry10/sonic-k1 onnx/policy_g1.onnx k1_plant.json --local-dir checkpoints/sonic-k1
python gear_sonic/scripts/play_k1.py # live viewer (macOS: mjpython)
python gear_sonic/scripts/play_k1.py --record demo.mp4
Ten sample motions (shadow boxing, jumps, lunges and more, recorded from SONIC-K1 itself) ship with the code. Batch evaluation: see the GitHub README.
On the real robot
bash sonic_k1_deploy/make_kit.sh sonic_k1_kit # code + these weights + K1 model + sample motions
scp -r sonic_k1_kit booster@<robot-ip>:~/
ssh booster@<robot-ip> 'cd sonic_k1_kit && ./run.sh --dry-run' # then ./run.sh, robot in a belt
A motion menu: pick a clip, press g, the robot plays it and goes to DAMPING at the end. SPACE damps at any moment
(also any gamepad button or Ctrl+C), with upright, fall, joint-speed and latency guards. Full guide:
sonic_k1_deploy/README.md.
You bring the motion. Retarget any human clip (SMPL/BVH) to K1 with
UMR, starting from its Booster K1 example config (our settings: docs/k1/data.md in the GitHub repo),
then convert it with gear_sonic/data_process/convert_k1_npz_to_motion_lib.py.
Policy interface
| Robot | Booster K1, 22 actuated DoF (official K1_22dof.xml, BoosterRobotics/booster_assets) |
| Control | 50 Hz policy, 200 Hz physics. q* = default + action_scale · clip(a, ±20), PD τ = kp(q*−q) − kd·q̇, clamped to effort limits |
policy_g1.onnx input [1, 1220] |
motion command 440 (10 future frames at 0.1 s: joint pos 10×22 | joint vel 10×22) | anchor orientation 60 (10 × first two columns of R(q_robot⁻¹·q_ref)) | actor obs 720 |
| Actor obs 720 | 10-step history, oldest first, term-major: base ang vel 3 | joint pos − default 22 | joint vel 22 | last action 22 | gravity dir 3 (body frame) |
| Encoder / decoder | encoder [1, 1611] → token [1, 64]; decoder [1, 784] = token 64 | actor obs 720 → action [1, 22] |
| Output | 22 actions in IsaacLab joint order (listed below) |
| ONNX parity | ≈1e-5 (float32) on 384/400 MuJoCo clips (median 2e-6); 15 clips show one isolated FSQ token flip (~1 step in 400). Closed loop with ONNX driving the robot: same success and MPJPE as PyTorch (96.5%, 17.8 mm) |
Joint order: head_yaw, L/R shoulder_pitch, L/R hip_pitch, head_pitch, L/R shoulder_roll, L/R hip_roll, L/R elbow_pitch,
L/R hip_yaw, L/R elbow_yaw, L/R knee_pitch, L/R ankle_pitch, L/R ankle_roll. Exact names are in k1_plant.json.
| Joints | kp | kd | Effort (N·m), v1.0 = Booster deploy limits | Action scale |
|---|---|---|---|---|
| head / arms | 3.95 | 0.25 | 6 / 14 | 0.38 / 0.89 |
| hip pitch | 30.2 | 3.61 | 30 (v0.1: 68) | 0.56 |
| hip roll | 21.4 | 2.56 | 35 (v0.1: 76) | 0.89 |
| hip yaw | 17.8 | 2.13 | 20 (v0.1: 38.3) | 0.54 |
| knee | 60.4 | 4.81 | 40 (v0.1: 112) | 0.46 |
| ankle pitch / roll | 35.7 | 4.26 | 20 (v0.1: 38.3) | 0.27 |
Default pose: all zeros except shoulder roll ∓1.3 rad. Gains follow Booster's formula, kp = armature·(2π·4 Hz)², with
action_scale = 0.25·effort/kp (computed from the v0.1 limits, so v0.1 and v1.0 share one action space).
The SMPL encoder mode exists in the graph but is untrained; use mode 0 (robot motion).
Training
- Recipe: SONIC (GR00T-WholeBodyControl) universal-token tracker, with the same PPO settings, decoder MLP [4096, 4096, 2048, 2048, 1024, 1024, 512, 512], future-frame horizon and adaptive sampling as the release config.
- K1 changes:
- K1 robot config and joint maps;
- an extra head-joint tracking term (the K1 has an actuated head);
- pushes and COM randomization scaled ×0.7 for the smaller robot;
- mass randomization 0.9–1.3;
- initial action std 0.5.
- v1.0 real-robot fine-tune (from v0.1, iteration 50,000 → 54,000; config
sonic_k1_legs, robot typek1_real):- leg and ankle torque capped at Booster's deploy limits (30 / 35 / 20 / 40 / 20 N·m);
- every joint command delayed by a random 0–40 ms per episode, ramped in from 0 over the first 2,000 iterations;
- kp and kd randomized ×U(0.9, 1.1) per episode;
- a penalty on PD torque demand above 90% of the limit;
- same observations, actions, rewards and data as v0.1, all 9,991 clips loaded.
- Data: 9,991 clips from Bones-SEED, retargeted to K1 at 60 fps with UMR. The clips are QA-filtered (joint limits,
foot penetration, velocity spikes) and tagged for K1 feasibility (no waist, no wrists, 0.93 m). The exact clip list
and the held-out test split are in
bones_seed_splits.csv. - Compute: v0.1: 16,384 parallel environments on one H100 NVL, 50,000 iterations, ~100 GPU-hours, trained from scratch, seed 0, no NVIDIA checkpoint. v1.0 fine-tune: 16,384 environments on one RTX PRO 6000, 4,000 iterations, ~9 GPU-hours.
- Setup: headless, physics-only Isaac Lab, following our Isaac Lab on H100 guide. The K1 USD used is at Kyry10/booster-k1-usd.
- Software: Isaac Sim 5.1.0, Isaac Lab 0.54.4, torch 2.7.0+cu128, trl 0.28.0, accelerate 1.15.0, hydra-core 1.3.2, mujoco 3.13.0, onnx 1.22.0, onnxruntime 1.20.1, numpy 1.26.4.
Evaluation
Unseen = 1,985 held-out Bones-SEED clips never used in training. Seen = 2,000 training clips. Deterministic actions. v0.1 and v1.0 were run with the same code on the same clips.
MuJoCo sim-to-sim, all clips (different physics engine, explicit PD, 5 ms steps, 10 s clips). Real-robot = Booster deploy torque limits + sensor noise + the given command latency. SONIC's rule / official-like rule, MPJPE-L over successful clips:
| Condition | Unseen, v0.1 | Unseen, v1.0 | Seen, v0.1 | Seen, v1.0 |
|---|---|---|---|---|
| Nominal | 97.5% / 92.0%, 15.4 mm | 97.4% / 91.5%, 17.1 mm | 98.7% / 97.2% | 98.4% / 96.8% |
| Real-robot, 20 ms | 95.5% / 85.9%, 18.1 mm | 97.1% / 90.6%, 17.6 mm | 97.4% / 92.3% | 98.0% / 96.4% |
| Real-robot, 40 ms | 76.7% / 58.5%, 21.2 mm | 96.6% / 89.1%, 18.2 mm | 78.3% / 59.6% | 97.9% / 95.1% |
PHUMA (the SONIC paper's external benchmark; HF release, 2,000 motions stratified over its 15 sources, G1 → K1 robot
retarget, 1,758 pass QA; MuJoCo, --no-terminate). SONIC's rule / official-like, MPJPE-L, joint jerk:
| Condition | v0.1 | v1.0 |
|---|---|---|
| Nominal | 93.8% / 84.9%, 22.6 mm, 312 | 92.3% / 81.7%, 25.2 mm, 296 |
| Real-robot, 20 ms | 92.2% / 83.1%, 22.8 mm, 544 | 92.2% / 81.0%, 25.1 mm, 446 |
| Real-robot, 40 ms | 78.0% / 68.9%, 23.9 mm, 1252 | 91.7% / 79.4%, 25.4 mm, 459 |
Isaac Lab, official repo eval (height, orientation, end-effector and foot-position limits), both checkpoints with Booster's torque limits, unseen = full-length clips:
| Set | v0.1 | v1.0 |
|---|---|---|
| Unseen 1,985, no latency | 92.3%, MPJPE-L 15.3 mm | 90.7%, 17.0 mm |
| Unseen 1,985, 40 ms latency | 70.4%, 16.1 mm | 89.4%, 16.9 mm |
| Seen 2,000 (10 s), no latency | 98.1%, 15.4 mm | 97.3%, 16.6 mm |
v1.0 trades about 1.5 mm of tracking accuracy at zero latency for robustness to the latency and torque limits of the
real robot. Every number is in release.json.
These numbers are on a Bones-SEED hold-out split, not the paper's AMASS test set, and the K1 is ~0.7× the G1's size. Don't compare millimetres with G1 or X2 results.
v0.1 evaluation (iteration 50,000, first release)
Isaac Lab, 10 s windows, 2,000 parallel envs, deterministic actions, v0.1 robot model.
| Rule | Unseen success | Seen success |
|---|---|---|
| Official repo eval (height, orientation, end-effector and foot-position limits) | 93.1% | 98.5% |
| Same, without the strict foot-position term | 97.9% | 98.8% |
| No-fall rule (root height ±0.25 m, tilt < 1 rad) | 98.7% | 98.8% |
Unseen tracking error, over successful clips as in SONIC/PHC: MPJPE-L 14.7 mm, PA-MPJPE 10.8 mm, MPJPE-G 84.9 mm. Over all clips: 15.5 / 11.4 / 85.8 mm. Legs 17.4 mm, hands and head 11.7 mm, feet 18.7 mm.
Over training (same 1,985 unseen clips, official rule): 85.8% at 8.4K it, 90.4% at 18K, 92.2% at 29K, 93.1% at 50K.
Full-length clips (no 10 s cut): 98.6% paper rule / 93.4% official, MPJPE-L 15.0 mm. Teleop mode (head + hands targets with lower-body joints): 98.7% / 93.4%, MPJPE-L 15.1 mm. PHUMA: 93.6% under SONIC's rule, 97.3% no-fall, 85.0% official-like; MPJPE-L 22.4 mm. 100STYLE (100 locomotion styles × forward walk/run, 200 clips × 20 s, MuJoCo): 99.0% under SONIC's rule, MPJPE-L 22.5 mm. MuJoCo, all 1,985 unseen (10 s): 98.4% paper rule / 91.9% official-like, MPJPE-L 16.6 mm, PA 12.4 mm.
All v0.1 numbers are in v0.1/release.json.
Comparison with published trackers (indicative)
Success without a fall on unseen motions. Other methods run on the Unitree G1 as published, with their own retargeting and protocols.
All rows use the SONIC paper's success rule: a rollout fails if the root or an end-effector height deviates by more than 0.25 m. Ours are in MuJoCo with --no-terminate.
| Benchmark | SONIC-K1 v1.0 (ours, K1; run by us) | SONIC (G1)* | BeyondMimic (G1)* | Any2Track (G1)* |
|---|---|---|---|---|
| PHUMA (1,758 clips, G1→K1) | 92.3% | 97.2% | 73.8% | 78.5% |
| Held-out mocap (ours: 1,985 Bones-SEED; SONIC: in-house test-content) | 97.4% | 98.5% | 82.0% | 61.6% |
* Reported in the SONIC paper (Luo et al., arXiv 2511.07820); we did not rerun these methods. They run on the Unitree G1 with their own data and retargeting, so this comparison is indicative. SONIC-K1 is the first open-weights general motion-tracking model for the Booster K1.
Coming soon
- Real Booster K1 runs: v1.0 runs on the physical robot (videos coming)
- Deployment controller: an open runtime for the Booster SDK (sonic_k1_deploy)
- Whole-body teleoperation: drive the K1 live from a VR headset
- Video to K1: SMPL/video input, so you can film a move and the K1 does it
- A bigger model: trained on 62K motions (6× more)
Intended use
Non-commercial research and education on humanoid whole-body control. Not for safety-critical, hazardous or commercial deployment. On hardware, start in a safety belt with a hand on the damping key.
License and attribution
- These weights: CC BY-NC 4.0 (non-commercial, required by the training-data license).
- Code: Apache-2.0 (fork of NVlabs/GR00T-WholeBodyControl).
- Robot model: BoosterRobotics/booster_assets, BSD-3-Clause.
- NVIDIA: this model was trained from scratch with SONIC's open-source code and does not include NVIDIA weights.
NOTICElinks the NVIDIA Open Model License for reference.
Training data includes Motion Data by Bones Studio (https://bones.studio/).
Use of the underlying dataset is subject to the BONES Motion Capture Dataset License Agreement.
No motion data, raw or retargeted, is distributed here. bones_seed_splits.csv lists clip names only.
Citation
@misc{kolesnichenko2026sonick1,
title = {{SONIC-K1}: Porting a Universal Humanoid Motion Tracker to a Small Humanoid on a Single {GPU}},
author = {Kolesnichenko, Kyrylo and Cardenas, Irvin Steve and Kim, Jong-Hoon},
year = {2026},
eprint = {2610.39327},
archivePrefix = {arXiv},
primaryClass = {cs.RO}
}
@article{luo2025sonic,
title = {SONIC: Supersizing Motion Tracking for Natural Humanoid Whole-Body Control},
author = {Luo, Zhengyi and Yuan, Ye and Wang, Tingwu and Li, Chenran and Chen, Sirui and Casta\~neda, Fernando and Cao, Zi-Ang and Li, Jiefeng and Minor, David and Ben, Qingwei and Da, Xingye and Ding, Runyu and Hogg, Cyrus and Song, Lina and Lim, Edy and Jeong, Eugene and He, Tairan and Xue, Haoru and Xiao, Wenli and Wang, Zi and Yuen, Simon and Kautz, Jan and Chang, Yan and Iqbal, Umar and Fan, Linxi and Zhu, Yuke},
journal = {arXiv preprint arXiv:2511.07820},
year = {2025}
}
Acknowledgements
Thanks to NVIDIA GEAR for open-sourcing SONIC, to Bones Studio for Bones-SEED, to the UMR authors for the retargeter, and to Booster Robotics for the K1 models. Compute: ATR Lab.
- Downloads last month
- 72