Task4:SO-101 实机数据采集与 LeRobot Dataset 上传

一、任务介绍

本次任务使用 SO-101 领臂遥操作从臂,采集机械臂抓取瓶子并将其放到国旗旁边的演示数据。
(Task3是关于搭建相机与机械臂系统(Eye-in-Hand 或 Eye-to-Hand)略过了)

任务名称:

Place the bottle next to the national flag

采集的数据包括:

  • 机械臂六个关节状态;
  • 领臂下发的动作;
  • wrist 摄像头图像;
  • 时间戳及 episode、frame、task 索引。

数据最终保存为 LeRobot Dataset v3 格式,并上传至 Hugging Face。


二、遥操作测试

正式录制前,先测试领臂、从臂和摄像头能否正常工作。

lerobot-teleoperate \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodem5B3D0458541 \
  --robot.id=monica_follower_arm \
  --robot.cameras='{wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}' \
  --teleop.type=so101_leader \
  --teleop.port=/dev/tty.usbmodem5B3D0457201 \
  --teleop.id=monica_leader_arm \
  --display_data=true

测试通过后,可以通过领臂控制从臂,同时查看 wrist 摄像头画面。


三、采集数据

使用以下命令录制数据:

lerobot-record \
  --robot.type=so101_follower \
  --robot.port=/dev/tty.usbmodem5B3D0458541 \
  --robot.id=monica_follower_arm \
  --robot.cameras='{wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}' \
  --teleop.type=so101_leader \
  --teleop.port=/dev/tty.usbmodem5B3D0457201 \
  --teleop.id=monica_leader_arm \
  --display_data=true \
  --dataset.repo_id=feng0724821/so101_test_record \
  --dataset.root=/Users/cx330/.cache/huggingface/lerobot/feng0724821/so101_test_record_20260721_165456 \
  --dataset.push_to_hub=false \
  --dataset.single_task="Place the bottle next to the national flag" \
  --resume=true \
  --dataset.num_episodes=20 \
  --dataset.episode_time_s=30 \
  --dataset.reset_time_s=5

其中:

  • --resume=true:继续向已有数据集追加轨迹;
  • --dataset.num_episodes=20:本次录制20条;
  • --dataset.episode_time_s=30:单条轨迹最长30秒;
  • --dataset.reset_time_s=5:两条轨迹之间预留5秒复位。

录制时的按键如下:

→:保存当前 episode,进入下一条
←:取消当前 episode,重新录制
ESC:停止录制并完成视频编码

失败、掉落或动作不完整的轨迹直接按左方向键取消。


四、双摄像头问题

原计划同时使用 wristfront 两个摄像头,但在 MacBook Air 上无法稳定运行。

实际现象:

  • 两个摄像头单独测试都能出图;
  • 只打开 wrist 时可以正常遥操作;
  • 同时打开两路摄像头时,第二路持续出现 read failed
  • 调整分辨率、warmup 和 MJPG 后仍然失败。

由于 MacBook Air 接口较少,机械臂和摄像头需要通过扩展坞连接。当前 USB 连接条件下,两路视频无法稳定并发读取,因此最终只使用:

wrist:640×480,30 fps

另外,将摄像头设置为15 fps时出现:

OpenCVCamera(0) failed to set fps=15
actual_fps=30

说明该摄像头在当前模式下实际只能稳定运行在30 fps,因此不能强制设置为15 fps。


五、读取数据集

录制完成后,使用 LeRobotDataset 检查数据:

from pathlib import Path
from lerobot.datasets.lerobot_dataset import LeRobotDataset

root = Path(
    "~/.cache/huggingface/lerobot/"
    "feng0724821/so101_test_record_20260721_165456"
).expanduser()

ds = LeRobotDataset(
    "feng0724821/so101_test_record",
    root=root,
)

print("episodes:", ds.num_episodes)
print("frames:", ds.num_frames)
print("fps:", ds.fps)

frame = ds[0]
print(frame.keys())
print("state:", frame["observation.state"].shape)
print("action:", frame["action"].shape)
print("image:", frame["observation.images.wrist"].shape)

正式数据中的主要字段为:

observation.state
observation.images.wrist
action
timestamp
episode_index
frame_index
task_index

observation.stateaction 都是六维,对应 SO-101 的五个关节和夹爪。项目中的验证脚本也采用 LeRobotDataset 检查数据集帧数、episode 数和字段结构。


六、上传至 Hugging Face

确认数据集读取正常后,执行:

hf upload feng0724821/so101_test_record \
  <最终数据集本地目录> \
  --repo-type dataset

例如:

hf upload feng0724821/so101_test_record \
  ~/.cache/huggingface/lerobot/feng0724821/so101_test_record_20260721_165456 \
  --repo-type dataset

上传时要确保该目录与录制命令中的 --dataset.root 完全一致,避免误上传旧版本数据。


七、结果

最终完成了以下工作:

  • SO-101 领臂与从臂遥操作;
  • 单路 wrist 摄像头数据采集;
  • 使用 --resume=true 分批追加 episode;
  • 数据保存为 LeRobot Dataset v3;
  • 使用 LeRobotDataset 成功读取;
  • 将数据集上传到 Hugging Face。

数据集:

feng0724821/so101_test_record

代码仓库:

LongtermFcq/lerobot-so101-vla-end2end-demo

LeRobot 官方文档也提供了 SO-101 的连接、遥操作和数据采集流程,可用于核对设备配置。(huggingface.co)

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐