humanoidhumanoidvlawhole-bodygrootunitree-g1architecturedecoupled-control

GR00T N1 + Unitree G1: kiến trúc WBC+VLA decoupled từ 6Hz đến 500Hz

Hiểu cách GR00T N1 (VLA 6Hz) kết hợp với GR00T-WBC (200Hz) để điều khiển Unitree G1 — kiến trúc decoupled, tại sao không thể chạy end-to-end, và cách adapt cho robot khác.

Nguyễn Anh Tuấn2 tháng 6, 20266 phút đọcCập nhật: 6 thg 6, 2026
GR00T N1 + Unitree G1: kiến trúc WBC+VLA decoupled từ 6Hz đến 500Hz

GR00T N1 + Unitree G1: kiến trúc WBC+VLA decoupled từ 6Hz đến 500Hz

Đây là bài 1 trong series GR00T N1 + Unitree G1. Series này hướng dẫn từng bước từ thu data đến deploy working whole-body VLA policy trên G1, với G1 là ví dụ cụ thể nhưng cấu trúc adapt được cho bất kỳ humanoid nào có URDF.

Bài này giải thích tại sao kiến trúc phải decoupled, và các tần số khác nhau có nghĩa gì trong thực tế.

Vấn đề cốt lõi: inference 150ms vs control 5ms

Mọi thiết kế kiến trúc trong stack này đều xuất phát từ một thực tế không thể thay đổi:

GR00T N1 inference:  ~150ms  →  ~6 Hz
GEAR upper body ctrl:  20ms  →  50 Hz
SONIC loco ctrl:        5ms  → 200 Hz
Robot joint servo:      2ms  → 500 Hz

Nếu bạn cố chạy end-to-end — VLA output trực tiếp vào joint servos — robot sẽ bị jerk nặng mỗi 150ms và mất balance. Giải pháp là decoupled layers: mỗi layer chạy tốc độ riêng và interpolate.

Ba layer trong GR00T-WBC stack

┌─────────────────────────────────────────┐
│  GR00T N1 (VLA)          6Hz / 150ms   │
│  Input: camera × 3 + language           │
│  Output: target wrist pose L/R          │
│          + gripper width L/R            │
└──────────────┬──────────────────────────┘
               │ high-level command
┌──────────────▼──────────────────────────┐
│  GEAR (upper body)       50Hz / 20ms   │
│  RL-trained arm controller              │
│  Input: wrist target + proprioception   │
│  Output: arm joint torques              │
└──────────────┬──────────────────────────┘
               │
┌──────────────▼──────────────────────────┐
│  SONIC / HOVER (loco)   200Hz / 5ms    │
│  MPC + RL whole-body balance            │
│  Input: CoM target + terrain            │
│  Output: ALL joint commands (30+ DoF)   │
└──────────────┬──────────────────────────┘
               │
┌──────────────▼──────────────────────────┐
│  Robot servo drivers     500Hz / 2ms   │
│  PD controller per joint                │
└─────────────────────────────────────────┘

Tại sao chia như vậy?

  • VLA không cần biết cách balance — nó chỉ cần biết "tay phải đến đây"
  • Locomotion không cần hiểu ngôn ngữ — nó chỉ cần biết CoM phải đặt đâu
  • Mỗi layer có domain riêng, debug độc lập, thay thế độc lập

GR00T N1: model architecture

Repo: NVIDIA/Isaac-GR00T

Input:
  - Left wrist camera RGB (224×224)
  - Right wrist camera RGB (224×224)
  - Head camera RGB (224×224) [optional]
  - Language instruction (tokenized)

Backbone:
  - Eagle2 vision encoder (NVIDIA, 300M params)
  - Llama-3 language model (adapted)
  - Fusion: cross-attention layers

Action head:
  - Flow-matching diffusion
  - Predicts action chunk (T=16 steps ahead)
  - Output per step: Δ end-effector pose L/R + gripper binary

Parameters: ~2B total
Inference: ~150ms on RTX 4090

Action chunking: GR00T N1 không predict 1 action — nó predict chunk 16 bước tới. Robot thực thi chunk đó trong khi N1 inference bước tiếp. Đây là cách "smooth" được 6Hz thành cảm giác liên tục.

Unitree G1: joint map

G1 có 29 DoF trong config đầy đủ (với gripper):

Mỗi chân (×2):
  hip_yaw, hip_roll, hip_pitch  → 3 DoF
  knee_pitch                    → 1 DoF
  ankle_pitch, ankle_roll       → 2 DoF
  = 6 DoF × 2 chân = 12 DoF

Mỗi cánh tay (×2):
  shoulder_pitch, shoulder_roll, shoulder_yaw → 3 DoF
  elbow_pitch                               → 1 DoF
  wrist_roll, wrist_pitch                   → 2 DoF
  = 6 DoF × 2 tay = 12 DoF

Thân (waist):
  waist_yaw                     → 1 DoF

Gripper (×2):
  gripper_left, gripper_right   → 2 DoF (nếu có)

Tổng: 12 + 12 + 1 + 2 = 27–29 DoF

GR00T-WBC kiểm soát tất cả 27-29 DoF đồng thời — đó là lý do WBC phức tạp hơn arm-only policy nhiều.

Adapt cho robot khác

Stack này thiết kế modular — bạn có thể thay G1 bằng bất kỳ humanoid nào có full URDF và joint SDK.

Thay robot: 3 bước

Bước 1: Cung cấp URDF

# Cấu trúc thư mục trong GR00T-WBC
groot_wbc/robots/
  ├── g1/
  │   ├── g1.urdf
  │   ├── joint_config.yaml     ← đây là file cần sửa
  │   └── pd_gains.yaml
  ├── gr1/
  └── YOUR_ROBOT/               ← tạo thư mục mới
      ├── your_robot.urdf
      ├── joint_config.yaml
      └── pd_gains.yaml

Bước 2: Sửa joint_config.yaml

# joint_config.yaml cho robot của bạn
robot_name: "your_robot"
urdf_path: "robots/YOUR_ROBOT/your_robot.urdf"

# Map joint names theo thứ tự URDF của bạn
left_arm_joints:
  - "left_shoulder_pitch_joint"
  - "left_shoulder_roll_joint"
  - "left_shoulder_yaw_joint"
  - "left_elbow_pitch_joint"
  - "left_wrist_roll_joint"
  - "left_wrist_pitch_joint"

right_arm_joints:
  - "right_shoulder_pitch_joint"
  # ... tương tự

leg_joints:
  - "left_hip_yaw_joint"
  # ... 12 joint cho 2 chân

# End-effector frames (phải có trong URDF)
left_ee_frame: "left_gripper_link"
right_ee_frame: "right_gripper_link"

Bước 3: Tune PD gains

# pd_gains.yaml — điều chỉnh theo motor specs của robot
joint_gains:
  left_shoulder_pitch_joint:
    kp: 150.0   # position gain
    kd: 10.0    # velocity gain (damping)
  left_elbow_pitch_joint:
    kp: 80.0
    kd: 5.0
  # ... mỗi joint có gains riêng

Với G1: gains đã được NVIDIA tune sẵn trong groot_wbc/robots/g1/pd_gains.yaml. Với robot khác, bắt đầu với gains thấp (kp 50, kd 3) và tăng dần sau khi test trong sim.

Điều kiện cần để chạy được series này

Thành phần Minimum Recommended
GPU (training) RTX 4090 (24GB) A100 40GB
GPU (inference) RTX 3090 (24GB) RTX 4090
RAM 32GB 64GB
Storage 500GB SSD 2TB NVMe
Robot Unitree G1/H1 (optional cho bài 2-4 nếu dùng sim) Unitree G1
Sim Isaac Lab (Isaac Sim 4.x) Isaac Lab

Không có G1? Bài 2-4 có thể làm hoàn toàn trong Isaac Sim với G1 URDF. Bài 5 (sim2real) cần robot thật.

Roadmap series

Bài Chủ đề
Bài 1 (này) Kiến trúc decoupled, G1 joints, adapt robot
Bài 2 Thu data: Isaac Lab teleop + xr_teleoperate, LeRobot format
Bài 3 Fine-tune GR00T N1: GPU config, training script
Bài 4 Deploy GR00T-WBC: GEAR + SONIC trên G1
Bài 5 Sim2real + Evaluation: domain rand, humanoid-bench

Kết

Insight quan trọng nhất từ bài này: decoupled không phải là compromise — đó là engineering đúng. Mixing VLA inference (ML) và joint servo (control) vào một loop duy nhất sẽ cho bạn hệ thống không thể debug và không an toàn. Mỗi layer có responsibility rõ ràng, test độc lập, và fail rõ ràng khi có vấn đề.

Bài tiếp theo: Thu data với Isaac Lab và xr_teleoperate → LeRobot format.


Nguồn tham khảo


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

GR00T N1 + G1 (Bài 5): sim2real transfer, domain randomization, và eval với humanoid-bench
humanoid

GR00T N1 + G1 (Bài 5): sim2real transfer, domain randomization, và eval với humanoid-bench

6/6/20266 phút đọc
NT
GR00T N1 + G1 (Bài 4): deploy GR00T-WBC trên Unitree G1 — GEAR + SONIC
humanoid

GR00T N1 + G1 (Bài 4): deploy GR00T-WBC trên Unitree G1 — GEAR + SONIC

5/6/20266 phút đọc
NT
GR00T N1 + G1 (Bài 3): fine-tune GR00T N1 — GPU, config, training script
humanoid

GR00T N1 + G1 (Bài 3): fine-tune GR00T N1 — GPU, config, training script

4/6/20265 phút đọc
NT