wholebody-vlaegohumanoidunitree-g1wholebody-vlaegocentric-datalerobotzedpicohumanoid

EgoHumanoid: human demo sang G1 VLA

Xây pipeline EgoHumanoid từ human/robot data, view alignment, action alignment, LeRobot, train và deploy policy cho G1.

Nguyễn Anh Tuấn11 tháng 6, 202617 phút đọc
EgoHumanoid: human demo sang G1 VLA

Vì sao EgoHumanoid là stack thứ ba?

bài 1 về OpenWBT, chúng ta bắt đầu bằng teleoperation whole-body có thể debug được: lower-body policy, upper-body IK, simulator trước, robot thật sau. Ở bài 2 về TWIST2, trọng tâm chuyển sang thu dữ liệu robot trực tiếp bằng PICO teleop, Redis bus, low-level controller và vòng sim2real. Cả hai stack đều đặt robot vào trung tâm: muốn có demonstration tốt thì robot phải chạy, operator phải điều khiển robot, và mỗi lỗi latency hoặc tracking đều ảnh hưởng trực tiếp tới dữ liệu.

EgoHumanoid hỏi một câu khác: nếu lab chưa thể thu hàng nghìn episode robot thật thì có thể tận dụng egocentric human demonstrations hay không? Paper và repo OpenDriveLab/EgoHumanoid mô tả framework co-train VLA policy bằng human demos góc nhìn thứ nhất cộng với một lượng robot data giới hạn. Project page của EgoHumanoid nhấn mạnh hai module alignment: view alignment để giảm chênh lệch góc nhìn camera giữa người và robot, action alignment để map chuyển động người sang không gian action robot. Đây là điểm khác hẳn TWIST2: TWIST2 cố làm teleop robot tốt hơn, EgoHumanoid cố làm dữ liệu người trở nên "robot-ready" hơn.

Bài này đi theo pipeline bốn bước đúng tinh thần repo: thu robot/human data, chạy data_alignment/human_data_process/run_human_data_pipeline.sh, chuyển HDF5 sang LeRobot bằng data_alignment/convert_to_lerobot.py, rồi train/deploy bằng scripts/train.py, scripts/serve_policy.pyscripts/deploy.py. Phần quan trọng nhất không phải command cuối cùng, mà là hai lớp alignment ở giữa: view_alignment/viewport_transform_batch_h5.py với cache_3d.py cho ảnh, và process_navigation_pipeline.py với add_hand_status.py cho action.

Roadmap series

  1. OpenWBT: G1 teleop trong MuJoCo/Isaac: dựng môi trường, kiểm tra ONNX policy, hiểu split lower-body joystick và upper-body IK.
  2. TWIST2: PICO teleop và G1 sim2real: dùng PICO teleop, Redis và low-level controller để thu dữ liệu robot trực tiếp.
  3. EgoHumanoid: human demo sang G1 VLA: biến egocentric human demo thành HDF5/LeRobot có ảnh, navigation command và hand status.
  4. VIRAL: retarget và kiểm tra kỹ năng: dùng motion source bên ngoài, retarget sang humanoid đích và đánh giá lỗi.
  5. FromW1: chuyển kỹ năng sang robot thật: đi từ sim policy sang real hardware với latency, contact và giới hạn actuator.
  6. CLONE: closed-loop whole-body teleop: nhìn closed-loop teleop như một stack thu dữ liệu dài hạn cho loco-manipulation.

Nếu bạn đang nối bài này vào pipeline VnRobo rộng hơn, nên đọc thêm GR00T N1 + G1 data collectionWholeBodyVLA open-source guide. Hai bài đó giúp đặt EgoHumanoid vào bức tranh data, VLA và whole-body control lớn hơn.

Nguồn kỹ thuật cần mở song song

Nguồn Dùng để làm gì Điểm cần ghi nhớ
EgoHumanoid README Nắm pipeline tổng thể collect, process, train, deploy Repo chia hệ thành data collection, data processing, model training và deployment
Human data pipeline README Hiểu run_human_data_pipeline.sh Script nội bộ có reorder, navigation, downsample, merge camera và hand status
View alignment README Chạy viewport_transform_batch_h5.py MoGe depth, Cache3D point-cloud warp, Stable Diffusion inpainting
EgoHumanoid paper Hiểu vì sao cần alignment Human demo dùng PICO + ZED; robot demo dùng Unitree G1 + Dex3 + ZED; action được tách thành EEF delta, velocity command và hand open/close

Humanoid robot trong môi trường lab
Humanoid robot trong môi trường lab

Mental model: EgoHumanoid không chỉ là convert dataset

Beginner dễ hiểu nhầm EgoHumanoid là một script chuyển HDF5 sang LeRobot. Thực tế pipeline có ba khoảng cách phải xử lý:

Người thật
  PICO VR + 5 tracker + ZED
  body pose, hand pose, egocentric RGB
        |
        | human_data_process + view/action alignment
        v
HDF5 robot-ready
  teleop_navigate_command
  observation_image_left/right
  action_eef, action_delta_eef
  delta_height, hand_status
        |
        | convert_to_lerobot.py
        v
LeRobot dataset
  observation.images.left
  action_eef, action_delta_eef
  teleop_navigate, delta_height, hand_status
        |
        | scripts/train.py
        v
π0.5-style G1 VLA policy
        |
        | serve_policy.py + deploy.py
        v
Unitree G1 runtime

Khoảng cách thứ nhất là visual domain gap. Người đeo camera ở độ cao, vị trí và hướng khác camera gắn trên đầu G1. Cùng một thao tác nhặt đồ, ảnh của người có thể nhìn xuống từ cao hơn hoặc lệch hơn so với robot. View alignment dùng depth, point-cloud warping và inpainting để tạo ảnh gần với viewpoint robot hơn.

Khoảng cách thứ hai là action domain gap. Người có xương, tỷ lệ tay, dáng đi và bàn tay khác robot. EgoHumanoid không cố xuất joint người rồi retarget từng joint sang G1. Paper mô tả unified action space: upper body dùng 6-DoF delta end-effector pose, lower body dùng discrete velocity command, hand dùng binary open/close. Đây là thiết kế thực dụng vì policy học mục tiêu thao tác và điều hướng, còn controller/IK bên dưới xử lý embodiment.

Khoảng cách thứ ba là dataset format gap. HDF5 nội bộ phù hợp cho alignment và kiểm tra từng episode. LeRobot phù hợp cho training policy, image writer, metadata, FPS và task instruction. Vì vậy convert_to_lerobot.py không phải bước phụ; nó là nơi khóa schema training.

Bước 1: thu robot data và human data

Repo EgoHumanoid hỗ trợ hai nhánh dữ liệu. Robot data được thu trên Unitree G1 với Dex3 hand, workstation Ubuntu, ZED Mini trên đầu robot và PICO VR cho teleoperation. README robot data ghi vòng chạy thực tế gồm control loop, teleop policy loop và exporter ZED:

# Terminal 1: G1 control loop, real interface, có hands
python decoupled_wbc/control/main/teleop/run_g1_control_loop.py \
  --interface real \
  --control-frequency 50 \
  --with_hands

# Terminal 2: PICO teleoperation
python decoupled_wbc/control/main/teleop/run_teleop_policy_loop.py \
  --body-control-device pico \
  --hand_control_device pico \
  --enable_real_device

# Terminal 3: ZED + robot data exporter
python decoupled_wbc/control/main/teleop/zed_mini_run_g1_data_exporter.py \
  --dataset-name pick_toy_v1 \
  --visualize

Human data dùng PICO VR headset, năm PICO Motion Trackers cho full-body tracking, ZED Mini gắn trên headset và workstation có USB 3.0. Paper gốc nhắc tới ZED X Mini, còn README repo ghi dùng ZED Mini để dễ tiếp cận hơn. Dữ liệu raw cần có ít nhất các trường:

Trường raw Shape tham khảo Dùng cho bước nào
body_pose (N, num_joints, 7) Tính pelvis trajectory, navigation command và end-effector pose
left_hand_pose (N, 26, >=3) Suy ra trạng thái mở/đóng tay trái
right_hand_pose (N, 26, >=3) Suy ra trạng thái mở/đóng tay phải
local_timestamps_ns (N,) Đồng bộ motion với frame ZED
episode_*.svo2 video ZED Trích left/right camera frames

Cấu trúc raw mà run_human_data_pipeline.sh mong đợi là các batch folder theo ngày. Đừng bỏ mọi episode vào một folder phẳng nếu bạn muốn dùng script mặc định:

raw_human/
  2026-06-11_batch1/
    episode_0.hdf5
    episode_0.svo2
    episode_1.hdf5
    episode_1.svo2
  2026-06-11_batch2/
    episode_0.hdf5
    episode_0.svo2

Với beginner, hãy thu ít nhưng sạch. Một task như "put the pillow on the bed" hoặc "grasp the toy and put it on the table" tốt hơn mười task lẫn lộn. Mỗi episode nên bắt đầu và kết thúc ở trạng thái dễ nhận diện, camera không bị che, tay không ra khỏi frame quá lâu, và operator lặp lại cùng instruction.

Bước 2: chạy human data pipeline

Command nhanh nhất là:

cd data_alignment/human_data_process

./run_human_data_pipeline.sh \
  --input_dir /data/ego/raw_human \
  --output_dir /data/ego/intermediate \
  --final-output-dir /data/ego/final \
  --file all

Mặc dù trong bài này ta gọi đây là bước 2 của pipeline bốn bước, bên trong script có năm stage nhỏ:

Stage Script liên quan Kết quả
Reorder scripts/reorder_episodes_for_raw.py Sắp xếp episode theo thời gian, copy thành episode_N.hdf5episode_N.svo2
Navigation process_navigation_pipeline.py Từ body_pose, tính trajectory, velocity [vx, vy, yaw_rate]
Downsample downsample_episode.py Giảm tần số, mặc định factor 5; tạo teleop_navigate_command rời rạc
Merge camera merge_camera_only.py Match timestamp và ghi ảnh ZED left/right vào HDF5
Hand status add_hand_status.py Ghi hand_status dạng (M, 2) cho trái/phải

Nếu muốn debug từng phần, chạy từng script độc lập:

# 1. Reorder
python scripts/reorder_episodes_for_raw.py \
  --input_dir /data/ego/raw_human \
  --output_dir /data/ego/intermediate \
  --file all \
  --workers 32

# 2. Navigation: pelvis trajectory -> velocity command
python process_navigation_pipeline.py \
  --dataset-dir /data/ego/intermediate \
  --baseline-sec 15 \
  --tangent-lag 5 \
  --overwrite \
  --no-png

# 3. Downsample: tạo teleop_navigate_command
python downsample_episode.py \
  --dataset-dir /data/ego/intermediate \
  --downsample-rate 5 \
  --overwrite

# 4. Merge camera: SVO2 -> HDF5 images
python merge_camera_only.py \
  --dataset-dir /data/ego/intermediate \
  --output-dir /data/ego/final \
  --num-workers 32

# 5. Hand status: pose tay -> open/close
python add_hand_status.py \
  --raw /data/ego/intermediate/hdf5 \
  --mid /data/ego/final \
  --target /data/ego/final \
  --downsample 5 \
  --num_workers 32

Sau bước này, HDF5 cuối nên có các field quan trọng:

body_pose
navigation_command
teleop_navigate_command
delta_height
observation_image_left
observation_image_right
camera_timestamp
timestamp_diff_ms
hand_status

teleop_navigate_command là chỗ lower-body alignment bắt đầu có ý nghĩa. Script navigation đọc pelvis và hip landmarks, smoothing trajectory bằng Savitzky-Golay, ước lượng hướng tangent, rồi biến chuyển động người thành velocity command trong local body frame. Sau downsample, command được rời rạc hóa bằng threshold để giống primitive teleop của robot hơn. Đây không phải ground truth hoàn hảo, nhưng nó đủ nhất quán để policy học khi nào đi tới, lùi, sang trái/phải, quay hoặc đứng.

hand_status là chỗ dexterous hand được đơn giản hóa. add_hand_status.py lấy pose bàn tay, tính metric dựa trên khoảng cách fingertip và độ cong ngón, rồi fit square wave để suy ra 0/1. README định nghĩa 1 = closed, 0 = open, shape (M, 2) theo thứ tự [left, right]. Với G1 + Dex3, biểu diễn này thô hơn joint-level hand pose, nhưng dễ học hơn và ít nhạy hơn với sai số tracker.

Bước 3: view alignment bằng viewport_transform_batch_h5.py

View alignment là phần hay bị bỏ qua vì nó tốn GPU và nhìn giống augmentation ảnh. Với EgoHumanoid, đây là phần cốt lõi. Paper giải thích rằng chênh lệch chiều cao và camera pose giữa người và humanoid tạo ra visual gap rõ rệt. Pipeline view alignment dùng MoGe để suy ra per-pixel 3D point map/depth, dùng Cache3D để warp point cloud sang viewpoint robot, rồi dùng Stable Diffusion inpainting để lấp vùng thiếu do disocclusion.

Chạy một file HDF5:

cd data_alignment/view_alignment

python viewport_transform_batch_h5.py \
  --h5_file /data/ego/final/episode_0.hdf5 \
  --image_key "observation_image_left" \
  --trajectory "down" \
  --movement_distance 0.07 \
  --output_dir /data/ego/view_aligned/episode_0

Chạy cả thư mục với nhiều GPU:

python viewport_transform_batch_h5.py \
  --h5_dir /data/ego/final \
  --batch_size 32 \
  --trajectory "down" \
  --movement_distance 0.07 \
  --num_gpus 4 \
  --output_dir /data/ego/view_aligned

Các argument cần hiểu:

Argument Ý nghĩa Gợi ý beginner
--image_key Field ảnh trong HDF5 Bắt đầu với observation_image_left; xử lý right sau nếu cần
--trajectory Hướng shift camera: left, right, up, down, forward, backward Với người cao hơn robot, thử down trước
--movement_distance Khoảng dịch camera README ví dụ 0.07; đừng tăng quá mạnh khi chưa xem ảnh
--movement_distance_noise Nhiễu pose mỗi sample Hữu ích để policy chịu được sai số mounting
--sd_model Inpainting model Mặc định stabilityai/stable-diffusion-2-inpainting
--save_h5 Lưu lại dạng H5 Dùng khi muốn thay ảnh trong dataset thay vì chỉ xuất ảnh kiểm tra

Sau khi chạy, đừng chỉ nhìn loss training. Hãy mở vài frame trước/sau alignment. Nếu warp làm méo bàn tay hoặc đồ vật đang thao tác, policy có thể học tín hiệu sai. Nếu inpainting lấp mất vật nhỏ, giảm distance hoặc kiểm tra depth validity mask. Với robot data thật, bạn thường không cần view alignment; với human data, đây là bước giúp ảnh của người gần với input robot hơn.

Bước 4: action alignment và HDF5 robot-ready

Action alignment trong EgoHumanoid có ba phần. Upper body dùng action_eefaction_delta_eef, lower body dùng teleop_navigate_command, hand dùng hand_status. convert_to_lerobot.py trong repo mong thấy các field kiểu này trong HDF5:

action_eef               # (N, 14), pose end-effector
action_delta_eef         # (N, 12), delta end-effector action
teleop_navigate_command  # (N, 3), command điều hướng rời rạc
delta_height             # (N,), thay đổi chiều cao base/pelvis
hand_status              # (N, 2), trái/phải open-close
observation_image_left   # ảnh RGB/JPEG từ ZED

Nếu file của bạn mới có navigation và hand status nhưng chưa có EEF action, kiểm tra utility process_human_eef_pipeline.py trong thư mục human data process. README ghi utility này tính hand end-effector poses 7D và delta 6D từ skeleton data. Với tutorial beginner, cách kiểm tra tốt nhất là dùng h5py in ra keys và shape:

python - <<'PY'
import h5py

path = "/data/ego/final/episode_0.hdf5"
with h5py.File(path, "r") as f:
    for key in [
        "action_eef",
        "action_delta_eef",
        "teleop_navigate_command",
        "delta_height",
        "hand_status",
        "observation_image_left",
        "observation_image_right",
    ]:
        if key in f:
            print(key, f[key].shape, f[key].dtype)
        else:
            print("MISSING", key)
PY

Một episode tốt để convert phải thỏa ba điều kiện. Thứ nhất, số frame của action và ảnh phải khớp hoặc được loader xử lý nhất quán. Thứ hai, teleop_navigate_command không được toàn zero nếu task có di chuyển. Thứ ba, hand_status phải chuyển trạng thái ở đoạn grasp/release, không nhảy liên tục từng frame. Nếu hand_status bị rung, hãy chạy lại add_hand_status.py với cấu hình wave type hoặc transition shift thủ công thay vì để policy học nhiễu.

Bước 5: chuyển sang LeRobot

Khi HDF5 đã sạch, chuyển sang LeRobot:

cd data_alignment

python convert_to_lerobot.py \
  --src-path /data/ego/final \
  --output-path /data/ego/lerobot \
  --repo-id egohumanoid_pick_toy_v1 \
  --fps 20 \
  --task "grasp the toy and put it on the table"

Nếu dataset lớn, dùng worker song song:

python convert_to_lerobot.py \
  --src-path /data/ego/final \
  --output-path /data/ego/lerobot \
  --repo-id egohumanoid_pick_toy_v1 \
  --num-workers 16 \
  --fps 20 \
  --task "grasp the toy and put it on the table"

Trong code, LeRobot feature chính gồm observation.images.left, action_eef, action_delta_eef, teleop_navigate, delta_heighthand_status. Lưu ý ảnh left là feature chính trong converter hiện tại; nếu bạn muốn train stereo left/right, cần mở rộng config và loader thay vì giả định right tự được dùng. Với beginner, hãy train bản left-only trước để giảm số biến.

Task instruction rất quan trọng. Đừng đặt instruction chung chung kiểu "do task". Nếu episode là nhặt đồ bỏ lên bàn, dùng câu cụ thể. Nếu episode là bỏ rác vào thùng, tách thành repo-id khác hoặc ít nhất task khác. VLA học từ ảnh, action và ngôn ngữ; task label mơ hồ làm dataset khó kiểm soát.

Bước 6: train, serve và deploy

Trước training, README EgoHumanoid yêu cầu tính normalization statistics:

uv run python scripts/compute_norm_states_ultra_fast.py \
  --config-name=norm_compute

Sau đó train:

XLA_PYTHON_CLIENT_MEM_FRACTION=0.9 \
uv run scripts/train.py pi05_g1_custom \
  --exp_name=egohumanoid_pick_toy_v1

Nếu dùng nhiều GPU:

XLA_PYTHON_CLIENT_MEM_FRACTION=0.9 \
uv run scripts/train.py pi05_g1_custom \
  --exp_name=egohumanoid_pick_toy_v1 \
  --fsdp-devices 4

Checkpoint được lưu dưới:

checkpoints/<config_name>/<exp_name>/<iteration>

Khi có checkpoint, chạy policy server:

uv run scripts/serve_policy.py policy:checkpoint \
  --policy.config=pi05_g1_custom \
  --policy.dir=checkpoints/pi05_g1_custom/egohumanoid_pick_toy_v1/10000

Server mặc định nghe port 8000. Phía robot/client chạy:

cd /root/Projects/openpi

python scripts/deploy.py \
  --host <server_ip> \
  --port 8000

Đây là nơi phải quay lại bài 1 và bài 2 về safety. Đừng deploy lên G1 thật chỉ vì server đã trả action. Kiểm tra camera mount, network, emergency stop, low-level locomotion policy, workspace không có người đứng sát robot, và thử task ngắn với tốc độ thấp. EgoHumanoid giúp policy học từ human data, nhưng nó không xóa các rủi ro của whole-body robot thật.

EgoHumanoid hay TWIST2: thu robot trực tiếp hay tận dụng human demos?

Câu hỏi TWIST2 EgoHumanoid
Dữ liệu chính Robot teleoperation trực tiếp Human egocentric demos + robot data giới hạn
Điểm mạnh Action/state gần robot thật, ít embodiment gap Scale nhanh hơn, đa dạng môi trường hơn, không cần robot cho mọi demo
Điểm yếu Tốn thời gian robot, operator mệt, khó mở rộng scene Cần view/action alignment, dễ sai nếu HDF5 không sạch
Camera Robot-centric active vision trong teleop Human headset/ZED được align sang viewpoint robot
Lower-body signal Command từ teleop/retarget trực tiếp Pelvis trajectory -> teleop_navigate_command
Hand signal Robot hand command/tracking Human hand pose -> hand_status
Khi nên chọn Lab đã có G1 ổn định, muốn imitation data chính xác Lab muốn tận dụng người demo ở nhiều bối cảnh, robot time hạn chế

Cách ra quyết định thực tế: nếu task đòi hỏi contact chính xác, lực tinh tế hoặc robot morphology quyết định thành bại, hãy thu robot data trực tiếp trước. Ví dụ kéo xe nặng, mở tay nắm khó, thao tác ở rìa workspace của G1. Nếu task chủ yếu cần hiểu scene, di chuyển tới vật, grasp/release ở mức tương đối và nhiều biến thể môi trường, EgoHumanoid rất đáng thử vì human demos rẻ hơn robot demos.

Một lab tốt không cần chọn tuyệt đối. Dùng TWIST2 để tạo robot dataset sạch cho vài task lõi. Dùng EgoHumanoid để mở rộng diversity: nhiều phòng, nhiều vị trí đồ vật, nhiều cách tiếp cận. Sau đó co-train để policy vừa có grounding robot thật, vừa thấy nhiều cảnh mà robot chưa từng được teleop trực tiếp.

Checklist debug trước khi train dài

Kiểm tra Command/cách làm Kỳ vọng
HDF5 có key cần thiết h5py in keys và shape Không thiếu teleop_navigate_command, image, hand_status, EEF action
FPS hợp lý Kiểm tra metadata và frame count Human data sau downsample thường về 20 Hz
Camera sync Xem timestamp_diff_ms Không có spike lớn kéo dài
Navigation không toàn zero Plot hoặc in unique command Task có đi bộ thì command phải đổi
Hand status có nghĩa Plot hai cột trái/phải Chuyển trạng thái ở grasp/release
View alignment không phá vật Mở frame trước/sau Vật và bàn tay vẫn nhận ra được
LeRobot load được Chạy smoke train nhỏ Dataloader không lỗi image/action shape

Nếu một trong các dòng trên lỗi, đừng train qua đêm. VLA có thể giảm loss trên dữ liệu bẩn, nhưng robot thật sẽ phơi bày lỗi rất nhanh. Với EgoHumanoid, chất lượng alignment quyết định giá trị của human demo.

Kết luận

EgoHumanoid là stack đáng học vì nó đưa bài toán humanoid VLA ra khỏi giới hạn "có bao nhiêu giờ robot teleop". Thay vì coi human videos là tham khảo thị giác rời rạc, EgoHumanoid biến chúng thành dataset có schema gần robot: ảnh egocentric đã align viewpoint, teleop_navigate_command cho lower body, action_delta_eef cho tay và hand_status cho grasp. Khi convert sang LeRobot và train bằng scripts/train.py, bạn có một đường đi rõ ràng từ human demo tới policy triển khai trên G1.

Nhưng lợi thế này chỉ có ý nghĩa nếu dữ liệu được kiểm tra cẩn thận. run_human_data_pipeline.sh, viewport_transform_batch_h5.py, process_navigation_pipeline.py, add_hand_status.pyconvert_to_lerobot.py không phải các bước hành chính; chúng là nơi embodiment gap được thu hẹp. Nếu xem chúng như black box, EgoHumanoid sẽ cho bạn một dataset đẹp tên nhưng khó dùng. Nếu debug từng field HDF5, bạn có một cách mở rộng data thực dụng cho whole-body VLA 2026.

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

TWIST2: PICO teleop và G1 sim2real
wholebody-vla

TWIST2: PICO teleop và G1 sim2real

11/6/202617 phút đọc
NT
VIRAL: RGB sim2real cho G1 loco-manip
wholebody-vla

VIRAL: RGB sim2real cho G1 loco-manip

11/6/202616 phút đọc
NT
FRoM-W1: text → motion → G1 policy
wholebody-vla

FRoM-W1: text → motion → G1 policy

11/6/202617 phút đọc
NT