Thu thập dữ liệu cho OpenArm: Từ mở hộp đến 50 episodes gắp carton
Bạn đã hiểu lý thuyết về SimpleVLA-RL — framework dùng Reinforcement Learning để cải thiện VLA model trong simulation. Bạn cũng đã nắm được kiến trúc OpenArm và tại sao nó là nền tảng phần cứng lý tưởng cho các thí nghiệm manipulation. Giờ là lúc bắt tay vào phần thực hành quan trọng nhất: thu thập dữ liệu.
Trong robotics, dữ liệu là nhiên liệu. Mô hình AI dù tốt đến đâu cũng vô dụng nếu không có dữ liệu chất lượng để học. Bài viết này sẽ hướng dẫn bạn từng bước — từ cắm dây CAN bus đến khi có 50 episodes gắp hộp carton sẵn sàng upload lên HuggingFace Hub. Nếu bạn là người mới bắt đầu, đừng lo — mình sẽ giải thích mọi thứ chi tiết, kèm theo những mẹo mà chỉ người đã làm thực tế mới biết.
Checklist phần cứng: Bạn cần gì?
Trước khi bắt đầu, hãy kiểm tra bạn đã có đủ thiết bị chưa. Đây là danh sách tối thiểu:
| Thiết bị | Mô tả | Giá tham khảo |
|---|---|---|
| OpenArm follower | Cánh tay robot thực hiện task — 6 DOF với Damiao motors | ~$3,500 (single arm) |
| OpenArm leader | Cánh tay điều khiển (teleoperation) — cùng cấu hình | Đã bao gồm trong bộ bimanual (~$6,500) |
| CAN bus USB adapter | Kết nối robot với máy tính qua giao thức CAN | ~$20-50 (CANable, PCAN-USB) |
| Linux PC với GPU | Ubuntu 22.04+, NVIDIA GPU (tối thiểu RTX 3060) | Máy bạn đang dùng |
| USB camera | Webcam thông thường, 640x480 trở lên, 30fps | ~$30-100 (Logitech C920+) |
| Hộp carton | Nhiều kích cỡ khác nhau (nhỏ, vừa, lớn) | Miễn phí — lấy từ hộp ship hàng |
| Bàn làm việc | Bề mặt phẳng, ổn định, đủ rộng cho robot hoạt động | Bàn bạn đang có |
Lưu ý quan trọng: Nếu bạn chỉ có một cánh tay (không có leader), bạn vẫn có thể thu thập dữ liệu bằng cách dùng gamepad hoặc keyboard teleop. Tuy nhiên, leader-follower teleoperation cho chất lượng dữ liệu tốt hơn đáng kể vì chuyển động tự nhiên hơn.
Bước 1: Setup CAN bus — Kết nối robot với máy tính
CAN bus (Controller Area Network) là giao thức truyền thông mà OpenArm sử dụng để giao tiếp giữa máy tính và các motor Damiao. Nếu bạn từng làm việc với xe hơi hoặc thiết bị công nghiệp, bạn đã quen với CAN. Nếu chưa — hãy nghĩ về nó như một "đường cao tốc dữ liệu" nối máy tính với từng khớp robot.
Cắm dây
- Kết nối CAN USB adapter thứ nhất vào cổng USB → nối dây CAN (CAN-H, CAN-L) vào follower arm
- Kết nối CAN USB adapter thứ hai vào cổng USB khác → nối dây CAN vào leader arm
- Đảm bảo có termination resistor 120Ω ở cuối mỗi bus (nhiều adapter đã tích hợp sẵn — kiểm tra datasheet)
Cấu hình interface
LeRobot cung cấp sẵn script setup CAN bus. Chạy lần lượt:
# Setup CAN interfaces (can0 cho follower, can1 cho leader)
lerobot-setup-can --mode=setup --interfaces=can0,can1
Lệnh này sẽ:
- Load kernel module
gs_usb(hoặccan_raw) - Set bitrate phù hợp cho Damiao motors (thường 1Mbps)
- Bring up interface
can0vàcan1
Kiểm tra kết nối
# Test xem CAN bus hoạt động không
lerobot-setup-can --mode=test --interfaces=can0,can1
Nếu thành công, bạn sẽ thấy output kiểu:
[OK] can0: Detected 6 motors (Damiao DM-J4340-2EC)
[OK] can1: Detected 6 motors (Damiao DM-J4340-2EC)
All interfaces ready!
Troubleshooting phổ biến:
- "No device found": Kiểm tra dây USB, thử cổng USB khác
- "Permission denied": Thêm user vào group
dialout:sudo usermod -aG dialout $USERrồi logout/login lại - "Timeout waiting for motors": Kiểm tra nguồn điện robot — motor cần được cấp điện trước khi giao tiếp CAN
- Chỉ detect 5/6 motors: Kiểm tra connector CAN bus tại khớp bị thiếu — có thể lỏng dây
Bước 2: Cài đặt LeRobot với hỗ trợ Damiao motors
LeRobot là framework mã nguồn mở của HuggingFace cho robot manipulation. Phiên bản mới nhất (v0.5+) đã hỗ trợ OpenArm và motor Damiao natively.
# Cài LeRobot từ PyPI
pip install lerobot
# Cài thêm driver cho Damiao motors
pip install -e ".[damiao]"
Tại sao cần .[damiao]? Damiao motors sử dụng giao thức CAN proprietary khác với Dynamixel (dùng trên SO-100/Koch). LeRobot tách driver motor thành optional dependency để package chính nhẹ hơn. Flag [damiao] cài thêm thư viện pydamiao để giao tiếp với motor qua CAN bus.
Kiểm tra cài đặt thành công:
python -c "import lerobot; print(lerobot.__version__)"
# Output: 0.5.x hoặc mới hơn
python -c "from lerobot.common.robots.openarm import OpenArmFollower; print('OpenArm OK')"
# Output: OpenArm OK
Bước 3: Calibrate follower và leader
Calibration là bước cực kỳ quan trọng mà nhiều người bỏ qua hoặc làm qua loa. Calibration xác định vị trí "zero" và giới hạn chuyển động của từng khớp. Nếu calibrate sai, robot sẽ thực hiện sai lệch so với ý bạn — và model AI học từ dữ liệu sai sẽ cho kết quả tệ.
Calibrate follower (cánh tay thực hiện)
lerobot-calibrate \
--robot.type=openarm_follower \
--robot.port=can0 \
--robot.side=right \
--robot.id=my_follower
Script sẽ yêu cầu bạn di chuyển robot đến các vị trí tham chiếu (reference positions). Với OpenArm, quy trình thường là:
- Home position: Đưa robot thẳng đứng, tất cả khớp ở 0°
- Joint limits: Di chuyển từng khớp đến giới hạn min/max
- Gripper calibration: Mở hết → đóng hết gripper
Kết quả calibration được lưu vào file ~/.cache/lerobot/calibration/my_follower.json. File này chứa offset angle và joint limits — giữ nguyên file này, không cần calibrate lại trừ khi tháo rời robot.
Calibrate leader (cánh tay điều khiển)
lerobot-calibrate \
--teleop.type=openarm_leader \
--teleop.port=can1 \
--teleop.id=my_leader
Quy trình tương tự follower. Điểm khác biệt: leader thường có gravity compensation tắt (không có motor giữ khớp) để người thao tác có thể di chuyển tự do, cảm nhận trực tiếp lực cần thiết.
Mẹo calibration từ kinh nghiệm thực tế:
- Calibrate trên bề mặt phẳng, cố định — nếu bàn rung, kết quả sẽ bị noise
- Dùng thước đo góc (protractor) hoặc level cho home position chính xác hơn
- Calibrate cả hai arm cùng phiên — đảm bảo hệ tọa độ nhất quán
- Sau calibrate, test bằng cách di chuyển leader → follower phải mirror chính xác. Nếu có offset nhỏ → calibrate lại
Bước 4: Test teleoperation — Làm quen trước khi thu thập
Teleoperation là quá trình bạn (con người) điều khiển follower thông qua leader. Đây là bước "luyện tập" trước khi bắt đầu record dữ liệu chính thức.
lerobot-teleoperate \
--robot.type=openarm_follower \
--robot.port=can0 \
--robot.side=right \
--robot.id=my_follower \
--teleop.type=openarm_leader \
--teleop.port=can1 \
--teleop.id=my_leader
Khi chạy lệnh này, follower sẽ mirror mọi chuyển động của leader theo thời gian thực. Bạn di chuyển leader bằng tay → follower làm theo.
Tại sao cần luyện tập?
Thu thập dữ liệu cho robot learning không giống quay video. Mỗi episode phải:
- Nhất quán: Cùng một task, thực hiện theo cùng pattern (không quá khác biệt giữa các episode)
- Mượt mà: Chuyển động smooth, không giật cục (jittery motion tạo ra action noise)
- Hoàn chỉnh: Bắt đầu từ vị trí sẵn sàng → thực hiện task → kết thúc ở vị trí thành công
Hãy dành 15-20 phút luyện tập thao tác gắp hộp carton trước khi record:
- Tiếp cận hộp từ trên xuống (top grasp) — dễ nhất cho gripper parallel
- Tiếp cận hộp từ bên cạnh (side grasp) — khó hơn nhưng versatile hơn
- Thử các kích cỡ hộp khác nhau
- Luyện mở gripper → hạ xuống → đóng gripper → nhấc lên → giữ ổn định
Mẹo quan trọng: Giữ tốc độ chuyển động vừa phải. Quá nhanh → follower không theo kịp (latency ~20-50ms ở 30fps). Quá chậm → episode dài, tốn disk space và training time.
Bước 5: Record dataset — 50 episodes gắp hộp carton
Đây là bước chính. LeRobot cung cấp script lerobot-record tự động hóa toàn bộ quá trình: record joint positions + camera frames → đóng gói thành dataset chuẩn.
lerobot-record \
--robot.type=openarm_follower \
--robot.port=can0 \
--robot.side=right \
--robot.id=my_follower \
--robot.cameras="{ top: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--teleop.type=openarm_leader \
--teleop.port=can1 \
--teleop.id=my_leader \
--dataset.repo_id=username/openarm-box-grasp \
--dataset.single_task="Grasp the carton box and lift it" \
--dataset.num_episodes=50 \
--dataset.fps=30
Hãy phân tích từng tham số:
--robot.cameras: Cấu hình camera.toplà tên camera (bạn đặt tùy ý).index_or_path: 0là webcam mặc định. Resolution 640x480 ở 30fps là đủ cho hầu hết task.--dataset.repo_id: Tên dataset trên HuggingFace Hub. Format:username/tên-dataset. Thayusernamebằng HuggingFace username của bạn.--dataset.single_task: Mô tả ngắn gọn task bằng tiếng Anh. Đây là language instruction mà VLA model sẽ nhận khi inference.--dataset.num_episodes: Số episode cần thu thập. 50 là mức tối thiểu để fine-tune — nhiều hơn (100-200) sẽ cho kết quả tốt hơn.--dataset.fps: Tần số lấy mẫu. 30fps nghĩa là mỗi giây ghi 30 cặp (state, action, image).
Workflow mỗi episode
Khi chạy lerobot-record, terminal sẽ hiện giao diện điều khiển:
- Press Enter để bắt đầu episode mới
- Thực hiện task: Dùng leader để điều khiển follower gắp hộp carton và nhấc lên
- Press S để kết thúc episode (success) hoặc Press F để đánh dấu failed (sẽ bị loại bỏ)
- Đặt lại hộp về vị trí mới → quay lại bước 1
Mỗi episode thường kéo dài 5-15 giây (150-450 frames ở 30fps). Tổng thời gian cho 50 episodes: khoảng 30-45 phút bao gồm thời gian reset.
Phân bổ 50 episodes thông minh
Đừng gắp cùng một hộp ở cùng vị trí 50 lần — model sẽ overfit. Thay vào đó, đa dạng hóa:
| Biến thể | Số episodes | Chi tiết |
|---|---|---|
| Hộp nhỏ (10-15cm) | 15 | 5 vị trí × 3 góc tiếp cận |
| Hộp vừa (15-25cm) | 20 | 5 vị trí × 4 góc tiếp cận |
| Hộp lớn (25-35cm) | 10 | 5 vị trí × 2 góc tiếp cận |
| Recovery từ fail | 5 | Cố tình hụt → sửa lại → gắp thành công |
Tại sao cần recovery episodes? Trong thực tế, robot sẽ gặp tình huống gắp hụt. Nếu training data chỉ có "perfect grasp", model sẽ không biết xử lý khi miss — dẫn đến failure cascade. 5-10% recovery episodes giúp model học cách tự sửa sai.
Tips chất lượng dữ liệu — Điều làm nên sự khác biệt
Thu thập dữ liệu là nghệ thuật, không chỉ là khoa học. Đây là những mẹo từ kinh nghiệm thực tế mà documentation hiếm khi đề cập:
1. Ánh sáng nhất quán
Camera là "mắt" của robot. Nếu ánh sáng thay đổi giữa các episode (mây che nắng, đèn bật/tắt), model sẽ confused. Giải pháp:
- Dùng đèn LED cố định thay vì ánh sáng tự nhiên
- Tránh bóng đổ trên workspace — dùng diffused light
- Nếu dùng ánh sáng tự nhiên, thu thập dữ liệu vào cùng khung giờ mỗi ngày
2. Background sạch
Workspace nên đơn giản, ít vật thể gây nhiễu. Robot đang học gắp hộp carton — nếu trên bàn còn chai nước, điện thoại, sách... model có thể attend vào các vật thể không liên quan. Giữ chỉ hộp carton + bề mặt bàn.
3. Camera góc cố định
Không di chuyển camera giữa các episode. Dán cố định camera hoặc dùng tripod. Nếu camera xê dịch dù chỉ vài mm, pixel-level features thay đổi → model cần nhiều dữ liệu hơn để generalize.
4. Ghi chú metadata
Tạo một file notes đơn giản:
Episode 1-15: Hộp nhỏ đỏ, vị trí trung tâm → phải
Episode 16-35: Hộp vừa nâu, vị trí trái → trung tâm
Episode 36-45: Hộp lớn trắng, vị trí random
Episode 46-50: Recovery (cố tình miss → correct)
Metadata này vô giá khi bạn cần debug model performance sau này — biết episode nào chứa biến thể nào giúp phân tích failure mode.
Sử dụng dữ liệu cộng đồng từ HuggingFace Hub
Một trong những lợi thế lớn nhất của LeRobot là hệ sinh thái dữ liệu cộng đồng. Bạn không nhất thiết phải thu thập mọi thứ từ đầu.
Duyệt dataset có sẵn
Truy cập HuggingFace Hub và tìm kiếm với keyword lerobot. Bạn sẽ thấy hàng trăm dataset từ cộng đồng:
lerobot/so100_pick_place— Dataset gắp đồ vật với SO-100 armlerobot/koch_push_cube— Đẩy khối vuông với Koch arm- Và nhiều dataset khác cho các task đa dạng
Cross-embodiment transfer learning
Đây là điểm mạnh của VLA models như SmolVLA. SmolVLA được pretrain trên dữ liệu từ nhiều loại robot khác nhau (SO-100, Koch, Franka) — nó đã học được manipulation priors tổng quát: cách tiếp cận vật thể, cách đóng/mở gripper, cách nhấc vật lên ổn định.
Khi bạn fine-tune SmolVLA trên 50 episodes OpenArm, nó không phải học từ đầu. Thay vào đó:
- Pretrained knowledge (từ hàng nghìn episodes trên SO-100/Koch) cung cấp "sense" chung về manipulation
- Fine-tune data (50 episodes OpenArm của bạn) dạy model cách adapt sang kinematics cụ thể của OpenArm
- Kết quả: hiệu quả dữ liệu cao — 50 episodes đủ để đạt 70-85% success rate
Ngược lại, nếu bạn train ACT from scratch (không có pretrained model), 50 episodes chỉ cho khoảng 40-60% success rate. Bạn cần 200-500 episodes để đạt kết quả tương đương.
Download và merge dataset
# Download dataset cộng đồng
python -c "
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset
ds = LeRobotDataset('lerobot/so100_pick_place')
print(f'Dataset: {len(ds)} frames, {ds.num_episodes} episodes')
print(f'Tasks: {ds.tasks}')
"
Bạn có thể dùng dataset cộng đồng để pretrain rồi fine-tune trên dữ liệu OpenArm của mình — cách tiếp cận này gọi là staged training và thường cho kết quả tốt hơn training trực tiếp.
Định dạng dữ liệu: LeRobotDataset
LeRobot lưu dữ liệu theo format chuẩn LeRobotDataset, được thiết kế tối ưu cho robot learning:
Cấu trúc thư mục
openarm-box-grasp/
├── meta/
│ ├── info.json # Metadata: fps, robot type, task description
│ ├── episodes.jsonl # Thông tin từng episode (timestamps, success/fail)
│ └── tasks.jsonl # Danh sách task descriptions
├── data/
│ ├── chunk-000/
│ │ ├── episode_000000.parquet # Joint states + actions
│ │ ├── episode_000001.parquet
│ │ └── ...
├── videos/
│ ├── chunk-000/
│ │ ├── top/
│ │ │ ├── episode_000000.mp4 # Camera frames
│ │ │ ├── episode_000001.mp4
│ │ │ └── ...
Parquet files chứa gì?
Mỗi file Parquet chứa một bảng với các cột:
| Cột | Mô tả | Shape |
|---|---|---|
state |
Joint positions hiện tại | (6,) cho 6-DOF |
action |
Joint positions target (command) | (6,) |
timestamp |
Thời gian trong episode | scalar |
episode_index |
Index của episode | scalar |
frame_index |
Index frame trong episode | scalar |
task_index |
Index của task | scalar |
Tự động upload lên HuggingFace Hub
Sau khi thu thập xong, lerobot-record tự động upload dataset lên HuggingFace Hub. Bạn cần đăng nhập trước:
huggingface-cli login
# Nhập token từ https://huggingface.co/settings/tokens
Dataset sẽ có URL dạng: https://huggingface.co/datasets/username/openarm-box-grasp
Bạn có thể visualize dataset trực tiếp trên Hub — xem video episodes, kiểm tra action distributions, phát hiện outliers.
Kiểm tra chất lượng dataset
Sau khi thu thập, hãy kiểm tra chất lượng trước khi train:
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset
import numpy as np
ds = LeRobotDataset("username/openarm-box-grasp")
print(f"Total episodes: {ds.num_episodes}")
print(f"Total frames: {len(ds)}")
print(f"Average episode length: {len(ds) / ds.num_episodes:.0f} frames")
# Kiểm tra action range
actions = np.array([ds[i]["action"].numpy() for i in range(len(ds))])
print(f"Action range: [{actions.min():.3f}, {actions.max():.3f}]")
print(f"Action std: {actions.std(axis=0)}")
# Kiểm tra có episode nào quá ngắn/dài không
for ep_idx in range(ds.num_episodes):
ep_len = len(ds.get_episode(ep_idx))
if ep_len < 30: # < 1 giây ở 30fps
print(f"WARNING: Episode {ep_idx} quá ngắn ({ep_len} frames)")
if ep_len > 900: # > 30 giây
print(f"WARNING: Episode {ep_idx} quá dài ({ep_len} frames)")
Red flags cần chú ý:
- Episode quá ngắn (<1s): Có thể bạn bấm kết thúc sớm
- Episode quá dài (>30s): Có thể bạn quên bấm kết thúc hoặc thao tác chậm
- Action std gần 0 ở một khớp: Khớp đó không di chuyển — kiểm tra calibration
- Action range vượt ngoài giới hạn: Calibration sai
Tổng kết và bước tiếp theo
Bạn đã hoàn thành phần quan trọng nhất của pipeline: thu thập 50 episodes gắp hộp carton trên OpenArm. Tóm tắt những gì đã làm:
- Setup CAN bus kết nối robot với máy tính
- Cài LeRobot với Damiao motor support
- Calibrate cả follower và leader arm
- Luyện tập teleoperation
- Record 50 episodes đa dạng (kích cỡ, vị trí, góc tiếp cận)
- Kiểm tra chất lượng dataset
Trong bài tiếp theo — SimpleVLA-RL (8): Train & Deploy trên OpenArm — chúng ta sẽ dùng dataset này để train 3 policy khác nhau (ACT, SmolVLA, Pi0-FAST), deploy lên robot thật, và cải thiện bằng HIL-SERL. Đó là lúc dữ liệu bạn vừa thu thập phát huy giá trị thực sự.
Nếu bạn muốn hiểu sâu hơn về quá trình training VLA models, hãy đọc phần 3 của series. Còn nếu muốn tìm hiểu cách HIL-SERL cải thiện policy trên robot thật, bài viết đó sẽ cho bạn cái nhìn tổng quan.
Bài viết liên quan
- SimpleVLA-RL (1): Tổng quan framework — Hiểu toàn bộ pipeline từ SFT đến RL trên VLA model
- SmolVLA Training với LeRobot — Hướng dẫn chi tiết fine-tune SmolVLA 450M trên dữ liệu robot
- HIL-SERL: RL trên robot thật — Cải thiện policy bằng human-in-the-loop RL