humanoidhumanoidvlasim2realdomain-randomizationhumanoid-benchunitree-g1evaluationgroot

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

Closing the loop: domain randomization trong Isaac Lab, actuator modeling để thu hẹp sim2real gap, deploy lên G1 thật, và evaluate performance bằng humanoid-bench — cộng với debug guide cho các failure mode thường gặp.

Nguyễn Anh Tuấn6 tháng 6, 20266 phút đọc
GR00T N1 + G1 (Bài 5): sim2real transfer, domain randomization, và eval với humanoid-bench

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

Đây là bài cuối trong series GR00T N1 + Unitree G1. Bài trước deploy stack lên G1. Bài này: làm cho nó thực sự hoạt động đáng tin cậy ngoài sim — sim2real transfer — và đo performance một cách khoa học.

Sim2real gap là gì và tại sao nó quan trọng

Khi train trong Isaac Sim và deploy lên G1 thật, bạn sẽ gặp "sim2real gap" — behavior trong sim tốt nhưng trên real robot lại khác. Nguyên nhân chính:

Sim:                        Real robot:
├── Lý tưởng frition        ├── Carpet/tile/dust thay đổi friction
├── Exact joint torques      ├── Motor backlash, gear compliance
├── Zero sensor noise        ├── IMU noise, encoder jitter
├── Tức thì actuator        ├── Actuator delay ~5-10ms
├── Perfect mass params      ├── Payload, component wear
└── No cable drag            └── Cable tension affects joints

Không có sim nào perfect. Mục tiêu là thu hẹp gap đủ để policy từ sim vẫn hoạt động trên real.

Domain Randomization trong Isaac Lab

Giải pháp chính: randomize simulation parameters trong quá trình training để policy learn robust hơn.

# Isaac Lab domain randomization config
# File: groot_wbc/configs/domain_rand_g1.yaml

domain_randomization:
  enabled: true
  
  # Friction randomization
  ground_friction:
    range: [0.5, 1.5]        # thực tế: 0.6–1.2 tùy sàn
    sample_per_episode: true  # đổi mỗi episode
    
  robot_friction:
    range: [0.3, 0.8]         # joint-level friction
    
  # Mass randomization (±20%)
  body_mass:
    range: [0.8, 1.2]         # scale factor
    per_body: true
    
  # Actuator delay
  actuator_delay_ms:
    range: [0, 15]            # 0–15ms random delay
    
  # Sensor noise
  imu_noise:
    gyro_std: 0.02            # rad/s
    accel_std: 0.1            # m/s²
    
  joint_encoder_noise:
    std: 0.005                # rad, per joint
    
  # Push perturbations (làm robot mạnh hơn với external forces)
  random_push:
    enabled: true
    force_range: [0, 50]      # N
    interval_s: [3, 8]        # mỗi 3-8 giây
    direction: "random"

Áp dụng trong training:

python scripts/finetune.py \
  --config configs/finetune_g1_pickplace.yaml \
  --domain_rand configs/domain_rand_g1.yaml

Domain randomization thường tăng training time ~30% nhưng sim2real transfer tốt hơn rõ rệt.

Actuator Modeling: thu hẹp gap quan trọng nhất

Actuator delay là nguồn sim2real gap lớn nhất. G1 dùng servo motors với ~8ms delay:

# Thêm actuator model vào Isaac Lab env
# File: groot_wbc/envs/g1_env.py

from isaaclab.actuators import DelayedPDActuator

actuator_cfg = DelayedPDActuator(
    joint_names_expr=[".*"],   # tất cả joints
    effort_limit=150.0,
    velocity_limit=5.0,
    
    # PD params (khớp với real robot)
    stiffness={".*shoulder.*": 150.0, ".*elbow.*": 80.0, ".*hip.*": 200.0},
    damping={".*shoulder.*": 10.0, ".*elbow.*": 5.0, ".*hip.*": 15.0},
    
    # Delay modeling
    delay_range=(0.005, 0.012),  # 5–12ms delay range
    
    # Gear compliance
    gear_ratio={".*": 1.0},
    armature={".*": 0.01},       # rotor inertia
)

Sau khi thêm actuator model, performance trong sim sẽ giảm nhẹ nhưng transfer sang real tốt hơn.

Evaluate với humanoid-bench

Trước khi nói "policy hoạt động," cần có số liệu cụ thể. humanoid-bench là standard để compare với papers.

Cài đặt

git clone https://github.com/carlosferrazza/humanoid-bench.git
cd humanoid-bench
pip install -e .

# Thêm G1 model
cp groot_wbc/robots/g1/g1.xml humanoid_bench/assets/robots/

Chạy eval

# Eval task: pick-and-place
python humanoid_bench/evaluate.py \
  --robot g1 \
  --task "h1_pick_place"   # hoặc task tương đương cho G1
  --policy_checkpoint ./runs/g1_pickplace/checkpoint_best/ \
  --num_episodes 100 \
  --seed 42

# Output:
# Task: h1_pick_place | Robot: G1
# Episodes: 100
# Success rate:      82/100 = 82%
# Mean episode time: 14.3s ± 2.1s
# Grasp success:     91/100 = 91%
# Place success:     82/100 (given grasp)

Metrics quan trọng

Metric Ý nghĩa Target
Success rate Hoàn thành task ≥ 80% sim, ≥ 60% real
Grasp success Grasping đúng vật ≥ 90%
Mean episode time Nhanh hay chậm < 20s cho pick-place đơn giản
Balance fall rate Robot có ngã không 0% trong evaluation

Eval trên real robot

# Với G1 thật — chạy eval qua Unitree SDK
python humanoid_bench/evaluate_real.py \
  --robot g1 \
  --policy_checkpoint ./runs/g1_pickplace/checkpoint_best/ \
  --num_episodes 20 \   # ít hơn vì real robot chậm hơn
  --task "pick_place_red_cup"

Debug guide: failure modes thường gặp

1. Robot mất balance khi tay vươn ra xa

Triệu chứng: G1 ngã về phía trước khi tay extend > 0.5m.
Nguyên nhân: SONIC CoM estimation không đúng khi arm configuration thay đổi.
Fix:

# groot_wbc/configs/sonic_g1.yaml
com_compensation:
  arm_mass_fraction: 0.15   # tăng từ 0.10 nếu robot nặng tay
  update_rate_hz: 50        # tăng để CoM update nhanh hơn

2. Tay jerk khi nhận target mới từ N1

Triệu chứng: Arm movement không mượt, giật mỗi ~150ms (khớp N1 inference rate).
Nguyên nhân: GEAR không smooth transition giữa target mới và target cũ.
Fix:

# groot_wbc/configs/gear_g1.yaml
target_smoothing:
  enabled: true
  alpha: 0.3   # EMA filter — 0.1 (rất mượt) đến 0.9 (responsive)

3. Gripper không nhả vật

Triệu chứng: Gripper close OK nhưng không open đúng lúc.
Nguyên nhân: N1 không predict gripper open đủ mạnh, hoặc threshold quá cao.
Fix:

# Giảm ngưỡng để gripper dễ open hơn
action_config:
  gripper_open_threshold: 0.3   # từ 0.5 xuống 0.3

4. Object không được nhận diện đúng vị trí

Triệu chứng: Tay vươn ra vị trí sai, lệch 5-10cm.
Nguyên nhân: Camera calibration sai hoặc lighting khác với lúc train.
Fix:

  • Recalibrate wrist cameras (chạy scripts/calibrate_cameras.py)
  • Thu thêm data trong lighting conditions đa dạng hơn

5. Sim2real gap lớn — policy dùng được trong sim nhưng fail real

Nguyên nhân phổ biến: actuator delay không được model trong sim.
Fix nhanh: thêm actuator_delay_ms: [5, 12] vào domain rand config và retrain ~50 epochs.

Cải thiện policy — nếu performance chưa đủ

Theo thứ tự thử:

  1. Thu thêm data — thêm 50 demos, đặc biệt từ failure cases
  2. Tăng data diversity — lighting khác nhau, object position khác nhau
  3. Tăng domain randomization — friction range rộng hơn, push force lớn hơn
  4. Fine-tune thêm từ checkpoint tốt nhất, với lr thấp hơn (1e-5)
  5. Kiểm tra camera calibration — nguyên nhân hay bị bỏ qua nhất

Tổng kết series

Từ 5 bài, bạn đã đi qua đầy đủ pipeline:

Bài Input Output
1: Architecture Hiểu kiến trúc decoupled
2: Data Robot + sim LeRobot dataset
3: Training LeRobot dataset GR00T N1 checkpoint
4: Deploy Checkpoint + G1 Stack running trên robot
5: Eval (bài này) Stack trên robot Benchmark numbers + fixes

Adapt cho robot khác: bài 1, 2, 4 đều có "adapt guide" cụ thể — swap URDF + joint config là 80% công việc.


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 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
GR00T N1 + G1 (Bài 2): thu data trong Isaac Lab và xr_teleoperate → LeRobot
humanoid

GR00T N1 + G1 (Bài 2): thu data trong Isaac Lab và xr_teleoperate → LeRobot

3/6/20266 phút đọc
NT
GR00T N1 + Unitree G1: kiến trúc WBC+VLA decoupled từ 6Hz đến 500Hz
humanoid

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

2/6/20266 phút đọc
NT