Mục tiêu của bài này
Năm bài đầu đã đưa ta từ bản đồ pipeline WholeBodyVLA, video egocentric, retarget motion, teleoperation đến huấn luyện tracker và LMO RL. Bài 6 là chặng kiểm định trước khi động đến Unitree G1 thật. Đây là phần ít hào nhoáng nhất nhưng lại là phần quyết định nhóm của bạn có mất một buổi debug hay mất một robot.
Nếu bạn chưa đọc các bước nền, nên xem lại Bản đồ pipeline WholeBodyVLA, Retarget humanoid, Teleoperation fine-tuning, và Huấn luyện tracker và LMO RL. Ngoài series, hai bài nền hữu ích là pipeline sim-to-real cho robotics và thu thập dữ liệu GROOT N1 trên G1.
Ta sẽ xây checklist từ hai repo thật:
| Repo | Lệnh/tài sản chính | Vai trò trong checklist |
|---|---|---|
| TWIST | assets/twist_general_motion_tracker.pt, server_high_level_motion_lib.py, server_low_level_g1_sim.py, server_low_level_g1_real.py --net |
Pipeline đầy đủ từ checkpoint JIT, Redis motion server, MuJoCo low-level sim đến G1 thật |
| GMT | sim2sim.py --robot g1 --motion walk_stand.pkl, view_motion.py --motion walk_stand.pkl |
Bộ kiểm nhẹ để xem motion và đánh giá tracking trong MuJoCo trước khi đưa vào stack nặng hơn |
Ý tưởng chính: đừng coi sim-to-real là một lệnh cuối cùng. Hãy coi nó là một chuỗi cổng kiểm. Một motion phải qua kiểm file, kiểm kinematic view, kiểm policy trong sim, kiểm Redis, kiểm checkpoint, kiểm network, rồi mới được phép đi tới robot thật.
motion.pkl
-> view_motion.py
-> sim2sim.py
-> TWIST high-level motion server
-> TWIST low-level MuJoCo sim
-> network dry-run
-> G1 in hoist / damping / supervised deployment
Vì sao phải kiểm theo tầng?
Một beginner thường hỏi: "Nếu repo đã có checkpoint, tại sao không chạy thẳng server_low_level_g1_real.py?" Vì lỗi của humanoid không xuất hiện theo kiểu dễ chịu. Một sai khác nhỏ trong thứ tự joint, scale action, frame quaternion, kích thước observation, hoặc interface mạng có thể biến thành cú giật ở chân, mất cân bằng thân, hoặc controller đọc command cũ từ Redis.
Trong TWIST, README nói rõ repo cung cấp student checkpoint đã train ở assets/twist_general_motion_tracker.pt và có thể dùng trực tiếp cho deployment. Nhưng chính README cũng tách pipeline thành hai lớp: high-level control gửi motion target và low-level control chạy policy RL. Low-level sim được chạy trước để robot đứng yên, sau đó high-level motion server mới phát motion qua Redis. Với robot thật, README yêu cầu kết nối Ethernet, đặt IP laptop 192.168.123.222 với netmask 255.255.255.0, ping robot 192.168.123.164, đưa G1 vào dev mode bằng L2+R2, kiểm tra joint ở damping state, rồi mới chạy low-level real server với --net.
GMT đi theo hướng nhẹ hơn. README của GMT nói codebase hỗ trợ MuJoCo simulation cho Unitree G1, cung cấp checkpoint pretrained và vài motion mẫu. Hai lệnh quan trọng là:
python sim2sim.py --robot g1 --motion walk_stand.pkl
python view_motion.py --motion walk_stand.pkl
Đây là công cụ rất tốt để lọc motion trước khi dùng stack TWIST. view_motion.py giúp xem motion kinematic: robot có tự xuyên sàn không, chân có trượt vô lý không, root height có nhảy không. sim2sim.py đưa policy vào vòng kín MuJoCo: motion không chỉ "nhìn được" mà còn phải "track được".
Checklist 0: khoanh vùng trách nhiệm
Trước khi chạy bất kỳ lệnh nào, hãy phân vai trong hệ thống. Với WholeBodyVLA, bạn có nhiều tầng:
| Tầng | Đầu vào | Đầu ra | Lỗi thường gặp |
|---|---|---|---|
| Motion file | .pkl từ retarget hoặc dataset |
root pose, joint pose, velocity | Sai robot, sai FPS, thiếu key, joint order lệch |
| High-level motion server | motion frame theo thời gian | action_mimic_g1 trong Redis |
Redis chưa chạy, publish sai shape, motion hết mà không reset |
| Low-level policy | mimic obs + proprioception + history | target joint/action | Checkpoint không phải TorchScript, obs dim lệch, chạy nhầm device |
| MuJoCo sim | action target | trạng thái robot mô phỏng | XML không khớp policy, actuator order sai, gain quá mạnh |
| Real G1 | target joint qua SDK | chuyển động thật | sai interface mạng, robot chưa vào dev mode, không có treo an toàn |
Một checklist tốt không chỉ hỏi "lệnh có chạy không". Nó hỏi "lệnh này chứng minh được điều gì?" Nếu view_motion.py chạy, bạn mới biết file motion đọc được và hình học sơ bộ ổn. Nếu sim2sim.py chạy, bạn biết policy GMT track được motion mẫu trong MuJoCo. Nếu server_low_level_g1_sim.py đứng yên được sau khi warm Redis, bạn biết TWIST low-level controller, checkpoint JIT và đường Redis tối thiểu đã nối. Nếu G1 ping được, bạn chỉ mới biết mạng IP đúng, chưa có nghĩa là an toàn deploy.
Checklist 1: kiểm môi trường và dependency
TWIST dùng Python 3.8, Isaac Gym, RSL-RL, Legged Gym, MuJoCo, redis[hiredis], mujoco-python-viewer, pytorch-kinematics, cùng unitree_sdk2_python nếu muốn sim-to-real. GMT cũng dùng Python 3.8, PyTorch, NumPy 1.23.0, MuJoCo và các gói visualization. Điểm beginner hay bỏ qua là cùng một motion .pkl có thể được sinh bởi môi trường NumPy khác. Chính README TWIST có Q&A nhắc vấn đề mismatch giữa NumPy của TWIST và GMR.
Tôi thường tách hai môi trường thay vì nhồi tất cả vào một conda env:
# Env nhẹ để xem và lọc motion bằng GMT
conda create -n gmt python=3.8
conda activate gmt
pip install torch torchvision torchaudio
pip install "numpy==1.23.0" pydelatin tqdm opencv-python ipdb imageio[ffmpeg] mujoco mujoco-python-viewer scipy matplotlib
# Env nặng hơn cho TWIST deploy
conda create -n twist python=3.8
conda activate twist
pip install "numpy==1.23.0" pydelatin wandb tqdm opencv-python ipdb pyfqmr flask dill gdown hydra-core imageio[ffmpeg] mujoco mujoco-python-viewer isaacgym-stubs pytorch-kinematics rich termcolor
pip install redis[hiredis]
Nếu chạy hardware thật, thêm Unitree SDK:
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
cd unitree_sdk2_python
pip3 install -e .
Trong checklist của bạn, dependency không nên chỉ là "pip install xong". Hãy ghi lại:
| Mục | Cách kiểm | Pass khi |
|---|---|---|
| Python | python --version |
đúng 3.8 nếu repo yêu cầu |
| Torch | python -c "import torch; print(torch.__version__)" |
import được trên device dự kiến |
| MuJoCo | python -c "import mujoco; print(mujoco.__version__)" |
import không lỗi |
| Redis | redis-server --daemonize yes rồi redis-cli ping |
trả về PONG |
| Unitree SDK | import hoặc chạy ví dụ SDK | chỉ cần cho bước real |
Không cần vội tối ưu. Mục tiêu giai đoạn này là một môi trường lặp lại được. Nếu lệnh hôm nay chạy nhưng ngày mai không ai biết dùng env nào, bạn chưa có pipeline deploy.
Checklist 2: kiểm motion file bằng GMT
Motion file là nơi nhiều lỗi bị che giấu. Một file .pkl có thể load được nhưng vẫn không phù hợp với G1: root height quá thấp, chân xuyên sàn, arm joint vượt giới hạn, hoặc tốc độ xoay yaw quá mạnh. Vì vậy bước đầu tiên nên là xem motion kinematic.
Trong GMT:
python view_motion.py --motion walk_stand.pkl
Khi thay motion, hãy dùng file trong folder motions của GMT hoặc file bạn đã retarget:
python view_motion.py --motion your_motion.pkl
Bạn cần xem ít nhất năm điểm:
| Điểm kiểm | Dấu hiệu ổn | Dấu hiệu lỗi |
|---|---|---|
| Root height | pelvis không nhảy bất thường | thân rơi xuống sàn hoặc bật lên |
| Foot contact | chân chạm sàn hợp lý | chân xuyên sàn, trượt ngang liên tục |
| Joint range | tay/chân không gập vô lý | elbow/knee đảo chiều hoặc rung |
| Heading | yaw đổi mượt | robot xoay đột ngột 180 độ |
| Loop/reset | hết motion không giật mạnh | frame cuối về default quá gấp |
Sau đó chạy sim2sim:
python sim2sim.py --robot g1 --motion walk_stand.pkl
Với motion khác:
python sim2sim.py --robot g1 --motion your_motion.pkl
sim2sim.py là bài kiểm khó hơn view_motion.py. Kinematic viewer chỉ phát lại pose tham chiếu. Sim2sim cho robot động lực học cố gắng bám pose đó. Nếu motion trông đẹp trong viewer nhưng policy không track được, nguyên nhân thường là motion quá nhanh, contact không khả thi, root velocity không khớp khả năng chân, hoặc joint target nằm ngoài vùng policy đã học.
Hãy lưu kết quả bằng một bảng đơn giản:
| Motion | view_motion.py |
sim2sim.py |
Quyết định |
|---|---|---|---|
walk_stand.pkl |
pass | pass | dùng làm smoke test |
door_push.pkl |
pass | fail ở đoạn xoay | cắt clip hoặc retarget lại |
kick_fast.pkl |
foot xuyên sàn | không chạy | loại bỏ |
Beginner nên bắt đầu với motion đơn giản như walk, stand, squat nhẹ. Đừng test cú đá, chạy nhanh, xoay gấp hoặc thao tác hai tay dài ngay từ đầu. Sim-to-real tốt là tăng độ khó có kiểm soát.
Checklist 3: kiểm checkpoint JIT/PT
TWIST cung cấp assets/twist_general_motion_tracker.pt như trained student checkpoint. README cũng có bước export student policy sang JIT bằng:
bash to_jit.sh 0927_twist_rlbcstu
Kết quả mẫu trong README là một file *-jit.pt trong thư mục traced. Điều cần hiểu: file .pt dùng để deploy trong server_low_level_g1_sim.py và server_low_level_g1_real.py được load bằng torch.jit.load. Vì vậy file phải là TorchScript/JIT, không chỉ là checkpoint training bình thường chứa state_dict.
Smoke test tối thiểu:
python - <<'PY'
import torch
path = "assets/twist_general_motion_tracker.pt"
policy = torch.jit.load(path, map_location="cpu")
policy.eval()
print(type(policy))
PY
Nếu lệnh này fail, đừng thử trong MuJoCo và càng không thử trên G1. Hãy kiểm lại đường dẫn, file tải có đầy đủ không, hoặc bạn có đang dùng nhầm checkpoint training chưa trace không.
Sau đó kiểm metadata thực tế:
ls -lh assets/twist_general_motion_tracker.pt
sha256sum assets/twist_general_motion_tracker.pt
Bạn không cần hash "chuẩn" nếu repo không công bố, nhưng bạn cần hash nội bộ để cả team biết mọi người đang deploy cùng một file. Với robot thật, "tôi nghĩ là cùng checkpoint" không đủ.
Checklist 4: warm Redis và chạy TWIST low-level sim
Trong TWIST, high-level motion server và low-level controller trao đổi qua Redis. High-level server đọc motion .pkl, dựng mimic observation, rồi publish vào các key như action_mimic_g1. Low-level controller đọc mimic obs và proprioception, chạy policy, rồi gửi target vào MuJoCo hoặc robot thật.
Trước hết bật Redis:
redis-server --daemonize yes
redis-cli ping
Warm Redis bằng high-level motion server:
cd deploy_real
python server_high_level_motion_lib.py --motion_file PATH/TO/YOUR/MOTION/FILE
Theo README TWIST, lần đầu chạy low-level sim cần warm Redis trước. Sau đó chạy low-level simulation server:
python server_low_level_g1_sim.py --policy_path ../assets/twist_general_motion_tracker.pt
Mục tiêu ban đầu không phải là robot đi ngay. README mô tả lệnh này sẽ khởi động mô phỏng chỉ chạy low-level controller, vì TWIST tách high-level control khỏi low-level RL policy. Kỳ vọng đầu tiên là robot đứng yên được.
Khi low-level sim đã mở, chạy high-level server với visualization:
python server_high_level_motion_lib.py --motion_file PATH/TO/YOUR/MOTION/FILE --vis
Luồng kiểm đúng là:
- Redis trả
PONG. - High-level server publish mimic obs, không crash ở
MotionLib. - Low-level sim load được
twist_general_motion_tracker.pt. - MuJoCo hiện G1, không lỗi XML.
- Robot đứng yên khi chưa phát motion.
- Robot bắt đầu bám motion khi high-level server publish.
- Khi dừng high-level server, motion quay về default đủ mượt.
Nếu low-level sim báo không đọc được action_mimic_g1, đừng sửa policy. Đó thường là lỗi Redis hoặc high-level server chưa publish đúng. Nếu policy load được nhưng observation dimension mismatch, kiểm lại checkpoint và script có cùng version repo không. Nếu robot trong sim rung mạnh dù motion rất đơn giản, kiểm XML, action scale, stiffness/damping và thứ tự actuator.
Checklist 5: dry-run mạng G1
Chỉ sau khi motion và low-level sim ổn, mới chuyển sang mạng robot. README TWIST mô tả pipeline sim2real cho Unitree G1 như sau: bật robot, nối laptop và robot bằng Ethernet, cấu hình interface laptop với IP 192.168.123.222 và netmask 255.255.255.0, ping 192.168.123.164, dùng remote G1 vào dev mode bằng L2+R2, thấy joint ở damping state, rồi chạy low-level real server với --net.
Ví dụ trên Linux, giả sử interface là enp3s0:
ip link show
sudo ip addr flush dev enp3s0
sudo ip addr add 192.168.123.222/24 dev enp3s0
sudo ip link set enp3s0 up
ping 192.168.123.164
Checklist mạng:
| Mục | Lệnh/thao tác | Pass khi |
|---|---|---|
| Interface đúng | ip link show |
thấy cổng Ethernet nối G1 |
| IP laptop | ip addr show enp3s0 |
có 192.168.123.222/24 |
| Robot reachable | ping 192.168.123.164 |
latency ổn định, không packet loss |
| Dev mode | remote L2+R2 |
joint vào damping state |
| Người giám sát | kiểm vật lý | robot treo hoặc có không gian an toàn |
Đừng chạy real server khi robot đứng tự do lần đầu. Tài liệu Unitree trong repo nói robot nên bắt đầu ở trạng thái treo/hoisting, vào zero torque hoặc damping, rồi mới đưa dần về default position và motion control. Với research controller, luôn có người cầm remote, có phương án cắt nguồn/thoát, và có khoảng trống quanh robot.
Checklist 6: chạy server_low_level_g1_real.py --net
Khi tất cả cổng trước đã pass, lệnh real trong TWIST có dạng:
cd deploy_real
python server_low_level_g1_real.py \
--policy_path ../assets/twist_general_motion_tracker.pt \
--net enp3s0
Trong script real, controller tạo G1RealWorldEnv(net=net, config=...), load policy bằng torch.jit.load, lấy trạng thái robot, publish proprioception vào Redis, đọc action_mimic_g1, ghép observation history, chạy policy, clip action, rồi gửi target joint xuống robot. Nói cách khác, real server không tự sinh motion. Nó cần high-level server đang publish mimic obs giống bước sim.
Sau khi low-level real server đã vào trạng thái giữ an toàn, phát motion bằng:
python server_high_level_motion_lib.py --motion_file PATH/TO/YOUR/MOTION/FILE --vis
Thứ tự này quan trọng. Chạy low-level trước giúp robot có controller nhận proprioception và sẵn sàng. High-level server đến sau mới thay đổi target. Nếu chạy high-level trước quá lâu, bạn có thể đang phát một motion đã đi tới frame giữa khi low-level bắt đầu đọc. Với lần đầu, hãy dùng motion ngắn, chậm, có đoạn đứng đầu clip.
Quy tắc dừng:
| Tình huống | Hành động |
|---|---|
| Không đọc được Redis | dừng real server, quay lại sim |
| Joint giật khi vào default | dừng bằng remote/select hoặc quy trình an toàn của lab |
| Ping chập chờn | không deploy |
| Robot nghiêng liên tục | dừng, kiểm motion root và foot contact |
| Action saturate thường xuyên | quay lại kiểm scale/policy/motion |
Không có bài blog nào thay thế được quy trình an toàn của lab. Nếu bạn chưa từng deploy low-level controller trên G1, hãy coi lệnh real là thao tác của nhóm có người phụ trách hardware, không phải bài tập cá nhân.
Checklist 7: log tối thiểu cho mỗi lần thử
Một lần sim-to-real không có log thì gần như không học được gì. Bạn không cần hệ thống telemetry phức tạp ở ngày đầu, nhưng cần đủ thông tin để tái hiện:
date:
operator:
robot:
repo commit/tag:
conda env:
policy path:
policy hash:
motion path:
motion duration:
network interface:
robot IP:
result:
failure frame/time:
notes:
Với WholeBodyVLA, log này còn giúp phân loại dữ liệu. Một demo thất bại có thể vẫn hữu ích nếu biết nguyên nhân là motion infeasible, network jitter, checkpoint sai, hay hardware setup. Ngược lại, một demo "thành công" nhưng không biết dùng checkpoint nào thì không nên đưa vào dataset chính.
Một checklist gọn để in ra
| Cổng | Câu hỏi | Pass/Fail |
|---|---|---|
| File | .pkl load được, đúng robot, đúng FPS? |
|
| Viewer | view_motion.py không xuyên sàn, không joint lạ? |
|
| GMT sim2sim | sim2sim.py --robot g1 --motion ... track ổn? |
|
| Checkpoint | torch.jit.load được file .pt? |
|
| Redis | redis-cli ping trả PONG? |
|
| TWIST high-level | publish action_mimic_g1 không crash? |
|
| TWIST low-level sim | G1 đứng yên rồi bám motion trong MuJoCo? | |
| Network | laptop 192.168.123.222/24, ping 192.168.123.164? |
|
| Hardware state | G1 treo/an toàn, dev mode, damping state? | |
| Real dry-run | low-level real server load policy, không lỗi SDK? | |
| Motion real | phát motion chậm, có người giám sát, có log? |
Kết luận
Sim-to-real cho WholeBodyVLA không phải là "train xong rồi deploy". Nó là một quy trình kiểm soát rủi ro. GMT cho bạn một evaluator nhẹ để xem motion và thử tracking trong MuJoCo. TWIST cho bạn pipeline triển khai thực tế hơn: checkpoint JIT, Redis high-level motion server, low-level MuJoCo sim, rồi low-level real server qua network interface của Unitree G1.
Nếu mỗi motion đều đi qua view_motion.py, sim2sim.py, warm Redis, server_low_level_g1_sim.py, kiểm checkpoint, kiểm IP và chỉ sau đó mới tới server_low_level_g1_real.py --net, bạn đã giảm phần lớn lỗi nguội trước khi robot thật chịu lực. Bài cuối của series sẽ chuyển từ "chạy được" sang "đánh giá được": metric nào cho tracking, stability, task success và chất lượng dữ liệu WholeBodyVLA.