wholebody-vlagrootvlawhole-body-vlareal-robotteleopunitree-g1sonic

GR00T whole-body VLA data: có cần data real?

Phần 3 của series GR00T whole-body VLA data pipeline: khi nào cần data real, thu VR teleop với SONIC, export LeRobot, mix real/sim/public và deploy.

Nguyễn Anh Tuấn6 tháng 6, 202613 phút đọc
GR00T whole-body VLA data: có cần data real?

GR00T whole-body VLA data: có cần data real?

Disclosure: Bài viết có thể chứa affiliate/referral links. Nếu bạn mua hoặc đăng ký qua các link đó, VnRobo có thể nhận commission hoặc credit. Nội dung kỹ thuật ưu tiên tính đúng và khả năng chạy được.

Phần 1 dùng open dataset. Phần 2 dùng sim data. Phần 3 trả lời câu hỏi thực tế nhất: có cần data real không?

Câu trả lời ngắn:

  • Nếu mục tiêu là học format, debug loader, chạy open-loop: không cần real data.
  • Nếu mục tiêu là demo trong simulator hoặc task sim-to-sim: sim + public có thể đủ.
  • Nếu mục tiêu là chạy humanoid thật với camera thật, latency thật, contact thật, lighting thật: gần như chắc chắn cần data real hoặc ít nhất real calibration/eval data.

Với whole-body VLA kiểu Unitree G1 + GEAR-SONIC, data real thường đi qua workflow:

VR teleop + SONIC deploy + camera server
  -> data exporter
  -> GR00T-LeRobot dataset
  -> process/clean/merge
  -> fine-tune Isaac-GR00T
  -> PolicyServer
  -> SONIC inference client + C++ deploy

3.1 Khi nào cần data real?

Mục tiêu

Quyết định có nên đầu tư vào real data collection hay chưa. Thu data real đắt, rủi ro và chậm; nhưng bỏ qua nó quá lâu sẽ khiến policy fail khi ra robot.

Khi sim/public có thể đủ

Bạn có thể chưa cần data real nếu:

  • Bạn chỉ muốn verify GR00T-LeRobot format.
  • Bạn đang viết converter, loader, training script.
  • Task chỉ chạy trong Isaac Lab / IsaacLab-Arena.
  • Camera/object distribution giống dataset public.
  • Controller/action space còn đang thay đổi.
  • Robot thật chưa có safety rig, E-stop, current limit, camera sync.

Ở giai đoạn này, mục tiêu không phải "robot chạy được", mà là:

dataset loads
training starts
checkpoint saves
open-loop predicts action
server-client pipeline responds

Khi bắt buộc phải có real data

Bạn nên thu real data khi thấy một trong các dấu hiệu:

Dấu hiệu Vì sao sim/public không đủ
Camera thật khác sim Lens distortion, exposure, motion blur, rolling shutter, timestamp lệch.
Contact task Grasp, push, carry, door, drawer rất nhạy với friction và compliance.
Whole-body balance Base sway, foot slip, torso motion khác sim.
Wrist/hand khác dataset Hand joint mapping và gripper affordance lệch.
Latency lớn Sim không phản ánh camera server, ZMQ, policy server, C++ deploy loop.
Object/domain mới Public dataset không có vật, scene, pose, lighting tương tự.

Với humanoid, sim-to-real gap không chỉ là ảnh. Nó còn là:

  • controller latency,
  • joint backlash,
  • IMU drift,
  • foot-ground contact,
  • hand compliance,
  • camera placement,
  • operator style,
  • action scaling.

Quy tắc ra quyết định

Nếu task không có contact thật:
  public + sim + domain randomization có thể đủ lâu hơn.

Nếu task có grasp/carry/push hoặc robot phải đi trong không gian thật:
  cần real data sớm.

Nếu policy trong sim tốt nhưng real robot fail ngay ở approach:
  kiểm tra camera calibration + latency trước khi đổ lỗi model.

Nếu policy approach được nhưng fail khi grasp/contact:
  cần real data cho final interaction.

3.2 Thu data real với VR teleop + SONIC

Mục tiêu

Thu demonstration trên robot thật hoặc sim loop bằng GR00T-WholeBodyControl, xuất thành LeRobot dataset có:

outputs/<timestamp>-G1-robot01/
├── data/
│   ├── train-00000.parquet
│   └── ...
├── videos/
│   ├── observation.images.ego_view/
│   │   └── episode_000000.mp4
│   ├── observation.images.left_wrist/
│   └── observation.images.right_wrist/
└── meta/
    ├── info.json
    ├── modality.json
    ├── episodes.jsonl
    └── tasks.jsonl

Theo docs GR00T-WholeBodyControl, data exporter chạy cùng SONIC deployment và VR teleop stack, capture robot state, SMPL teleop pose và camera images. Camera server chạy onboard robot computer, thường là Jetson Orin, và publish JPEG frames qua ZMQ.

Yêu cầu môi trường

Robot/onboard:

  • Unitree G1 hoặc embodiment tương thích stack bạn dùng.
  • Jetson Orin hoặc robot computer kết nối camera.
  • OAK camera là setup được docs nói test/support; RealSense/USB webcam có driver nhưng cần kiểm chứng vì docs nói chưa test gần đây.
  • Network ổn định giữa robot và workstation.
  • E-stop vật lý, giới hạn current/torque, safety area.

Workstation:

  • Ubuntu/Debian.
  • CUDA Toolkit.
  • Repo NVlabs/GR00T-WholeBodyControl.
  • Python env cho data collection, teleop, inference.
  • PICO VR nếu dùng VR whole-body teleop.

Training GPU:

  • Debug: 1x GPU 48-80 GB VRAM.
  • Production-ish whole-body fine-tune: 4+ GPUs 80 GB recommended theo tinh thần GEAR workflow.
  • Inference PolicyServer: 1 GPU đủ load checkpoint; VRAM phụ thuộc model/checkpoint/inference mode.

Clone và cài data collection env

Trên workstation:

git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
cd GR00T-WholeBodyControl

bash install_scripts/install_data_collection.sh

Script này tạo .venv_data_collection và cài LeRobot, PyAV, OpenCV, các dependency data exporter.

Setup camera server trên robot

SSH vào robot/onboard computer:

git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
cd GR00T-WholeBodyControl

bash install_scripts/install_camera_server.sh

Kiểm tra service:

sudo systemctl status composed_camera_server.service
journalctl -u composed_camera_server.service -f

Nếu không dùng systemd, chạy camera server thủ công theo README/script của repo. Cần kiểm chứng command cụ thể theo camera driver.

Launch data collection all-in-one

Trên workstation:

python gear_sonic/scripts/launch_data_collection.py \
  --camera-host 192.168.123.164 \
  --task-prompt "pick up the soda can and place it in the bin"

Nếu muốn record wrist cameras:

python gear_sonic/scripts/launch_data_collection.py \
  --camera-host 192.168.123.164 \
  --task-prompt "pick up the soda can and place it in the bin" \
  --record-wrist-cameras

Tên flag wrist camera cần kiểm chứng bằng:

python gear_sonic/scripts/launch_data_collection.py --help

Docs mô tả all-in-one tmux launcher mở bốn pane:

Pane 0: C++ Deploy
Pane 1: PICO Teleop
Pane 2: Data Exporter
Pane 3: Camera Viewer

Trong buổi thu data, mỗi episode nên có:

  • Task prompt rõ ràng, một hành động chính.
  • Start pose giống nhau vừa đủ để học, nhưng không quá cứng.
  • Success/fail marking nhất quán.
  • Không giữ frame khi operator pause lâu.
  • Không để robot mất balance hoặc va chạm mạnh.

Số lượng episode

Theo VLA workflow docs, nên thu ít nhất 50-100 demonstrations cho target task để fine-tune ổn hơn. Thực tế:

Task Số episode khởi đầu
Pick object đơn giản 50-100
Pick-and-place với nhiều pose 100-300
Mobile manipulation có approach 200-500
Multi-object / long horizon 500+ và nên chia subtask

Đừng thu 500 episode lỗi. 80 episode sạch thường tốt hơn 300 episode lẫn fail không annotation.

Post-process real dataset

Mục tiêu

Loại bỏ discarded episodes, stale SMPL frames, frame drop và session không cùng config.

Chạy trong data collection env:

source .venv_data_collection/bin/activate

python gear_sonic/scripts/process_dataset.py \
  --dataset-path outputs/2026-04-03-14-30-00-G1-robot01 \
  --output-path outputs/my_task_cleaned

Merge nhiều session:

python gear_sonic/scripts/process_dataset.py \
  --dataset-path outputs/session1 outputs/session2 outputs/session3 \
  --output-path outputs/my_task_merged

Hoặc dùng list file:

cat > datasets.txt <<'TXT'
outputs/session1
outputs/session2
outputs/session3
TXT

python gear_sonic/scripts/process_dataset.py \
  --dataset-list datasets.txt \
  --output-path outputs/my_task_merged

Nếu chỉ muốn merge, không remove stale SMPL:

python gear_sonic/scripts/process_dataset.py \
  --dataset-list datasets.txt \
  --output-path outputs/my_task_merged_no_clean \
  --no-remove-stale-smpl

Thông thường không nên dùng --no-remove-stale-smpl trừ khi bạn biết rõ stale detector làm mất data hợp lệ.

Verify dataset sau post-process

cd Isaac-GR00T
export REAL_DATASET=/abs/path/to/GR00T-WholeBodyControl/outputs/my_task_cleaned

uv run python tools/verify_groot_lerobot_dataset.py "$REAL_DATASET"
python -m json.tool "$REAL_DATASET/meta/modality.json" | head -120

Kiểm tra video:

find "$REAL_DATASET/videos" -name "*.mp4" | head -5
ffprobe "$(find "$REAL_DATASET/videos" -name '*.mp4' | head -1)"

Kiểm tra parquet:

uv run python - <<'PY'
from pathlib import Path
import pandas as pd
root = Path("$REAL_DATASET")
p = sorted((root / "data").rglob("*.parquet"))[0]
df = pd.read_parquet(p)
print(p)
print(df.head())
print(df.columns.tolist())
PY

Lưu ý: trong heredoc trên, shell sẽ không expand $REAL_DATASET vì dùng quote đơn nếu copy nguyên. Cách chắc hơn:

uv run python -c "from pathlib import Path; import os, pandas as pd; root=Path(os.environ['REAL_DATASET']); p=sorted((root/'data').rglob('*.parquet'))[0]; df=pd.read_parquet(p); print(p); print(df.head()); print(df.columns.tolist())"

Train với real data

Trước khi train, chạy preflight giống Phần 1:

cd Isaac-GR00T

uv run python gr00t/experiment/launch_finetune.py --help | \
  grep -E "dataset|embodiment|modality|base-model|max-steps|num-gpus"

test -d "$REAL_DATASET"
test -f "$REAL_DATASET/meta/modality.json"
python -m json.tool "$REAL_DATASET/meta/modality.json" >/tmp/real_modality.pretty.json

UNITREE_G1_SONIC

cd Isaac-GR00T

export NUM_GPUS=4
export REAL_DATASET=/abs/path/to/outputs/my_task_cleaned
export MODALITY_CONFIG=gr00t/configs/data/embodiment_configs.py
export OUT=/mnt/checkpoints/groot_g1_sonic_real_my_task

test -f "$MODALITY_CONFIG"

uv run torchrun --nproc_per_node=$NUM_GPUS --master_port=29500 \
  gr00t/experiment/launch_finetune.py \
  --base-model-path nvidia/GR00T-N1.7-3B \
  --dataset-path "$REAL_DATASET" \
  --embodiment-tag UNITREE_G1_SONIC \
  --modality-config-path "$MODALITY_CONFIG" \
  --num-gpus $NUM_GPUS \
  --output-dir "$OUT" \
  --save-total-limit 5 \
  --save-steps 5000 \
  --max-steps 20000 \
  --use-wandb \
  --global-batch-size 32 \
  --color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
  --dataloader-num-workers 4

NEW_EMBODIMENT

Nếu robot/action schema không phải SONIC latent:

export NUM_GPUS=1
export REAL_DATASET=/abs/path/to/outputs/my_task_cleaned
export MODALITY_CONFIG=/abs/path/to/configs/my_robot_config.py
export OUT=/mnt/checkpoints/groot_new_embodiment_real_my_task

test -f "$MODALITY_CONFIG"

CUDA_VISIBLE_DEVICES=0 uv run python \
  gr00t/experiment/launch_finetune.py \
  --base-model-path nvidia/GR00T-N1.7-3B \
  --dataset-path "$REAL_DATASET" \
  --embodiment-tag NEW_EMBODIMENT \
  --modality-config-path "$MODALITY_CONFIG" \
  --num-gpus $NUM_GPUS \
  --output-dir "$OUT" \
  --save-total-limit 3 \
  --save-steps 1000 \
  --max-steps 5000 \
  --global-batch-size 4 \
  --dataloader-num-workers 2

Mix real + sim + public

Khi nào mix?

Mix Dùng khi
Real only Task nhỏ, domain rất cụ thể, đã có 100+ demo sạch.
Real + sim Muốn tăng pose/object/lighting diversity nhưng vẫn anchor vào robot thật.
Real + public Public cùng embodiment/action schema, giúp regularize.
Real + sim + public Task cần generalization, nhưng phải đảm bảo schema/action space giống nhau.

Tỉ lệ bắt đầu

Giai đoạn Tỉ lệ
Ít real data, sim tốt 30% real / 70% sim
Real data đã có 100-300 demo 60% real / 40% sim/public
Deployment thật đang fail ở contact 80% real / 20% sim/public
Public dataset khác task nhưng cùng embodiment 10-30% public để regularize

Nếu schema giống nhau, dùng script merge ở Phần 2:

cat > mix_real_sim_public.txt <<'TXT'
/abs/path/to/outputs/my_task_cleaned
/abs/path/to/datasets/g1_pick_place_lerobot
/abs/path/to/datasets/arena_g1_loco/lerobot
TXT

uv run python tools/merge_groot_lerobot_datasets.py \
  --dataset-list mix_real_sim_public.txt \
  --output-dir datasets/g1_mix_real_sim_public

Nếu modality.json khác nhau, không merge trực tiếp. Bạn cần:

  1. Convert tất cả về cùng action/state schema.
  2. Hoặc train riêng từng stage:
base GR00T
  -> fine-tune sim/public
  -> continue fine-tune real
  -> deploy/evaluate

Continue fine-tune command cần kiểm chứng theo version repo; thường sẽ dùng --base-model-path /path/to/previous/checkpoint thay vì base Hugging Face model.

Inference trên robot thật

Start PolicyServer

Trên GPU machine:

cd Isaac-GR00T

uv run python gr00t/eval/run_gr00t_server.py \
  --model-path /mnt/checkpoints/groot_g1_sonic_real_my_task/checkpoint-20000 \
  --embodiment-tag UNITREE_G1_SONIC \
  --device cuda:0 \
  --port 5550

Run inference client + SONIC

Từ GR00T-WholeBodyControl:

python gear_sonic/scripts/launch_inference.py \
  --policy-host <gpu_machine_ip> \
  --policy-port 5550 \
  --camera-host 192.168.123.164 \
  --prompt "pick up the soda can and place it in the bin"

Manual setup nếu không dùng tmux:

Terminal 1:

cd Isaac-GR00T
uv run python gr00t/eval/run_gr00t_server.py \
  --model-path /path/to/checkpoint \
  --embodiment-tag UNITREE_G1_SONIC \
  --device cuda:0 \
  --port 5550

Terminal 2:

cd GR00T-WholeBodyControl/gear_sonic_deploy
./deploy.sh --input-type zmq_manager real

Terminal 3:

cd GR00T-WholeBodyControl
python gear_sonic/scripts/launch_inference.py \
  --policy-host <gpu_machine_ip> \
  --policy-port 5550 \
  --camera-host <robot_camera_host> \
  --prompt "pick up the object"

Safety checklist trước khi chạy real robot

  • E-stop hoạt động và người vận hành đứng gần.
  • Không có người trong vùng motion.
  • Test --sim trước real.
  • Bắt đầu với prompt đơn giản, object nhẹ.
  • Giới hạn tốc độ/torque nếu controller hỗ trợ.
  • Log camera/state/action ngay cả khi inference.
  • Có rollback checkpoint cũ.

Lỗi thường gặp và cách fix

Lỗi Nguyên nhân Fix
Camera server không có frame Sai IP, camera service chết, firewall journalctl -u composed_camera_server.service -f, ping robot, kiểm tra port ZMQ.
Frame delay lớn Network yếu hoặc encode quá nặng Dùng Ethernet, giảm resolution/fps, tách camera host.
Stale SMPL frames VR stream pause/drop Chạy process_dataset.py, loại episode lỗi.
Data có nhiều failed demos Operator marking không nhất quán Tách success/fail, bỏ fail khỏi first fine-tune.
Policy server action shape sai Sai embodiment tag hoặc checkpoint Dùng đúng UNITREE_G1_SONIC vs NEW_EMBODIMENT; kiểm tra checkpoint config.
Real robot đứng im Client không publish action hoặc deploy không subscribe Kiểm tra ZMQ ports, gear_sonic_deploy, topic/action manager.
Robot mất ổn định Action scale/latency/safety issue Dừng ngay, test sim, giảm speed, kiểm tra SONIC/deploy config.
Training overfit real data Ít episode, scene quá giống nhau Mix sim/public, augment lighting/camera, collect thêm pose/object.

Tiêu chí "đã làm đúng"

Bạn đã làm đúng Phần 3 nếu:

  • Camera server chạy ổn trên robot.
  • Data collection launcher mở đủ deploy/teleop/export/viewer.
  • Dataset output có data, videos, meta.
  • process_dataset.py clean được data.
  • verify_groot_lerobot_dataset.py pass.
  • Fine-tune chạy qua ít nhất vài nghìn step không NaN.
  • PolicyServer load checkpoint.
  • Inference sim chạy trước real.
  • Real robot chạy task nhỏ với safety limit trước khi tăng độ khó.

Tổng kết toàn pipeline

Nguồn data Download/collect Format Train Infer Khi dùng
Public/open hf download ... --repo-type dataset Verify meta/modality.json, data, videos launch_finetune.py --dataset-path <public> open_loop_eval.py hoặc run_gr00t_server.py Học format, baseline, regularization.
Sim Isaac Lab / IsaacLab-Arena / Mimic / scripted rollout Convert HDF5/trajectory -> GR00T-LeRobot Sim-only hoặc mix public Sim inference trước, real sau nếu gap nhỏ Scale data rẻ, randomization, task exploration.
Real VR teleop + SONIC + camera server GR00T-WholeBodyControl exporter -> process/merge Real-only hoặc continue from sim/public checkpoint PolicyServer + SONIC deploy Deployment thật, contact, camera/latency/robot-specific behavior.
SONIC controller Bones-SEED / SMPL / SOMA / robot motion Convert/filter sang motion_lib PKL gear_sonic/train_agent_trl.py trong Isaac Lab Export ONNX -> C++ deploy Cần controller/motion foundation mới hoặc embodiment mới.

Checklist cuối series

[ ] Chọn embodiment/action space: UNITREE_G1_SONIC hay NEW_EMBODIMENT
[ ] Dataset có meta/info.json
[ ] Dataset có meta/episodes.jsonl
[ ] Dataset có meta/tasks.jsonl
[ ] Dataset có meta/modality.json
[ ] Parquet có observation.state/action đúng dim
[ ] Video key trong modality khớp videos/
[ ] Verify script pass
[ ] Fine-tune smoke test 100-500 step pass
[ ] Checkpoint save đúng
[ ] Open-loop eval không NaN/shape mismatch
[ ] PolicyServer load được checkpoint
[ ] Sim inference pass trước real
[ ] Nếu dùng UNITREE_G1_SONIC, đã có SONIC checkpoint/ONNX/deploy path kiểm chứng
[ ] Không trộn raw joint action với SONIC latent action trong cùng dataset
[ ] Real safety checklist pass
[ ] Log real rollout để cải thiện vòng sau

Bài viết liên quan

Nguồn

NT

Nguyễn Anh Tuấn

Robotics & AI Engineer. Building VnRobo — sharing knowledge about robot learning, VLA models, and automation.

Khám phá VnRobo

Bài viết liên quan

GR00T whole-body VLA data: dùng open dataset
wholebody-vla

GR00T whole-body VLA data: dùng open dataset

6/6/202613 phút đọc
NT
GR00T whole-body VLA: train SONIC controller
wholebody-vla

GR00T whole-body VLA: train SONIC controller

6/6/20269 phút đọc
NT
GR00T whole-body VLA data: sinh data sim
wholebody-vla

GR00T whole-body VLA data: sinh data sim

6/6/202614 phút đọc
NT