教程 · 命令逐字照录

SONIC 数据采集:给 VLA 的 LeRobot 数据集

把遥操作演示录成 LeRobot 数据集,供 Isaac-GR00T 后训练使用。数据导出器与 SONIC 部署和 VR 遥操作栈并行运行,按可配置频率捕获机器人状态、SMPL 遥操作姿态与相机图像。所有命令逐字摘自官方 Data Collection 教程

部署模型

除了相机服务器跑在机器人计算机上(如 Jetson Orin,物理相机就接在那里),其他一切都在工作站的 offboard 侧运行。相机服务器通过 ZMQ 向工作站发布 JPEG 帧。

前置要求:完成 Quick Start(sim2sim 循环,包括部署安装与模型 checkpoint 下载)、完成 VR Teleop Setup(PICO 硬件已标定、.venv_teleop 就绪),并让相机服务器在机器人上运行。仿真时,MuJoCo 仿真循环自动发布摄像头图像——无需相机服务器。

支持的相机

经过测试与支持的相机配置使用 Luxonis OAK 相机(OAK-D、OAK-1 等):一个头部/第一视角 OAK 相机,加可选的 OAK 腕部相机。其他相机驱动(RealSense、USB 摄像头)在代码库里,但最近没测过。头部/第一视角 OAK-D W 相机的 3D 打印支架在 hardware/camera_mount/ 下——README 覆盖打印设置、物料清单以及如何装到 G1 上。

一次性设置(工作站)

从仓库根目录运行安装脚本,创建带全部数据采集依赖(LeRobot、PyAV、OpenCV 等)的专用虚拟环境:

bash install_scripts/install_data_collection.sh

这会用 uv 基于 Python 3.10 创建 .venv_data_collection,安装 gear_sonic[data_collection](lerobot、av、opencv-python 等包)加上 espeak(系统包)用于录制时的语音反馈。这个环境与 .venv_teleop.venv_sim 相互独立——数据导出器有遥操作和仿真用不到的更重的 ML 依赖。

相机服务器设置(机器人侧)

相机服务器是唯一运行在机器人计算机上(如 Jetson Orin)的组件。其他所有组件——C++ 部署、PICO 遥操作流式程序、数据导出器与相机查看器——都运行在你的工作站上。它从物理连接在机器人上的 OAK 相机捕获帧,并通过 ZMQ 发布。

git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
cd GR00T-WholeBodyControl
bash install_scripts/install_camera_server.sh

脚本创建带 gear_sonic[camera](DepthAI、ZMQ、msgpack、OpenCV、tyro)的 .venv_camera,检测连接的 OAK 相机并列出它们的 MxID,逐个提示每个相机的位置(第一视角,可选左/右腕)与设备 ID,然后询问是否把相机服务器装成 systemd 服务(推荐)——回答 y 会自动生成 unit 文件、安装、启用并启动。验证:

sudo systemctl status composed_camera_server.service
journalctl -u composed_camera_server.service -f

手动替代:.venv_camera 里用 python -c "import depthai as dai; print(dai.Device.getAllAvailableDevices())" 找设备 ID,然后用 python -m gear_sonic.camera.composed_camera --ego-view-camera oak --ego-view-device-id <YOUR_MXID> --port 5555 启动服务器(腕部相机加 --left-wrist-camera / --right-wrist-camera 标志;--fps--use-mjpeg--mjpeg-quality--help)。手动 systemd:编辑 systemd/composed_camera_server.service,复制到 /etc/systemd/system/,然后 daemon-reload + enable + start。G1 机器人的默认 IP 是 192.168.123.164

ZMQ 消息格式

相机服务器每个帧周期发布一个包含所有相机图像的 msgpack 编码负载:

{
    "timestamps": { "ego_view": 1712345678.123, "left_wrist": 1712345678.125 },
    "images": { "ego_view": "<base64-jpeg>", "left_wrist": "<base64-jpeg>" }
}

图像经 JPEG 压缩(质量 80),以 base64 编码字符串或原始 JPEG 字节(启用 MJPEG 设备端编码时)传输。数据导出器的 ComposedCameraClientSensor 自动处理两种格式。

架构与 ZMQ 数据源

数据源运行在ZMQ 话题默认端口提供
C++ 部署工作站g1_debug5557关节位置、速度、IMU 四元数
C++ 部署工作站robot_config5557启动时的一次性机器人配置
PICO 遥操作流式程序工作站pose5556SMPL 身体参数(遥操作目标姿态)
相机服务器机器人(原始 TCP)5555JPEG 压缩的相机图像(第一视角 + 可选腕部视角)

数据导出器订阅全部三个 ZMQ 数据源——5557 端口的部署状态、5556 的 SMPL 遥操作姿态、5555 的相机图像——并写出 LeRobot 数据集(parquet + mp4)。

方案 A · 一体化 tmux 启动器(推荐)

启动器在单个 tmux 会话里启动全部组件,共四个窗格:C++ Deploy、PICO Teleop、Data Exporter、Camera Viewer(需要 tmuxsudo apt install tmux)。仿真(启动器会在单独的 tmux 窗口自动启动 run_sim_loop.py):

python gear_sonic/scripts/launch_data_collection.py --sim

真机(相机服务器运行在 192.168.123.164 的机器人上):

python gear_sonic/scripts/launch_data_collection.py \
    --camera-host 192.168.123.164 \
    --task-prompt "pick up the cup"

带腕部相机(录制第一视角 + 左/右腕流):

python gear_sonic/scripts/launch_data_collection.py \
    --camera-host 192.168.123.164 \
    --task-prompt "pick up the cup" \
    --record-wrist-cameras

无需先激活虚拟环境——如果当前 Python 缺必要依赖,启动器会自动检测并使用 .venv_data_collection。常用标志:--task-prompt(默认 "demo")、--dataset-name(默认:时间戳)、--sim / --no-sim--camera-host(默认 localhost)、--camera-port(5555)、--data-exporter-frequency(50)、--deploy-checkpoint--deploy-obs-config--deploy-planner--deploy-motion-data--record-wrist-cameras--no-text-to-speech。会话管理:Ctrl+b 加方向键切换窗格,Ctrl+bd 分离,tmux attach -t sonic_data_collection 重新接入,tmux kill-session -t sonic_data_collection 结束。

录制控制:PICO VR 手柄——Left Grip + A 切换录制(开始新 episode 或停止并保存),Left Grip + B 丢弃当前 episode(会存到磁盘,但在后处理时标记为移除)。键盘经 ZMQ(端口 5580):c 切换录制,x 丢弃该 episode。这些在任何 manager 模式(POSE、PLANNER 等)下都有效。

方案 B · 手动多终端设置

终端 1 —— MuJoCo 仿真器(真机跳过):

source .venv_sim/bin/activate
python gear_sonic/scripts/run_sim_loop.py \
    --enable-image-publish --enable-offscreen --camera-port 5555

终端 2 —— C++ 部署(在 gear_sonic_deploy/ 里):

cd gear_sonic_deploy
source scripts/setup_env.sh
./deploy.sh --input-type zmq_manager sim
# Wait until you see "Init done"

终端 3 —— PICO 遥操作流式程序:

source .venv_teleop/bin/activate
python gear_sonic/scripts/pico_manager_thread_server.py --manager

终端 4 —— 数据导出器:

source .venv_data_collection/bin/activate
python gear_sonic/scripts/run_data_exporter.py --task-prompt "pick up the cup"

终端 5(可选)—— 相机查看器:.venv_data_collection 里运行 python gear_sonic/scripts/run_camera_viewer.py。数据集保存在 <root-output-dir>/<dataset-name>/(默认根目录 outputs);省略 --dataset-name 用自动时间戳,或复用名字来追加 episode。独立相机查看器还录制原始 MP4 参考视频(R 开始/停止,Q 退出)到 camera_recordings/rec_<timestamp>/

录制的数据通道

特征形状描述
observation.state.joint_position(N,)被驱动的关节位置(弧度)
observation.state.joint_velocity(N,)被驱动的关节速度(弧度/秒)
observation.state.body_rotation_6d(6,)基座朝向(6D 旋转)
observation.state.projected_gravity(3,)body 系下的重力向量
observation.images.ego_view(480, 640, 3)第一视角相机图像(存为 MP4 视频)
observation.images.left_wrist(480, 640, 3)左腕相机(仅 --record-wrist-cameras 时)
observation.images.right_wrist(480, 640, 3)右腕相机(仅 --record-wrist-cameras 时)
action.joint_position(N,)遥操作目标关节位置
action.body_rotation_6d(6,)遥操作目标 body 朝向
annotation.human.action.task_descriptionstring本帧的任务提示

数据集按 LeRobot v2.1 格式保存在 <root-output-dir>/<dataset-name>/data/(parquet:关节状态、动作、标注)、videos/(每路相机流 H264 编码的 MP4)、meta/(info.json、modality.json、episodes.jsonl、tasks.jsonl)。

数据集后处理

所有命令在 .venv_data_collection 里运行。移除被丢弃的 episode(用 x 或 Left Grip + B 标记)——默认行为会移除它们,确保不进入微调;传 --no-remove-discarded 保留供检查:

# Clean a single dataset (removes discarded episodes + stale SMPL frames)
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/my_dataset \
    --output-path outputs/my_dataset_cleaned

移除过期 SMPL 帧——遥操作暂停或 ZMQ 丢帧会产生 teleop.smpl_pose 全为零的帧;脚本还会移除它们前面连续冻结(相同)的引入帧。可原地或非破坏处理:

# Clean a single dataset in-place
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/my_dataset

# Clean and write to a new directory (non-destructive)
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/my_dataset \
    --output-path outputs/my_dataset_cleaned
VR_3PT 陷阱:如果你用 VR 3 点跟踪模式(VR_3PT)采集,teleop.smpl_pose 全是零,因为 VR_3PT 用原始 VR 位置/朝向而不是 SMPL 身体参数。你必须禁用 SMPL 清理,否则会丢光所有帧:
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/my_dataset \
    --output-path outputs/my_dataset_cleaned \
    --no-remove-stale-smpl

合并多个数据集(会验证所有会话共享相同的 script_config 机器人配置):

# Merge by listing datasets on the command line
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/session1 outputs/session2 outputs/session3 \
    --output-path outputs/merged_dataset

# Or use a text file (one dataset path per line, # for comments)
python gear_sonic/scripts/process_dataset.py \
    --dataset-list datasets.txt \
    --output-path outputs/merged_dataset

SMPL 清理在合并时默认生效——它会移除 SMPL 遥操作姿态卡在零的整帧(操作员暂停、ZMQ 丢包时段),外加进入零段前的连续冻结帧。加 --no-remove-stale-smpl 跳过清理只合并。输出数据集直接兼容 Isaac-GR00T 后训练管线——下一步是VLA 全流程

BONES-SEED:离线动作语料

除了你自己的遥操作演示,训练数据栈还构建在 BONES-SEED 之上——一个开放数据集,包含 142,220 段带标注的人体动作动画(71,132 原始 + 71,088 镜像,120 fps 下约 288 小时),来自 522 位演员,带自然语言描述与时间分段,提供 SOMA 与 Unitree G1 两种格式。每段动作有三种格式:SOMA Proportional(BVH)、SOMA Uniform(BVH)与重定向到 G1 人形机器人的 Unitree G1(CSV)。下载:

# Using the Hugging Face CLI
pip install huggingface_hub
huggingface-cli download bones-studio/seed --repo-type dataset --local-dir ./bones-seed

SONIC 训练时,G1 CSV 用 convert_soma_csv_to_motion_lib.py(--fps 30 --fps_source 120)转换、用 filter_and_copy_bones_data.py 过滤,然后通过 --training Hugging Face 下载消费 SMPL 数据——完整命令在训练页Training Data 文档里。

数据采集常见问题

为 VLA 微调采集数据需要真机吗?
不需要——all-in-one 启动器支持仿真:python gear_sonic/scripts/launch_data_collection.py --sim 会在单独的 tmux 窗口里自动启动 run_sim_loop.py,MuJoCo 仿真循环在相机端口发布摄像头图像(无需相机服务器)。真机路径额外要求机器人上运行相机服务器。
相机服务器跑在哪里,其他组件跑在哪里?
相机服务器是唯一运行在机器人计算机(如 Jetson Orin)上的组件,那里接着物理 OAK 相机,通过 ZMQ 发布 JPEG 帧。其他所有组件——C++ 部署、PICO 遥操作流式程序、数据导出器与相机查看器——都运行在工作站的 offboard 侧。
为什么处理时我的整个数据集被丢弃了?
如果你用 VR 3 点跟踪模式(VR_3PT)采集,teleop.smpl_pose 列全是零,因为 VR_3PT 用原始 VR 位置/朝向而不是 SMPL 身体参数。默认的 SMPL 清理会因此移除所有帧——这种情况必须给 process_dataset.py 传 --no-remove-stale-smpl。
数据采集支持哪些相机?
经过测试与支持的是 Luxonis OAK 相机(OAK-D、OAK-1 等):一个头部/第一视角 OAK 相机,加可选的 OAK 腕部相机。头部/第一视角 OAK-D W 相机的 3D 打印支架在 hardware/camera_mount/,带打印设置与物料清单。代码库里存在 RealSense 与 USB 摄像头驱动,但最近没测过。