unifolm-vla + Unitree G1 (Bài 2): thu thập dữ liệu với xr_teleoperate + Meta Quest 3
Đây là bài 2 của series unifolm-vla + Unitree G1. Bài trước đã giải thích kiến trúc tổng thể. Bài này: cách thu thập dữ liệu teleoperation chất lượng cao trên G1 thật bằng Meta Quest 3.
Dữ liệu là xương sống của VLA. Chất lượng dữ liệu quyết định chất lượng policy. Với 50 demo tốt, VLA có thể học pick-and-place đơn giản. Với 50 demo kém, không có bao nhiêu training cũng cứu được.
Tại sao cần teleoperation?
VLA cần demonstration data — chuỗi video + trạng thái joint của người điều khiển robot làm task. Không thể dùng scripted path vì:
- Generalization: VLA cần thấy các biến thể tự nhiên (góc cầm, vị trí vật thể hơi lệch, v.v.)
- Language grounding: Mỗi demo đi kèm language instruction ("pick up the red cup") → VLA học ánh xạ ngôn ngữ → hành động
- Natural motion: Human motion có sự mượt mà mà scripted path thiếu → policy mượt hơn
Teleoperation qua VR headset là cách hiệu quả nhất hiện tại: operator nhìn qua camera của robot, dùng tay cầm controller VR để điều khiển cánh tay robot ở tỉ lệ 1:1.
Thiết bị cần thiết
Lựa chọn headset
| Headset | Giá (USD) | Độ trễ | Tracking quality | Ghi chú |
|---|---|---|---|---|
| Meta Quest 3 | ~500 | ~40ms | Tốt | Khuyến nghị — cân bằng giá/chất lượng |
| PICO 4 Ultra | ~400 | ~45ms | Khá | Phổ biến ở VN, Trung Quốc |
| Apple Vision Pro | ~3,500 | ~30ms | Xuất sắc | Tốt nhất nhưng đắt nhất |
Series này dùng Meta Quest 3 làm ví dụ. PICO 4 Ultra có setup tương tự.
Hardware checklist
[ ] Unitree G1 với Dex3 hands (tay 3 ngón)
[ ] Meta Quest 3 (đầy pin trước khi demo)
[ ] PC/workstation Ubuntu 20.04 hoặc 22.04 (đã setup conda)
[ ] Cable LAN từ workstation đến G1 (KHÔNG dùng WiFi)
[ ] Camera Intel RealSense D435 gắn ở cổ tay G1
[ ] Khu vực demo: bàn cao 70-80cm, không vật cản xung quanh G1 1m
[ ] Vật thể demo (VD: cốc nhựa đỏ) ổn định trên mặt bàn
Cài đặt xr_teleoperate
Step 1: Clone và cài environment
cd ~/unifolm_ws
git clone https://github.com/unitreerobotics/xr_teleoperate.git
cd xr_teleoperate
conda create -n xr_teleop python=3.10
conda activate xr_teleop
pip install -r requirements.txt
# Cài unitree SDK
pip install unitree_sdk2py
Step 2: Cài Quest Link app trên headset
Trên Meta Quest 3:
- Bật Developer Mode (Settings → Meta Quest Link → Developer)
- Kết nối Quest 3 cùng mạng WiFi với PC (hoặc dùng USB-C Link)
- Cài app SteamVR trên PC nếu dùng SteamVR mode
Hoặc dùng AirLink (không dây, độ trễ ~45ms thay vì ~40ms với dây).
Step 3: Verify kết nối G1
conda activate xr_teleop
# Kiểm tra interface mạng kết nối G1
ip addr show # tìm interface kết nối LAN với G1 (thường eth0 hoặc enp3s0)
python -c "
from unitree_sdk2py.core.channel import ChannelFactory
factory = ChannelFactory.Instance()
factory.Init(0, 'eth0') # thay bằng interface thực của bạn
print('G1 connected OK')
"
Cài đặt task environment
Thiết lập môi trường demo chuẩn — quan trọng vì mỗi lần demo phải consistent:
[Camera D435 ở cổ tay G1]
↓ nhìn xuống
┌─────────────────────────────────────┐
│ │
│ 🔴 [Cốc đỏ] 📦 [Hộp] │ ← Mặt bàn 70cm
│ │
└─────────────────────────────────────┘
[G1 đứng đây]
Rules để demo quality:
- Vị trí cố định: đánh dấu vị trí vật thể bằng băng keo. Mỗi demo reset về vị trí đó.
- Ánh sáng đều: tránh bóng đổ thay đổi — dùng đèn LED trắng từ góc cố định.
- Background sạch: mặt bàn màu trơn (tránh vân/hoa văn rối mắt cho VLM).
- Không có người trong frame camera trong lúc record.
Record demo đầu tiên
Chạy teleoperation
cd xr_teleoperate
conda activate xr_teleop
# Mode sim trước để test (KHÔNG dùng robot thật)
python teleop_hand_and_arm.py --ee=dex3 --sim --record
# Sau khi verify ổn, chạy với robot thật
python teleop_hand_and_arm.py --ee=dex3 --record
Flag quan trọng:
--ee=dex3— dùng với G1 có Dex3 hands (3 ngón dexterous)--sim— chạy simulation (không kết nối robot thật, để test trước)--record— bật chế độ ghi dữ liệu
Controls trong Meta Quest 3
Trong headset bạn thấy:
- Stream video từ camera G1 (bạn "đứng trong robot")
- Hai tay cầm Quest 3 = hai tay robot
Keyboard controls (trên workstation):
s = bắt đầu / dừng recording 1 demo
q = thoát script
r = reset arm về vị trí home
space = emergency stop
Quest 3 controller:
Trigger = điều khiển gripper (giữ = kẹp, thả = mở)
Joystick = không dùng (locomotion tách riêng)
Flow record 1 demo
1. Bấm s → terminal hiện: "Recording started: demo_0001"
2. Thực hiện task: nhặt cốc đỏ → đặt vào hộp
3. Bấm s → terminal hiện: "Recording stopped. Saved: demo_0001 (87 frames, 5.8s)"
4. Reset vật thể về vị trí ban đầu
5. Lặp lại từ bước 1
Output files
Dữ liệu được lưu tại:
xr_teleoperate/teleop/utils/data/
├── demo_0001/
│ ├── obs/
│ │ ├── left_wrist_rgb.mp4 # video camera trái
│ │ ├── right_wrist_rgb.mp4 # video camera phải
│ │ └── head_rgb.mp4 # video camera đầu (nếu có)
│ ├── actions.json # joint commands theo thời gian
│ └── metadata.json # task info, timestamp, robot config
├── demo_0002/
│ └── ...
└── dataset_config.json # thông tin toàn bộ dataset
Chiến lược thu thập dữ liệu tốt
Bao nhiêu demo là đủ?
| Task | Demo tối thiểu | Demo khuyến nghị |
|---|---|---|
| Pick-and-place đơn giản (1 vật, 1 vị trí) | 30 | 50-80 |
| Pick-and-place với variation (nhiều vị trí) | 80 | 120-200 |
| Pour liquid | 100 | 200+ |
| Multi-step task | 150 | 300+ |
Tips để demo chất lượng cao
1. Demo consistent nhưng có variation tự nhiên:
❌ Xấu: mỗi demo GIỐNG HỆT nhau (robot sẽ overfit)
❌ Xấu: mỗi demo quá KHÁC NHAU (robot không học được pattern)
✅ Tốt: vật thể lệch 2-5cm ngẫu nhiên, tốc độ tay hơi thay đổi
2. Bắt đầu và kết thúc sạch:
✅ Trước khi bấm s: tay ở vị trí home, task chưa bắt đầu
✅ Sau khi task xong: giữ nguyên 1-2 giây rồi mới bấm s
❌ Xấu: bắt đầu record khi tay đang di chuyển
3. Xử lý demo thất bại:
Nếu trong lúc record bạn drop vật thể hoặc làm sai:
- Bấm
sđể dừng record → demo đó bị discard - KHÔNG dùng demo thất bại để train (dữ liệu nhiễu)
4. Diversity trong variation:
# Trong 50 demos, aim for:
- 50% vật thể ở vị trí "chuẩn"
- 30% vật thể lệch trái/phải 3-5cm
- 20% vật thể lệch xa/gần 2-4cm
# KHÔNG làm:
- Lệch quá nhiều (>10cm) — khó học
- Quay vật thể quá nhiều (>45°) — tăng difficulty vô ích cho bước đầu
Verify dữ liệu sau khi thu thập
cd xr_teleoperate
conda activate xr_teleop
# Xem thống kê dataset
python scripts/dataset_stats.py --data_dir teleop/utils/data/
# Output mong đợi:
# Total demos: 52
# Valid demos: 50
# Discarded: 2 (too short < 2s)
# Mean demo length: 5.8s ± 1.2s
# Mean frames per demo: 87
# Camera coverage: left_wrist=100%, right_wrist=100%, head=0%
# Xem lại 1 demo để kiểm tra visual
python scripts/replay_demo.py --demo teleop/utils/data/demo_0001/
Số lượng kiểm tra trước khi sang bước tiếp
[ ] Ít nhất 50 valid demos (thời lượng > 2 giây mỗi demo)
[ ] Không có demo bị corrupt (kiểm tra bằng dataset_stats.py)
[ ] Dữ liệu video không bị dropout (frame rate ổn định)
[ ] actions.json có đủ joints (7+7+2+2 = 28 joints cho G1 Dex3)
[ ] Task instruction ghi rõ trong metadata.json
Troubleshooting thường gặp
Quest 3 không kết nối được với script
# Kiểm tra AirLink đang active
# Trên Quest 3: Quick Settings → AirLink → bật ON
# Sau đó chạy lại script
# Nếu vẫn không được, dùng USB-C Link cable thay AirLink
Robot arm không phản hồi
# Kiểm tra SDK version
python -c "import unitree_sdk2py; print(unitree_sdk2py.__version__)"
# Kiểm tra network interface
ping 192.168.123.1 # IP mặc định của G1
# Restart G1 communication
# (tắt/bật công tắc G1, chờ 30 giây rồi chạy lại)
Độ trễ cao (>80ms) làm teleoperation khó
- Ưu tiên dùng cable LAN thay WiFi
- Nếu dùng WiFi: đảm bảo cùng 5GHz access point, không có tường dày giữa Quest 3 và router
- Đóng tất cả ứng dụng nền trên PC
Bài tiếp theo: Data pipeline — chuyển đổi JSON thành RLDS để training.
References
- xr_teleoperate GitHub
- unitree_IL_lerobot GitHub
- TeleVision paper (arxiv:2407.01512) — kiến trúc VR teleoperation gốc



