Tại sao bài này khác hai bài WholeBodyVLA trước đó?
Nếu bạn đã đọc bài phân tích research WholeBodyVLA ICLR 2026 (đi vào ý tưởng & contribution) và bài deep-dive kiến trúc open-source (đào codebase), thì bài này tập trung vào con đường đi từ teleop demo đến robot tự chạy thực tế: bạn ngồi đâu, robot làm gì, dữ liệu chảy ra sao, GPU nào train, và khi nào nhấn nút "Run" trên humanoid AgiBot X2.
Đây là một tutorial pipeline-level — không phải copy-paste từng dòng code (vì repo OpenDriveLab/WholebodyVLA hiện tại mới release paper + resources, chưa release codebase đầy đủ tại thời điểm tháng 5/2026), mà là bản đồ thực địa giúp một kỹ sư robotics có thể bắt tay xây pipeline tương đương ngay hôm nay bằng các công cụ open-source hiện hành (LeRobot, Isaac Lab, AgiBot teleop suite).
Vấn đề mà WholeBodyVLA giải quyết
Whole-body loco-manipulation không phải "đi cộng với cầm" — nó là vừa đi vừa cầm, trong không gian lớn, với khối lượng đáng kể. Trên paper (arxiv.org/abs/2512.11047), nhóm tác giả (Jiang, Chen et al., từ Fudan University, OpenDriveLab & MMLab @ HKU, AGIBOT, SII) demo các task:
- Bimanual grasping + đặt vật trên kệ trong không gian rộng (robot phải đi/xoay/squat để tới điểm).
- Đẩy xe đẩy với tải > 50 kg — chân và tay phải phối hợp giữ thăng bằng.
- Lau bàn, hút bụi — task long-horizon, kết hợp navigation + manipulation liên tục.
Trước đây có 2 trường phái:
- Modular: locomotion policy chạy riêng (RL hoặc MPC), manipulation policy chạy riêng (VLA hoặc IL), nối lại bằng một state machine. Vấn đề: hai policy không biết về nhau — robot ngã khi với cao quá vì chân không bù trọng tâm.
- End-to-end monolithic: 1 mạng nhận tất cả → output cả joint torque chân + tay. Vấn đề: cần dữ liệu whole-body teleop cực hiếm và đắt, training không converge cho long-horizon.
WholeBodyVLA chọn con đường thứ ba: VLA học latent action từ video egocentric không cần action labels, kết hợp với LMO RL policy (Loco-Manipulation-Oriented) chạy ở tần số cao 50 Hz để thực thi. VLA ra lệnh latent, LMO biên dịch sang joint torque thật.
Kiến trúc pipeline ở mức tổng thể
┌──────────────────────────────────────────────────────────────┐
│ Input: Egocentric RGB (head cam) + Language instruction │
│ "Pick up the red box and put it on the shelf" │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ VLM Encoder (frozen pretrained, e.g. Qwen-VL/InternVL) │
│ → vision tokens + language tokens │
└────────────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Latent Action Model (LAM) — pretrained trên video không │
│ cần action labels, học inverse dynamics từ frame t → t+k │
│ → latent action tokens z_t (~10 Hz) │
└────────────────────────┬─────────────────────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌──────────────────────┐ ┌──────────────────────────────────┐
│ Dual-arm decoder │ │ Locomotion command decoder │
│ → joint targets │ │ → (v_x, v_y, ω_z, body_height) │
│ cho 2 cánh tay │ │ cho LMO RL policy │
└──────────┬───────────┘ └──────────────┬───────────────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────────────────┐
│ Arm low-level ctrl │ │ LMO RL Policy (PPO, 50 Hz) │
│ (PD @ 200-500 Hz) │ │ Joint torque cho chân + waist │
└──────────────────────┘ └──────────────────────────────────┘
Hai cấp tần số rất quan trọng:
- VLA chậm (~10 Hz) vì nó dùng transformer lớn cần GPU + xử lý vision.
- LMO nhanh (50 Hz) vì balance/locomotion cần phản ứng kịp với disturbance (đẩy, va chạm, mặt đất gồ ghề).
Kết quả paper: outperform baseline modular +21.3% success rate, đặc biệt mạnh ở task large-space và long-horizon.
Bước 1 — Chuẩn bị phần cứng và môi trường
Phần cứng tham chiếu
- Robot: AgiBot X2 (humanoid 1.7m, ~50 kg, 36+ DoF) — hoặc Unitree G1, Booster T1, Fourier GR-1 cho ai không có X2. Logic chung như nhau.
- Compute đào tạo: 8× A100/H100 80GB (paper sử dụng cluster lớn hơn cho pretrain LAM).
- Compute deploy on-robot: Jetson AGX Orin 64GB hoặc PC tích hợp với RTX 4090 mobile, đủ cho VLA 10 Hz.
Software stack đề xuất
# Tạo env
conda create -n wbvla python=3.10 -y
conda activate wbvla
# Core
pip install torch==2.4.0 torchvision --index-url https://download.pytorch.org/whl/cu121
pip install transformers==4.45 accelerate datasets
# Robot learning frameworks
pip install lerobot # teleop + dataset format
pip install isaac-lab # locomotion RL sim
pip install hydra-core wandb einops
Lưu ý: Mã nguồn chính thức WholeBodyVLA chưa release đầy đủ. Pipeline dưới đây dùng LeRobot + Isaac Lab + AgiBot teleop SDK để tái hiện ý tưởng trên hardware có sẵn.
Bước 2 — Thu thập dữ liệu teleop
Đây là phần đắt nhất của bất kỳ VLA project nào. WholeBodyVLA giảm chi phí bằng cách dùng video không-action-labels cho phần manipulation. Bạn vẫn cần một lượng nhỏ teleop để bootstrap action decoders.
2.1. Setup teleop AgiBot X2 (hoặc tương đương)
AgiBot mở sẵn teleop suite (VR controllers + exoskeleton arms). Workflow tổng quát:
# Trên control station
git clone https://github.com/AgiBot/teleop-suite
cd teleop-suite
./scripts/calibrate_operator.sh # đo chiều cao, sải tay
./scripts/start_teleop.sh --robot agibot_x2 --record
Người vận hành đeo VR headset + cầm controllers. Hệ thống map:
- Đầu → camera angle robot.
- Tay → end-effector poses (IK solve trên-bay).
- Người đi/xoay/squat → command (v_x, v_y, ω_z, height).
2.2. Định dạng dữ liệu
Mỗi episode được lưu theo chuẩn LeRobot v2:
# episode_000123.parquet
{
"observation.images.head_cam": [T, 3, 480, 640], # uint8 RGB
"observation.images.wrist_cam_l": [T, 3, 480, 640],
"observation.images.wrist_cam_r": [T, 3, 480, 640],
"observation.state": [T, 36], # joints
"action.arm_joints": [T, 14], # 7+7 DoF tay
"action.loco_cmd": [T, 4], # vx, vy, wz, h
"language_instruction": "pick the red box and place on shelf",
"task_id": "longhorizon_pick_place_001",
}
2.3. Bao nhiêu data là đủ?
Paper chỉ ra rằng với LAM pretrain trên video không-label, bạn chỉ cần khoảng 2-5k episodes teleop có action (50-150 giờ) để fine-tune decoder — giảm ~10× so với end-to-end. Lý do: LAM đã học inverse dynamics từ video phong phú trước.
Bước 3 — Pretrain Latent Action Model (LAM)
Đây là innovation cốt lõi của WholeBodyVLA. Ý tưởng: học action latent z_t từ cặp (frame_t, frame_{t+k}) mà không cần action labels — tương tự inverse dynamics model trong các paper như Genie hay LAPO.
3.1. Nguồn video pretrain
- Ego4D, Epic-Kitchens, RH20T: hàng nghìn giờ first-person video.
- AgiBot World 2026 (dataset overview): video humanoid teleop quy mô lớn.
- Video YouTube nội bộ về first-person manipulation.
Mục tiêu: encoder học biểu diễn hành động ngắn hạn từ thay đổi visual — không cần biết robot làm gì cụ thể.
3.2. Loss & training
# Pseudo-code rút gọn — ý tưởng chính
class LAM(nn.Module):
def __init__(self, vit_backbone):
self.vision = vit_backbone # frozen ViT
self.action_quantizer = VQVAE(codebook_size=1024)
self.forward_dynamics = Transformer(depth=8)
def forward(self, frame_t, frame_tk):
feat_t = self.vision(frame_t)
feat_tk = self.vision(frame_tk)
# encode action diff vào latent z_t
z_t = self.action_quantizer.encode(feat_tk - feat_t)
# predict frame_tk từ frame_t + z_t
pred_tk = self.forward_dynamics(feat_t, z_t)
loss = F.mse_loss(pred_tk, feat_tk) + self.action_quantizer.commit_loss
return loss
Training:
torchrun --nproc_per_node=8 train_lam.py \
--data.video_roots ego4d,epic_kitchens,agibot_world \
--model.vision_backbone vit-l-14 \
--model.codebook_size 1024 \
--train.batch_size 256 \
--train.lr 1.5e-4 \
--train.steps 200000
Trên 8×A100, khoảng 4-6 ngày.
Bước 4 — Train action decoders (arm + locomotion command)
Sau khi có LAM, bạn train hai decoder nhỏ map từ z_t sang hành động cụ thể, dùng dữ liệu teleop ở Bước 2.
torchrun --nproc_per_node=4 train_decoders.py \
--lam_ckpt outputs/lam/final.pt \
--data.teleop_dataset /data/agibot_x2_teleop \
--model.arm_decoder mlp_depth=4 \
--model.loco_decoder mlp_depth=3 \
--train.steps 50000
Mất ~1-2 ngày trên 4×A100. Output là 2 checkpoint nhẹ (~50-100M params mỗi cái).
Bước 5 — Train LMO RL policy trong sim
LMO chạy độc lập với VLA. Nó nhận loco_cmd từ VLA và phải biến nó thành torque cho chân + waist sao cho robot giữ thăng bằng dưới disturbance (đẩy, mang vật nặng, mặt đất gồ ghề).
5.1. Isaac Lab task
git clone https://github.com/isaac-sim/IsaacLab
cd IsaacLab
./isaaclab.sh -p source/standalone/workflows/skrl/train.py \
--task Isaac-Humanoid-LocoManip-AgiBotX2-v0 \
--num_envs 4096 --headless
Reward chính:
- Tracking command
(v_x, v_y, ω_z, body_height)chính xác. - Robustness: domain randomization (mass, friction, push forces).
- Manipulation-aware: penalty khi torso oscillate quá mức (vì sẽ rung tay) — đây là điểm khác biệt với locomotion RL thường.
Train ~24-48 giờ trên 1×A100 với 4096 env song song. Tham khảo Booster Gym ICRA 2026 cho công thức sim-to-real tương tự.
5.2. Sim-to-real
Sau train sim, deploy lên robot thật thường cần:
- Actuator network: huấn luyện thêm 1 MLP map motor command → actual torque (lấy ~1 giờ data từ robot thật chạy command ngẫu nhiên).
- Curriculum: bắt đầu với command nhẹ, tăng dần biên độ.
- Noise injection: thêm noise vào IMU/joint trong sim để chống jitter trên real hardware.
Bước 6 — Inference loop trên robot
# robot_runner.py
import torch, time
from wbvla import VLAPolicy, LMOPolicy
vla = VLAPolicy.from_pretrained("./ckpts/vla_final")
lmo = LMOPolicy.from_pretrained("./ckpts/lmo_final")
robot = AgiBotX2() # wrap teleop SDK
instruction = "pick the red box and place it on the top shelf"
while True:
obs = robot.get_observation() # ego image + state
# VLA @ 10 Hz
if time.time() - last_vla > 0.1:
arm_target, loco_cmd = vla.act(obs.image, instruction, obs.state)
last_vla = time.time()
# LMO @ 50 Hz
leg_torque = lmo.act(loco_cmd, obs.state)
robot.send(arm_target, leg_torque)
Latency thực tế:
| Block | Latency (Jetson AGX Orin) |
|---|---|
| VLM encoder (vision + lang) | ~60 ms |
| LAM + decoders | ~30 ms |
| LMO policy | ~5 ms |
| Robot control loop | ~2 ms |
| Tổng VLA tick | ~95 ms (~10.5 Hz) |
Bước 7 — Đánh giá kết quả
Chỉ số chính của paper:
| Task | Baseline (modular) | WholeBodyVLA | Δ |
|---|---|---|---|
| Pick & place large-space | 52% | 71% | +19% |
| Push cart > 50 kg | 38% | 64% | +26% |
| Wipe table long-horizon | 41% | 60% | +19% |
| Trung bình | 44% | 65% | +21.3% |
Điểm yếu cần biết:
- Failures chủ yếu xảy ra khi VLA tick chậm hơn 200 ms (do GPU thermal throttle) → robot bị "đông cứng" giữa task. Giải pháp: distill VLM nhỏ hơn (~1B params) hoặc speculative decoding.
- Task bimanual contact-rich (mở chai, tháo nắp) vẫn yếu — đây là hướng future work, có thể kết hợp với tactile sensing.
Pitfalls thực tế khi tái hiện pipeline
- Đừng đặt VLA + LMO cùng một tần số. Đây là sai lầm phổ biến nhất. VLA mục tiêu ý định, LMO mục tiêu ổn định. Hai mục tiêu khác nhau cần hai loop khác nhau.
- Domain randomization khi train LMO phải bao gồm "cầm vật nặng". Nhiều bạn quên thêm payload randomization → robot không biết cân bằng khi tay xách thùng 20 kg.
- Data teleop phải có audio/timestamp đồng bộ với loco_cmd. Misalignment 50 ms giữa arm action và walk command sẽ làm decoder học sai correlation.
- VLM frozen pretrained luôn tốt hơn fine-tune full. Bạn không có đủ data robot để fine-tune VLM 7B+ mà không catastrophic forgetting.
- Đánh giá luôn trên real robot, không chỉ sim. Sim-to-real gap đặc biệt lớn với loco-manipulation vì contact dynamics khó model.
Bài học transferable cho project khác
- Tách "ý định" khỏi "thực thi" — pattern này áp dụng được cho navigation (planner + controller), autonomous driving (perception planner + low-level), và cả software (orchestration layer + execution layer).
- Action-free pretrain từ video là một con đường rẻ. Nếu bạn có hàng nghìn giờ video task mà không có action label, đừng vứt đi — LAM-style có thể dùng được.
- Cùng latent space cho nhiều loại action (arm + leg) cho phép multi-task generalization. Đây là ý tưởng đáng nhớ ngoài robotics: thiết kế interface chung trước, decoder riêng sau.