wholebody-vlagr00tvlasynthetic-datawhole-bodyhumanoidlerobotisaacdreamgen

Làm synthetic data cho GR00T VLA

Các bước tạo synthetic data cho GR00T whole-body VLA, định dạng LeRobot, modality.json, training và inference cho beginner.

Nguyễn Anh Tuấn6 tháng 6, 202614 phút đọc
Làm synthetic data cho GR00T VLA

Nếu viết đúng theo tên NVIDIA, chủ đề này là GR00T với hai số 0, không phải GROOT. Nhưng trong cộng đồng robot, nhiều người vẫn gọi nhanh là "Groot". Bài này tập trung vào câu hỏi thực tế hơn: muốn làm synthetic data cho một whole-body VLA kiểu GR00T thì đi từng bước thế nào, data phải lưu ra sao, và sau đó fine-tune/inference bằng gì.

Nguồn gốc kỹ thuật gồm ba mảnh chính. Thứ nhất là paper GR00T N1: An Open Foundation Model for Generalist Humanoid Robots, mô tả VLA dual-system cho humanoid. Thứ hai là repo NVIDIA/Isaac-GR00T, nơi có data format, fine-tuning và deployment scripts. Thứ ba là NVIDIA/GR00T-Dreams và paper DreamGen, pipeline sinh synthetic robot trajectories bằng video world model rồi trích pseudo-actions để train policy.

Điểm quan trọng cho beginner: synthetic data trong GR00T không chỉ là "render thêm ảnh đẹp". Một trajectory dùng được cho VLA phải có đủ video observation, robot state, action, language instruction, episode metadata, và một file mô tả cách chia state/action theo từng modality. Nếu thiếu action hoặc state mapping, dữ liệu chỉ là video tham khảo, chưa phải dataset train policy.

Ý tưởng paper GR00T

GR00T N1 được NVIDIA giới thiệu như một open foundation model cho humanoid robot. Paper mô tả mô hình Vision-Language-Action với hai hệ thống:

  • System 2: vision-language module, nhận ảnh và language instruction để hiểu mục tiêu.
  • System 1: diffusion transformer action head, sinh motor actions theo thời gian thực.

Nói đơn giản, System 2 trả lời "mình đang nhìn thấy gì, lệnh là gì, mục tiêu nằm đâu", còn System 1 trả lời "ngay bây giờ tay, chân, thân, gripper phải di chuyển thế nào". Với whole-body VLA, System 1 không chỉ điều khiển end-effector của một cánh tay. Nó phải phối hợp body posture, hai tay, bàn tay, thậm chí chân nếu dùng controller kiểu whole-body.

Sơ đồ tối giản:

Camera frames + language + proprioception
        |
        v
+--------------------+       visual-language tokens
| System 2: VLM      | -----------------------------+
| scene + task       |                              |
+--------------------+                              v
        |                                  +---------------------+
        |                                  | System 1: DiT       |
        +---- robot state + noisy action ->| diffusion actions   |
                                           +---------------------+
                                                     |
                                                     v
                                      action chunk / latent actions
                                                     |
                                                     v
                                  robot controller / whole-body WBC

Trong các bản mới của repo Isaac-GR00T, mô hình hiện được trình bày với checkpoint N1.7 3B, nhưng tư duy data vẫn nối tiếp N1/N1.5: collect hoặc generate trajectories, chuẩn hóa về GR00T-flavored LeRobot v2, rồi fine-tune theo embodiment tag. Với whole-body humanoid như Unitree G1 + SONIC, repo mô tả hướng đi trong đó VLA dự đoán compact latent action tokens, sau đó controller whole-body giải mã thành joint commands cho chân, tay và bàn tay.

Synthetic data là gì trong GR00T-Dreams?

DreamGen/GR00T-Dreams giải quyết vấn đề đắt nhất của robot learning: thu teleoperation cho mọi hành vi và mọi môi trường. Pipeline này dùng video world model để "mơ" ra robot video mới từ một ảnh khởi tạo và text prompt, sau đó biến video thành trajectory có action.

Pipeline 4 bước:

1. Seed real robot demos
   -> vài demo thật để model hiểu embodiment và camera

2. Fine-tune video world model
   -> image-to-video model học chuyển động robot của bạn

3. Generate synthetic videos
   -> prompt: "robot hammers a peg", "robot wipes table", ...

4. Recover actions
   -> IDM / latent action model biến video thành pseudo-actions
   -> lưu thành LeRobot/GR00T dataset

Theo bài NVIDIA về synthetic trajectory data, GR00T-Dreams được dùng để sinh dữ liệu huấn luyện cho GR00T N1.5 trong khoảng 36 giờ, thay vì gần ba tháng nếu thu thủ công. Bài đó cũng nêu open Physical AI Dataset có dữ liệu real Unitree G1, 24,000 simulated teleoperation trajectories, và synthetic simulation data cho manipulation tasks. Trong trang GR00T N1.5, NVIDIA báo cáo DreamGen giúp N1.5 đạt 38.3% success rate trên 12 DreamGen tasks mới, so với 13.1% của N1. Con số này không có nghĩa synthetic data thay thế hoàn toàn robot thật, nhưng nó cho thấy neural trajectories có thể mở rộng behavior coverage khi real demos còn ít.

Data phải có những trường nào?

Một episode GR00T dùng được thường có các nhóm sau:

Nhóm Ví dụ Dùng để làm gì
Video observation.images.ego_view, observation.images.wrist_left Input thị giác cho VLA
State joint positions, gripper width, base pose, IMU, latent WBC state Proprioception, điều kiện hóa action
Action joint targets, end-effector delta, gripper command, latent action Supervision cho policy
Language "pick up the red cup", "wipe the table" Điều kiện task
Metadata episode length, fps, robot type, task index Loader, split, validation

GR00T hiện yêu cầu format tương thích LeRobot v2 kèm file bổ sung meta/modality.json. Cấu trúc thư mục nên giống:

my_groot_dataset/
  meta/
    info.json
    episodes.jsonl
    tasks.jsonl
    modality.json
  data/
    chunk-000/
      episode_000000.parquet
      episode_000001.parquet
  videos/
    chunk-000/
      observation.images.ego_view/
        episode_000000.mp4
        episode_000001.mp4
      observation.images.wrist_left/
        episode_000000.mp4
        episode_000001.mp4

Mỗi file parquet chứa dữ liệu theo timestep. Với beginner, hãy nghĩ một row là một frame điều khiển:

timestep 0:
  observation.state = [ ... float32 ... ]
  action            = [ ... float32 ... ]
  task_index        = 0

timestep 1:
  observation.state = [ ... float32 ... ]
  action            = [ ... float32 ... ]
  task_index        = 0

Video không nhét trực tiếp vào parquet. Video được lưu thành mp4 riêng theo episode. Parquet giữ numeric state/action và index language. tasks.jsonl lưu text instruction.

Ví dụ tasks.jsonl:

{"task_index": 0, "task": "pick up the red block and place it in the bowl"}
{"task_index": 1, "task": "wipe the table with the sponge"}

Ví dụ episodes.jsonl:

{"episode_index": 0, "tasks": [0], "length": 416}
{"episode_index": 1, "tasks": [1], "length": 470}

Vai trò của modality.json

modality.json là điểm nhiều người mới bị vấp. Trong parquet, observation.stateaction thường là các mảng float32 nối liền. Model không tự biết phần tử 0-6 là tay trái, phần tử 7-13 là tay phải, phần tử 14 là gripper, hay phần tử nào là latent WBC. modality.json chính là bản đồ cắt lát.

Ví dụ cho một robot hai tay đơn giản:

{
  "state": {
    "left_arm": { "start": 0, "end": 7 },
    "right_arm": { "start": 7, "end": 14 },
    "left_gripper": { "start": 14, "end": 15 },
    "right_gripper": { "start": 15, "end": 16 },
    "base": { "start": 16, "end": 19 }
  },
  "action": {
    "left_arm": { "start": 0, "end": 7 },
    "right_arm": { "start": 7, "end": 14 },
    "left_gripper": { "start": 14, "end": 15 },
    "right_gripper": { "start": 15, "end": 16 },
    "base": { "start": 16, "end": 19 }
  },
  "video": {
    "ego_view": {
      "original_key": "observation.images.ego_view"
    },
    "wrist_left": {
      "original_key": "observation.images.wrist_left"
    }
  }
}

Với whole-body VLA kiểu Unitree G1 + SONIC, action có thể không phải 29 hoặc 43 joint targets trực tiếp. Nó có thể là latent action nhỏ hơn:

{
  "state": {
    "proprio": { "start": 0, "end": 64 },
    "wbc_context": { "start": 64, "end": 96 }
  },
  "action": {
    "sonic_latent": { "start": 0, "end": 16 }
  },
  "video": {
    "ego_view": {
      "original_key": "observation.images.ego_view"
    }
  }
}

Đây là khác biệt lớn giữa "manipulation VLA" và "whole-body VLA". Nếu output là joint action trực tiếp, model phải học rất nhiều chi tiết ổn định động lực học. Nếu output là latent action cho whole-body controller, model học intent vận động ở mức cao hơn, còn controller xử lý balance, foot placement và ràng buộc động học.

Các bước làm synthetic data

Bước 1: Định nghĩa task và embodiment

Đừng bắt đầu bằng "generate thật nhiều video". Hãy bắt đầu bằng bảng task:

Field Ví dụ
Robot Unitree G1, Fourier GR-1, SO-100, dual-arm custom
Cameras ego view, left wrist, right wrist
Control rate 10 Hz policy, 50-200 Hz low-level controller
Action space joint targets, EEF delta, gripper, WBC latent
Task verbs pick, place, wipe, hammer, open, close, transfer
Success metric object in bowl, door angle, contact force, no fall

Với beginner, hãy chọn 1-3 verbs trước. Ví dụ "pick and place", "wipe", "open drawer". Synthetic data mạnh khi mở rộng biến thể object, background, camera pose, initial state; nó yếu nếu bạn prompt những hành vi quá xa seed demos.

Bước 2: Thu seed real demos

Bạn cần một ít real demos để world model và IDM hiểu embodiment. Seed demos nên gồm:

  • Video cùng camera setup sẽ dùng khi deploy.
  • State/action đồng bộ timestamp.
  • Task instruction rõ ràng.
  • Chuyển động không quá giật, ít occlusion.
  • Thành công thật, không chỉ video đẹp.

Nếu dùng Isaac Sim/Isaac Lab, bạn có thể thu simulated teleoperation hoặc scripted rollout trước. Nếu dùng robot thật, hãy log ROS bag rồi convert sang LeRobot. Điều quan trọng là timestamp phải nhất quán: frame video thứ N phải khớp state/action thứ N hoặc được resample rõ ràng.

Bước 3: Fine-tune video world model

Trong GR00T-Dreams, bước này dựa vào Cosmos Predict-2. Bạn fine-tune image-to-video model trên robot footage để model học hình dáng robot, camera viewpoint, motion prior và môi trường. Input thường là một ảnh đầu, text prompt, và output là video robot thực hiện hành vi.

Pseudo-command:

# trong repo GR00T-Dreams, theo docs Cosmos Predict-2
python train_video_world_model.py \
  --train-data /data/seed_robot_videos \
  --output-dir /checkpoints/world_model_g1 \
  --robot unitree_g1 \
  --num-gpus 8

Tên script cụ thể thay đổi theo repo version, nên khi làm thật hãy đọc cosmos-predict2/documentations/training_gr00t.md. Ý quan trọng là output của bước này chưa phải action dataset. Nó mới là model sinh video.

Bước 4: Generate synthetic videos

Bạn chuẩn bị prompts có cấu trúc:

- task: "pick up the red cup and place it on the tray"
  init_image: "scene_0001.png"
  variations:
    object_color: ["red", "blue", "green"]
    object_pose: "random_on_table"
    camera_jitter: true
    background: ["lab", "factory_bench", "kitchen_counter"]

Khi generate, nên lưu cả prompt, random seed, init image, model checkpoint và version. Sau này khi policy fail, bạn cần truy ra synthetic episode đó đến từ prompt nào.

Bước 5: Trích pseudo-actions bằng IDM

Video model chỉ sinh pixels. Policy cần actions. Vì vậy GR00T-Dreams dùng inverse dynamics model hoặc latent action model để recover action sequence từ cặp observation liên tiếp.

frame_t, frame_t+1, state_t
        |
        v
Inverse Dynamics Model
        |
        v
action_t hoặc latent_action_t

Với whole-body, bạn nên ưu tiên action representation mà controller thực thi ổn định. Nếu robot dùng WBC, hãy để IDM dự đoán latent action hoặc mục tiêu task-space, không nhất thiết dự đoán mọi torque/joint command cấp thấp. Sau đó bạn chạy validator trong sim để loại trajectory khiến robot ngã, xuyên vật thể, hoặc vi phạm joint limit.

Bước 6: Convert sang GR00T LeRobot

Khi đã có synthetic video + pseudo-action, hãy convert về cấu trúc LeRobot v2. Checklist:

  • MP4 đúng episode, đúng camera key.
  • Parquet có observation.state, action, timestamp nếu pipeline cần, task_index.
  • tasks.jsonl có language instruction.
  • episodes.jsonl có length đúng số row.
  • modality.json cắt state/action đúng index.
  • info.json ghi fps, robot type, feature schema.

Một lỗi phổ biến là action bị lệch một bước. Nếu action_t là lệnh đưa robot từ state_t sang state_t+1, hãy giữ convention đó nhất quán. Đừng trộn episode này action absolute, episode khác action delta.

Cài đặt Isaac-GR00T

Repo hiện dùng uv. Luồng cài đặt tối giản:

git clone https://github.com/NVIDIA/Isaac-GR00T
cd Isaac-GR00T
uv sync

Khi dùng dataset riêng:

uv run python gr00t/experiment/launch_finetune.py --help

Nếu data của bạn đang là LeRobot v3, repo có script convert về v2:

python scripts/lerobot_conversion/convert_v3_to_v2.py \
  --input /data/my_lerobot_v3 \
  --output /data/my_groot_lerobot_v2

Sau đó thêm meta/modality.json. Tài liệu data preparation của NVIDIA nói ngắn gọn: nếu đã có LeRobot v2, phần GR00T-specific quan trọng nhất là thêm meta/modality.json theo schema state/action/video/annotation.

Fine-tuning GR00T

Với robot mới, bạn dùng NEW_EMBODIMENT và một modality config Python. Ví dụ lệnh từ flow chính của Isaac-GR00T:

export NUM_GPUS=1
CUDA_VISIBLE_DEVICES=0 uv run python \
  gr00t/experiment/launch_finetune.py \
  --base-model-path nvidia/GR00T-N1.7-3B \
  --dataset-path /data/my_groot_dataset \
  --embodiment-tag NEW_EMBODIMENT \
  --modality-config-path examples/MY_ROBOT/my_robot_config.py \
  --num-gpus $NUM_GPUS \
  --output-dir /checkpoints/my_robot_gr00t \
  --save-total-limit 5 \
  --save-steps 2000 \
  --max-steps 2000 \
  --global-batch-size 32 \
  --color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
  --dataloader-num-workers 4

Hardware: tài liệu NVIDIA cho N1.7 khuyến nghị tối thiểu 40 GB VRAM cho fine-tuning; 1x H100/L40/A100 đủ cho demo, 4-8 GPU tốt hơn cho dataset lớn. Inference tối thiểu khoảng 16 GB VRAM, nhưng real-time whole-body nên ưu tiên GPU mạnh hoặc TensorRT.

Với beginner, đừng train quá lâu ngay lần đầu. Hãy train 500-2000 steps để kiểm tra data loader, loss, checkpoint, open-loop plot. Khi pipeline sạch rồi mới tăng data và số step.

Inference và đánh giá

Open-loop evaluation so sánh predicted action với ground truth:

uv run python gr00t/eval/open_loop_eval.py \
  --dataset-path /data/my_groot_dataset \
  --embodiment-tag NEW_EMBODIMENT \
  --model-path /checkpoints/my_robot_gr00t/checkpoint-2000 \
  --traj-ids 0 1 2 \
  --action-horizon 16 \
  --steps 400 \
  --modality-keys left_arm right_arm left_gripper right_gripper

Server-client inference cho deploy:

# Terminal 1
uv run python gr00t/eval/run_gr00t_server.py \
  --model-path /checkpoints/my_robot_gr00t/checkpoint-2000 \
  --embodiment-tag NEW_EMBODIMENT \
  --device cuda:0

# Terminal 2
uv run python gr00t/eval/open_loop_eval.py \
  --dataset-path /data/my_groot_dataset \
  --embodiment-tag NEW_EMBODIMENT \
  --host 127.0.0.1 \
  --port 5555 \
  --traj-ids 0 \
  --action-horizon 8

Với robot thật, client sẽ lấy observation từ camera/state bridge, gửi sang policy server, nhận action chunk rồi đưa vào controller. Whole-body deployment cần thêm safety layer: joint limit, velocity limit, fall detector, E-stop, collision checking, và watchdog nếu policy server chậm.

Kết quả cần đọc đúng

Các kết quả công bố nên hiểu theo ngữ cảnh:

Nguồn Kết quả chính Ý nghĩa thực tế
GR00T N1 paper/blog GR00T N1 vượt imitation baselines trên benchmark mô phỏng và GR-1 real tasks VLA generalist học tốt hơn khi có data mixture lớn
NVIDIA technical blog 750K synthetic trajectories trong 11 giờ, tương đương 6.5K giờ demo; +40% performance so với chỉ real data Synthetic simulation scale giúp tăng coverage
GR00T N1.5 page 83.0% overall success trên GR-1 language following; 38.3% trên 12 DreamGen tasks mới Grounding và DreamGen cải thiện language/novel behavior
Isaac-GR00T hardware docs N1.7 inference TensorRT đạt trên 30 Hz ở H100/RTX Pro 6000; Orin thấp hơn nhiều Chọn hardware phải theo latency thật

Đừng đọc các số này như cam kết rằng synthetic data của bạn sẽ chạy tốt ngay. Chất lượng phụ thuộc vào seed demos, camera setup, action representation, IDM, filtering và sim2real gap. Nhưng pattern đã rõ: nếu real data ít, synthetic trajectories có kiểm soát là cách hợp lý để mở rộng task verbs, object variations và environment variations.

Checklist cuối

Trước khi train nghiêm túc, hãy kiểm tra:

  • Video phát đúng, không lệch frame, không sai camera.
  • episodes.jsonl.length bằng số row parquet.
  • task_index trỏ đúng tasks.jsonl.
  • State/action dimension khớp modality.json.
  • Action convention nhất quán: absolute, delta, joint, EEF hay latent.
  • Synthetic episodes đã được filter bằng rule hoặc sim validator.
  • Train thử ít step chạy qua được.
  • Open-loop plot không nổ scale, không NaN.
  • Deploy có safety wrapper.

Nếu bạn đã quen với LeRobot data pipeline, phần khó nhất của GR00T không phải cú pháp lệnh, mà là thiết kế action/state representation đúng cho embodiment. Với whole-body VLA, nên đọc thêm về training pipeline và VLA cho humanoid để thấy vì sao controller, latency và safety quan trọng ngang model.

Bài viết liên quan

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

Software stack humanoid robot: từ ROS 2 đến VLA deployment
wholebody-vla

Software stack humanoid robot: từ ROS 2 đến VLA deployment

4/6/20265 phút đọc
NT
Fine-Tune GR00T N1.7 với EgoScale: Từ Zero đến Deploy
wholebody-vla

Fine-Tune GR00T N1.7 với EgoScale: Từ Zero đến Deploy

21/4/202612 phút đọc
NT
HEX: VLA Toàn Thân Đa Embodiment cho Humanoid
wholebody-vla

HEX: VLA Toàn Thân Đa Embodiment cho Humanoid

10/6/202610 phút đọc
NT