Trong bài 1, chúng ta đã xem SONIC như một policy điều khiển toàn thân dùng nhiều encoder và một không gian token chung. Trong bài 2, chúng ta đi từ checkpoint sang MuJoCo sim2sim và Isaac Lab eval. Bài 3 quay lại phần thường bị bỏ qua nhưng quyết định chất lượng policy: dữ liệu đi vào training.
Mục tiêu của bài này là giúp bạn đọc được pipeline dữ liệu thật trong repo NVlabs/GR00T-WholeBodyControl. Ta sẽ đi từ BONES-SEED ở dạng Unitree G1 CSV và SOMA BVH, chuyển sang motion_lib PKL bằng gear_sonic/data_process/convert_soma_csv_to_motion_lib.py và extract_soma_joints_from_bvh.py, lọc motion bằng filter_and_copy_bones_data.py, rồi cấu hình training với +exp=manager/universal_token/all_modes/sonic_release hoặc +exp=manager/universal_token/all_modes/sonic_bones_seed.
Nếu bạn là beginner, đừng cố train model lớn ngay. Hãy xem bài này như bản đồ dữ liệu: file nào chứa gì, tại sao phải downsample 120 fps xuống 30 fps, vì sao có motion_file, smpl_motion_file, soma_motion_file, và vì sao filtering loại khoảng 8,7% trong hơn 142K motion.
Nếu muốn đọc rộng hơn về bối cảnh dữ liệu whole-body trước khi đi vào script, bạn có thể mở thêm whole-body VLA data pipeline và bài GR00T whole-body SONIC training/export. Hai bài đó không thay thế tài liệu chính thức của NVlabs, nhưng giúp nối phần retargeting, dữ liệu người và export policy với workflow robotics thực tế.
Nguồn kỹ thuật nên mở song song:
| Nguồn | Dùng để kiểm tra gì |
|---|---|
| SONIC Training Guide | Lệnh convert, filter, train, eval, training với SOMA encoder |
| Training Data docs | Thống kê BONES-SEED, format SOMA/BVH và Unitree G1 CSV |
| Data process scripts | Ba script chuyển đổi/lọc dữ liệu trong repo |
| BONES-SEED trên Hugging Face | Dataset gốc, license, cấu trúc tải xuống |
| GEAR-SONIC project page | Bối cảnh universal control policy và scaling |
1. BONES-SEED đóng vai trò gì trong SONIC?
BONES-SEED là dataset motion capture lớn dành cho humanoid robotics. Tài liệu training data của GR00T-WBC mô tả dataset này có 142.220 motion gồm 71.132 motion gốc và 71.088 motion mirror, tổng thời lượng khoảng 288 giờ ở 120 fps, đến từ 522 diễn viên. Dữ liệu có mô tả ngôn ngữ tự nhiên, nhãn temporal segmentation, metadata skeleton, và nhiều format đầu ra.
Với SONIC, điểm quan trọng không chỉ là số lượng motion. BONES-SEED cung cấp motion ở ba dạng phù hợp với pipeline humanoid:
| Format | Ý nghĩa trong pipeline |
|---|---|
| SOMA Proportional BVH | Skeleton giữ tỷ lệ cơ thể từng actor, hữu ích cho nghiên cứu motion người |
| SOMA Uniform BVH | Skeleton chuẩn hóa, thuận tiện cho xử lý batch |
| Unitree G1 CSV | Joint trajectory đã retarget sang G1, tương thích MuJoCo, đi thẳng vào motion tracking robot |
SONIC học từ nhiều representation. sonic_release dùng ba encoder chính: G1 robot motion, teleop và SMPL. sonic_bones_seed mở rộng thêm encoder thứ tư cho SOMA skeleton. Vì vậy, cùng một motion trong BONES-SEED có thể xuất hiện ở nhiều vai trò: G1 CSV cho robot encoder, SMPL PKL cho human encoder, và SOMA BVH sau xử lý cho SOMA encoder.
Đây là điểm beginner hay nhầm: motion_lib không phải "một file dataset chung". Trong repo, motion_file, smpl_motion_file, và soma_motion_file là ba đường vào khác nhau cho ba dạng reference khác nhau. Nếu chỉ có G1 CSV đã convert, bạn chưa có SMPL data. Nếu chỉ extract BVH sang SOMA joints, bạn chưa có robot dof trajectory cho robot encoder.

2. Thư mục dữ liệu nên được tổ chức thế nào?
Tài liệu training khuyến nghị đặt dữ liệu đã xử lý ở repo root. Với pipeline đầy đủ, mental model nên là:
GR00T-WholeBodyControl/
├── data/
│ ├── motion_lib_bones_seed/
│ │ ├── robot/ # PKL từ Unitree G1 CSV, trước khi lọc
│ │ ├── robot_filtered/ # PKL G1 sau khi lọc, khoảng 130K motion
│ │ ├── soma/ # PKL từ SOMA BVH, trước khi lọc
│ │ └── soma_filtered/ # PKL SOMA sau khi lọc, khớp subset robot
│ └── smpl_filtered/ # PKL SMPL human motion đã xử lý
├── gear_sonic/
└── sonic_release/
Với quick test, bạn có thể dùng sample_data/robot_filtered và sample_data/smpl_filtered tải từ Hugging Face. Với training nghiêm túc, bạn dùng full dataset. Điều cần giữ nhất quán là các path trong Hydra override phải trỏ đến thư mục đúng format. motion_file không nên trỏ vào BVH. soma_motion_file không nên trỏ vào G1 CSV. Các script convert tạo PKL riêng cho từng motion và giữ cấu trúc session để sau này filter/copy dễ hơn.
3. Chuyển Unitree G1 CSV sang motion_lib PKL
Script chính cho G1 CSV là:
python gear_sonic/data_process/convert_soma_csv_to_motion_lib.py \
--input /path/to/bones_seed/g1/csv/ \
--output data/motion_lib_bones_seed/robot \
--fps 30 \
--fps_source 120 \
--individual \
--num_workers 16
Tên script có chữ soma_csv, nhưng nó hỗ trợ nhiều input mode, bao gồm Bones-SEED flat CSV. Với mode BONES-SEED, mỗi CSV là một motion, thường nằm trong các session directory. --individual yêu cầu script ghi từng motion thành một file .pkl riêng, thay vì gộp tất cả vào một dict PKL lớn. Đây là cách phù hợp với dataset 142K motion vì dễ resume, dễ filter, và dễ copy theo session.
Nội dung script đáng chú ý:
| Bước trong script | Chi tiết thực tế |
|---|---|
| Đọc CSV | Cột root_translateX/Y/Z, root_rotateX/Y/Z, và 29 cột joint kết thúc bằng _dof |
| Đổi đơn vị | Root translation từ cm sang m; joint angle từ độ sang radian |
| Root rotation | Euler xyz theo độ được đổi sang quaternion |
| Joint order | Bones-SEED CSV đã ở thứ tự MuJoCo/MJCF actuator, nên script gắn joint_order="mj" |
pose_aa |
Tạo axis-angle cho 29 DoF G1 bằng trục joint hardcode |
| Output | root_trans_offset, pose_aa, dof, root_rot, smpl_joints placeholder, fps |
Hai chi tiết quan trọng cho người mới:
Thứ nhất, --fps_source 120 --fps 30 không phải tham số trang trí. BONES-SEED gốc ở 120 fps, trong khi pipeline training ví dụ dùng 30 fps. Script dùng stride-based frame skipping: 120 xuống 30 là lấy mỗi 4 frame. Khi source fps chia hết cho target fps, cách này đơn giản và giữ số frame khớp với BVH nếu cả hai format bắt đầu từ cùng source.
Thứ hai, smpl_joints trong output G1 CSV là placeholder bằng zero. Điều này không biến robot PKL thành SMPL PKL. Nó chỉ giữ schema tương thích với motion_lib. Human encoder vẫn cần smpl_motion_file riêng.
Một file PKL robot motion sau convert về cơ bản chứa trajectory robot:
motion_name:
root_trans_offset: (T, 3) # root/pelvis translation, meters
root_rot: (T, 4) # root quaternion
dof: (T, 29) # G1 joint positions, radians
pose_aa: (T, 30, 3) # pelvis + 29 actuated joints as axis-angle
fps: 30
4. Vì sao phải lọc khoảng 8,7% motion?
Sau khi convert, docs yêu cầu lọc motion:
python gear_sonic/data_process/filter_and_copy_bones_data.py \
--source data/motion_lib_bones_seed/robot \
--dest data/motion_lib_bones_seed/robot_filtered \
--workers 16
Tài liệu nói bước này loại các motion mà G1 không thể hoặc không nên thực hiện, ví dụ tương tác với đồ nội thất, phương tiện, động tác nhào lộn, bề mặt cao. Kết quả là loại khoảng 8,7% motion; nói cách khác, từ 142K motion còn khoảng 130K motion để train. Nếu lấy mốc 142.220 motion, 8,7% tương đương khoảng 12.000 motion bị loại. Đây là lọc thực dụng, không phải đánh giá đạo đức hay chất lượng mocap.
Điểm cần hiểu: filter_and_copy_bones_data.py là keyword filter trên tên file/đường dẫn, không phải một classifier động học đọc từng frame rồi quyết định robot có làm được hay không. Script đi qua các thư mục session, tìm .pkl, tạo name_to_check từ parent folder và basename, rồi loại nếu tên chứa keyword mặc định. Nó giữ lại metadata.pkl, copy file qua destination, và in summary tổng số file tìm thấy, số copy, số bị lọc.
Danh sách keyword mặc định cho thấy tư duy lọc:
bed, bike, chair, climb, sitting, table, ladder, crutch,
scooter, acrobatics_, cartwheel, handstand, stair,
box_jump, walking_on_edge, push_obstacle, ...
Vì sao loại các motion này?
| Nhóm bị lọc | Lý do thực dụng |
|---|---|
| Ghế, giường, bàn | Motion phụ thuộc object/surface không có trong môi trường training cơ bản |
| Xe đạp, scooter | Kinematics người gắn với phương tiện, không phù hợp G1 đứng tự do |
| Cầu thang, box cao, bề mặt cao | Cần contact geometry đặc biệt, dễ tạo reference không khả thi |
| Handstand, cartwheel, acrobatics | Yêu cầu contact tay, va chạm và biên actuator rất khác locomotion thông thường |
| Crutch, push obstacle | Phụ thuộc vật thể ngoài và lực tương tác chưa được mô phỏng đúng |
Bạn có thể chạy --dry-run để xem trước số lượng bị lọc mà chưa copy. Nếu bạn đang train robot embodiment khác hoặc muốn giữ một nhóm motion riêng, script có --add-keywords để thêm keyword loại bỏ. Nó cũng có --filter_file để dùng include keyword list: khi có include list, file phải vừa không dính keyword loại bỏ, vừa có keyword được include.
5. Extract SOMA joints từ BVH
Nếu bạn dùng sonic_release, bạn chưa cần SOMA encoder. Nhưng nếu muốn training mở rộng với sonic_bones_seed, bạn cần thêm soma_motion_file. Script tương ứng là:
python gear_sonic/data_process/extract_soma_joints_from_bvh.py \
--input /path/to/bones_seed/bvh/ \
--output data/motion_lib_bones_seed/soma \
--fps 30 \
--num_workers 16 \
--skip_existing
Sau đó lọc để subset SOMA khớp với robot data:
python gear_sonic/data_process/filter_and_copy_bones_data.py \
--source data/motion_lib_bones_seed/soma \
--dest data/motion_lib_bones_seed/soma_filtered \
--workers 16
Script BVH làm nhiều việc hơn vẻ ngoài của lệnh. Nó parse hierarchy và motion section của BVH, tính forward kinematics, rồi chọn 26 joint SOMA quan trọng: hips, spine, chest, neck, head, shoulder, arm, forearm, hand, một số finger joint để định hướng bàn tay, leg, shin, foot và toe. Root Hips được dùng làm mốc để trừ translation toàn cục, khiến soma_joints thành vị trí body-local. Sau đó script đổi hệ trục từ Y-up sang Z-up theo mapping (x, y, z) -> (x, -z, y), đổi cm sang m, downsample về 30 fps, và lưu PKL.
Một entry SOMA PKL chứa:
motion_name:
soma_joints: (T, 26, 3) # Z-up, meters, body-local
soma_root_quat: (T, 4) # wxyz
soma_transl: (T, 3) # hips world position
fps: 30
joint_names: [26 SOMA joint names]
So với robot PKL, SOMA PKL không chứa 29 G1 dof. Nó chứa skeleton joint positions người. Đó là lý do nó đi vào soma_motion_file chứ không thay cho motion_file.
6. Chọn sonic_release hay sonic_bones_seed
Tài liệu training nêu rõ khác biệt:
| Config | Encoder | Khi nào dùng |
|---|---|---|
sonic_release |
G1, teleop, SMPL | Mặc định, khớp released checkpoint; dùng cho finetune/eval thông thường |
sonic_bones_seed |
G1, teleop, SMPL, SOMA | Training mở rộng với SOMA skeleton encoder từ BVH |
Nếu bạn mới bắt đầu, dùng sonic_release. Nó ít biến hơn, khớp checkpoint release, và đủ cho phần lớn workflow eval/finetune. Khi bạn đã chuẩn bị được soma_filtered và hiểu BVH/SOMA representation, hãy chuyển sang sonic_bones_seed.
Lệnh train cơ bản với sample data:
python gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/all_modes/sonic_release \
num_envs=16 headless=True \
++manager_env.commands.motion.motion_lib_cfg.motion_file=sample_data/robot_filtered \
++manager_env.commands.motion.motion_lib_cfg.smpl_motion_file=sample_data/smpl_filtered
Lệnh train với full robot và SMPL data:
python gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/all_modes/sonic_release \
num_envs=4096 headless=True \
++manager_env.commands.motion.motion_lib_cfg.motion_file=data/motion_lib_bones_seed/robot_filtered \
++manager_env.commands.motion.motion_lib_cfg.smpl_motion_file=data/smpl_filtered
Finetune từ released checkpoint:
python gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/all_modes/sonic_release \
+checkpoint=sonic_release/last.pt \
num_envs=4096 headless=True \
++manager_env.commands.motion.motion_lib_cfg.motion_file=data/motion_lib_bones_seed/robot_filtered \
++manager_env.commands.motion.motion_lib_cfg.smpl_motion_file=data/smpl_filtered
Training với SOMA encoder:
accelerate launch \
--multi_gpu --num_machines=8 --num_processes=64 \
--machine_rank=$MACHINE_RANK \
--main_process_ip=$MASTER_ADDR \
--main_process_port=$MASTER_PORT \
gear_sonic/train_agent_trl.py \
+exp=manager/universal_token/all_modes/sonic_bones_seed \
num_envs=4096 headless=True \
++manager_env.commands.motion.motion_lib_cfg.motion_file=data/motion_lib_bones_seed/robot_filtered \
++manager_env.commands.motion.motion_lib_cfg.smpl_motion_file=data/smpl_filtered \
++manager_env.commands.motion.motion_lib_cfg.soma_motion_file=data/motion_lib_bones_seed/soma_filtered
Hydra syntax ở đây quan trọng. +exp=... chọn experiment config. ++manager_env.commands.motion.motion_lib_cfg.motion_file=... override field sâu trong config. Nếu bạn viết sai tên field, có thể Hydra tạo field mới hoặc báo lỗi tùy cấu hình, nhưng policy sẽ không dùng dữ liệu bạn nghĩ. Với beginner, hãy copy nguyên đường dẫn key trước, chỉ thay value.
7. Monitoring: biết training có đang đi đúng hướng không
Docs training đưa vài metric thực dụng:
| Metric | Mốc tốt | Cách hiểu |
|---|---|---|
rewards/total |
3.0+ |
Tổng reward imitation/tracking đang đủ cao |
rewards/anchor_pos_err |
< 0.15 m |
Sai số root/anchor không quá lớn |
rewards/body_pos_err |
< 0.10 m |
Sai số body position đang hội tụ |
throughput/fps |
khoảng 4000+ |
Tốc độ rollout/training đủ hợp lý |
time_out |
> 0.90 |
Episode thường kết thúc tự nhiên thay vì early termination |
Checkpoint được lưu theo chu kỳ trong:
logs_rl/TRL_G1_Track/<experiment_name>-<timestamp>/
├── model_step_002000.pt
├── config.yaml
└── ...
Khi eval checkpoint, xem lại bài 2: success_rate > 0.97, mpjpe_l < 30 mm, mpjpe_g < 200 mm là các mốc cơ bản từ docs. Một policy hội tụ tốt có thể đạt hơn 0,98 success rate và dưới 29 mm mpjpe_l sau khoảng 100K iterations theo tài liệu. Nhưng đừng nhìn metric đơn lẻ: render vài video để xem foot sliding, jitter, early termination và motion có khớp ngữ nghĩa không.

8. Checklist lỗi thường gặp
| Triệu chứng | Nguyên nhân hay gặp | Cách xử lý |
|---|---|---|
| Train báo không thấy motion | Path override sai hoặc trỏ sai format | Kiểm tra motion_file, smpl_motion_file, soma_motion_file |
| Số frame robot và SOMA lệch nhiều | Downsample hoặc source fps không nhất quán | Dùng --fps_source 120 --fps 30 cho CSV và --fps 30 cho BVH |
| Motion load được nhưng tracking xấu | Data không lọc, có furniture/acrobatics/surface đặc biệt | Chạy filter và thử subset nhỏ trước |
| GPU hết VRAM | num_envs quá cao |
Giảm num_envs xuống 16/32/128 để debug |
| Eval release checkpoint đọc path lạ | Config checkpoint chứa path nội bộ | Override motion path bằng path local như sample/full data |
| SOMA training không chạy | Dùng sonic_release nhưng set soma_motion_file, hoặc thiếu soma_filtered |
Chuyển sang sonic_bones_seed và chuẩn bị BVH PKL |
Một nguyên tắc tốt: trước khi train hàng nghìn environment, hãy convert vài session, filter dry-run, replay reference motion, rồi mới scale. Data pipeline robotics rất dễ sai ở đơn vị cm/m, độ/radian, hệ trục Y-up/Z-up, thứ tự joint và fps. SONIC đã có script xử lý những việc đó; nhiệm vụ của bạn là dùng đúng input mode và path.
9. Kết luận
Training SONIC không bắt đầu từ train_agent_trl.py. Nó bắt đầu từ việc chuẩn hóa motion data. BONES-SEED CSV của G1 đi qua convert_soma_csv_to_motion_lib.py để thành robot motion_lib PKL. BONES-SEED BVH đi qua extract_soma_joints_from_bvh.py để thành SOMA skeleton PKL. Cả hai nên được lọc bằng filter_and_copy_bones_data.py để loại những motion phụ thuộc object, surface hoặc contact quá đặc biệt, giảm khoảng 8,7% dữ liệu và giữ lại khoảng 130K motion phù hợp hơn cho G1 tracking.
Sau đó, lựa chọn config trở nên rõ ràng: sonic_release cho workflow mặc định G1/teleop/SMPL; sonic_bones_seed khi bạn thật sự thêm SOMA encoder. Ba path quan trọng cần nhớ là motion_file, smpl_motion_file, và soma_motion_file. Khi ba path này đúng, phần còn lại của training dễ debug hơn nhiều.
Trong bài 4, chúng ta sẽ đi sang phía runtime: ONNX encoder/decoder, ZMQ protocol, C++ deployment loop và những điểm cần kiểm tra trước khi nghĩ đến robot thật.



