ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

机器人操作数据采集实战:从遥操作到数据流水线搭建

机器人操作数据采集实战:从遥操作到数据流水线搭建 Figure 最近的“全球悬赏人类干活”动作本质上是在给机器人囤数据。它用远程操作的方式把真人变成数据生产者让人在采集环境中操控机器人同步记录图像、关节角度、力反馈和执行指令再拿这批真实操作数据去训练机器人模型。这个思路在具身智能领域并不算新概念但把它从实验室小规模演示推到“全球悬赏”式的规模化采集确实值得关注。对做机器人、做具身智能、做数据工程的团队来说真正有借鉴意义的不是 Figure 那台机器人本身而是它背后的“数据采集—清洗—标注—入库”流水线。如果你也想给机器人攒操作数据本地要搭什么环境数据怎么录批次怎么调度接口怎么设计这些问题都比“机器人又多聪明”更值得先想清楚。这篇文章不猜 Figure 未公开的内部实现只从公开信息和通用工程实践出发拆解一套可以在本地机器人团队里落地的一体化数据采集方案。文中的部署命令、接口示例均为通用模板实际使用时需要根据你的机器人型号、传感器和网络环境调整。1. 核心能力速览先给结论。Figure 这种“人类远程操作采集数据”的模式核心能力可以概括为以下几点能力项说明采集模式人类远程操作Teleoperation真人操控机器人记录动作与传感器数据数据用途训练机器人操作模型VLA、模仿学习、强化学习提升真实场景泛化能力数据模态图像、深度图、关节角度、速度、力/力矩、任务指令、动作轨迹数据规模Figure 未披露具体数值业界普遍认为操作数据需要达到“大规模、多样化、可复用”水平硬件门槛机器人本体、RGB-D 相机、遥操作设备、高性能存储采集端对 GPU 要求不高显存需求采集阶段主要依赖 CPU 与 IO训练阶段按模型参数和 batch size 评估启动方式仿真环境或真机 ROS 节点命令行一键启动记录脚本API 能力Figure 未公开内部接口本文给出面向自建数据平台的通用 API 设计参考批量任务可以用任务队列、目录轮询、批量脚本实现多任务采集适合场景机械臂操作、人形机器人数据采集、仿真到真机迁移、机器人数据清洗与治理这套模式的价值不在单一功能而在“用户能不能以较低成本持续生产高质量数据”。机器人操作数据不像语言模型那样有海量互联网语料可以爬取它依赖真实物理环境中的传感器记录和人类示范。所以数据采集平台的稳定性和规范化程度往往决定了后续模型训练的上限。2. 适用场景与使用边界2.1 适合谁如果你属于以下几类情况可以参考这套数据采集体系正在做机械臂抓取、开门、叠衣服、整理桌面等操作任务的团队。准备训练 VLA 模型但缺少成规模的机器人操作数据集。已经有机器人本体却主要靠人工手写脚本控制希望过渡到遥操作采集路线。做机器人仿真平台开发需要将仿真数据和真机数据统一到同一个数据集格式。做数据标注、数据治理、数据清洗相关工具链的工程师想了解机器人操作数据与普通图像数据在格式上的差异。2.2 不适合什么场景如果你的需求只是“用已有数据集跑一次模型训练”那并不需要直接搭数据采集平台。现有公开数据集和仿真平台可以解决一部分问题。另外如果团队没有专属的硬件设备和操作人员不建议一上来就做大规模真机采集先用小批量数据把训练闭环验证清楚再扩大规模更稳妥。2.3 数据合规与授权边界机器人操作数据经常包含真实环境信息。室内采集会拍到人脸、桌面物品、家庭或办公布局工厂采集可能涉及设备图纸和工艺流程人体动作捕捉还涉及肖像权。这些数据一旦进入训练集并对外发布就存在隐私和版权风险。要求是所有采集环境必须提前获得场地和人员授权涉及人脸、声音、身份证件、商业文档的内容要在预处理阶段脱敏或直接丢弃第三方人体动作数据、相机 SDK、机器人驱动代码也要确认使用许可。数据集的许可证不是可选项而是训练和发布前的硬性检查项。3. 环境准备本地数据采集的前置条件3.1 硬件清单一套完整的遥操作采集工位至少包含这些硬件设备作用建议机器人本体执行任务输出关节状态六自由度机械臂起步双机械臂覆盖更多任务遥操作设备人类输入动作指令主手、VR 手柄、动作捕捉服、键盘手柄均可RGB-D 相机采集视觉信息放在机械臂末端或固定视角校验标定力/力矩传感器记录接触信息不是必须但抓取类任务强烈建议上位机运行控制与记录程序Linux 工作站16GB 以上内存高速存储保存原始数据NVMe SSD 优先后续再迁移到大容量磁盘采集阶段对 GPU 并不敏感瓶颈通常在磁盘写入速度和传感器同步精度。如果你准备在采集过程中直接运行视觉识别或大模型推理那才需要评估 GPU 显存。3.2 软件栈下面是通用软件组合具体版本按实际机器人 SDK 和操作系统确定操作系统Ubuntu 20.04 或 22.04运行语言Python 3.8 及以上部分机器人厂商 SDK 需要 C通信框架ROS2适合多个传感器节点之间的消息同步数据记录rosbag2、HDF5、JSON、NumPy仿真平台MuJoCo、Isaac Sim、Gazebo用于先跑通流程再上真机后续训练PyTorch、CUDA、视觉编码器相关依赖如果你完全不使用 ROS 生态也可以用厂商 SDK 自带的回调接口来采集关节状态和图像。关键在于数据格式必须统一不要每个传感器一套记录方式。3.3 数据集目录设计从第一天就把目录结构和文件命名规范定好后续可以省掉大量整理时间。这里给出一个通用参考mkdir -p robot_data/raw mkdir -p robot_data/clean mkdir -p robot_data/processed mkdir -p robot_data/raw/grasp_cup_001/{rgb,depth,joint_states,force,metadata} mkdir -p robot_data/raw/grasp_cup_002/{rgb,depth,joint_states,force,metadata}每个 episode 对应的目录含义清晰后续可以做批量清洗脚本。尤其注意rgb和depth不要混合保存关节状态和力传感器数据要带时间戳否则后期做时间对齐时会非常痛苦。4. 搭建采集环境与启动方式4.1 先在仿真平台跑通流程真机采集一旦出错很容易造成设备损伤或数据作废所以建议先在仿真环境验证采集流程。MuJoCo 和 Isaac Sim 都可以输出关节状态和相机图像并且支持 Python 直接控制。先跑通流程再上真机能够省下大量调试时间。4.2 真机采集节点的启动流程真机采集大体分为三步启动相机和控制驱动、启动遥操作主程序、启动数据记录节点。以 ROS2 为例先确认相机图像和机器人话题都能正常发布# 启动相机节点设备路径按实际环境调整 ros2 run usb_cam usb_cam_node_exe \ --ros-args -p video_device:/dev/video0 \ -p image_width:1280 -p image_height:720 # 查看话题是否发布 ros2 topic list ros2 topic echo /camera/color/image_raw --once再根据机器人厂商的驱动方式启动机械臂控制节点。这一步的目的不是马上记录而是确认控制指令能从遥操作设备传到机器人关节。全部话题正常发布后再启动统一记录脚本。4.3 数据记录脚本设计一个轻量的记录器需要做到逐帧接收关节状态、图像和力传感器数据保存为可检索格式并在结束时写入任务指令和元数据。下面是一段基于 Python 的通用示例实际设备接口需要按你的 SDK 替换import h5py import numpy as np from datetime import datetime class EpisodeRecorder: def __init__(self, output_path: str): self.output_path output_path self.observations [] self.actions [] self.instructions [] def add_step(self, obs: dict, action: np.ndarray): self.observations.append(obs) self.actions.append(action.copy()) def set_instruction(self, instruction: str): self.instructions.append(instruction) def save(self): with h5py.File(self.output_path, w) as f: f.create_dataset(actions, datanp.array(self.actions)) grp f.create_group(observations) last_obs self.observations[0] for key in last_obs.keys(): if key image: continue try: grp.create_dataset(key, datanp.array([obs[key] for obs in self.observations])) except Exception: f.create_dataset(fobs_{key}, datanp.array([obs[key] for obs in self.observations])) if image in last_obs: dt h5py.special_dtype(vlennp.dtype(uint8)) imgs [obs[image] for obs in self.observations] grp.create_dataset(image, datanp.array(imgs, dtypeobject), dtypedt) f.attrs[instruction] .join(self.instructions) f.attrs[created_at] datetime.now().isoformat()这段代码的核心思路是所有传感器数据统一拼成一个序列最后一次性写入 HDF5。实际项目中图像数据量较大建议单独保存为视频或压缩帧HDF5 中只放索引路径。这里给出的是最小可运行思路。启动命令可以封装到一个脚本里python collect_episode.py \ --task grasp_cup \ --output ./robot_data/raw/grasp_cup_001.h5 \ --max_steps 600采集过程中终端会打印当前步数和关键信息。如果中途发现相机断流或关节数据异常立即终止本轮采集不要等到最后统一处理废数据会污染整个批量任务。5. 功能测试与效果验证5.1 单条轨迹测试先录一条最简单的轨迹比如“从桌上抓取纸杯”。验证目标不是动作多复杂而是数据链路是否完整。操作步骤启动记录脚本。操作者通过遥操作设备控制机械臂完成一次抓取动作。手动停止记录。检查输出文件是否生成完整。用读取脚本检查动作维度和图像数量。检查脚本示例import h5py import numpy as np with h5py.File(grasp_cup_001.h5, r) as f: actions f[actions][:] obs_group f[observations] joint obs_group[joint_positions][:] images obs_group[image][:] print(动作步数:, len(actions)) print(关节状态维度:, joint.shape) print(图像帧数:, len(images)) print(任务指令:, f.attrs[instruction])判断成功的标准很简单行动步数大于 1关节维度正确图像帧数和动作步数在时间轴上对应。如果动作步数是 0说明遥操作链路没打通如果图像帧数远小于动作步数说明采集频率存在丢帧。5.2 连续多轮与批量验证单条轨迹通过后再连续录制 5 到 10 条相同任务的轨迹验证系统是否稳定。重点观察长时间录制后磁盘写入是否变慢。多个相机之间的时间戳是否仍然同步。遥操作设备是否出现漂移或延迟。不同操作者完成同一个任务数据分布差异是否过大。如果同一任务由两个人操作关节轨迹差异很大是正常现象。你需要做的是记录操作者 ID并给每条轨迹打质量标签而不是强行让所有人动作一致。5.3 数据质量检查数据质量不能只靠人眼抽看要写自动化脚本。常见检查点包括检查维度判断标准问题示例图像完整性每帧非空、未卡死画面全黑或重复帧占比过高关节连续性关节角度无跳变传感器丢包导致角度突跳时间同步各传感器时间戳近似对齐图像时间戳与控制帧时间戳偏差过大指令匹配每条轨迹有明确任务文本任务标签为空或写错动作合理性末段回到安全位姿动作中途中断、机械臂悬停对于图像模型类的下游任务还可以在采集时加入机械臂末端位姿和速度这比只保存关节角度更利于训练。这里没有固定标准按你自己模型输入需求决定。6. 接口 API 与批量任务6.1 数据平台接口设计当采集任务从“一个人手动录”变成“多个工位同时录”就需要一个数据平台统一接收入口。下面是一段基于 Flask 的通用 API 示例不是 Figure 内部接口仅作为团队自建设计参考。from flask import Flask, request, jsonify import os app Flask(__name__) SAVE_ROOT ./robot_data/raw app.route(/api/episodes, methods[POST]) def create_episode(): meta request.get_json() task_name meta.get(task_name, unknown_task) episode_id meta.get(episode_id) operator_id meta.get(operator_id, unknown_operator) save_dir os.path.join(SAVE_ROOT, f{task_name}_{episode_id}) os.makedirs(save_dir, exist_okTrue) meta_path os.path.join(save_dir, metadata.json) with open(meta_path, w, encodingutf-8) as f: json.dump(meta, f, ensure_asciiFalse, indent2) return jsonify({status: ok, save_dir: save_dir, operator_id: operator_id}), 201 app.route(/api/episodes/episode_id/steps, methods[POST]) def add_step(episode_id): data request.get_json() # 实际项目在这里追加 step 数据到对应采集文件 return jsonify({status: ok, episode_id: episode_id, step: data.get(step)}) if __name__ __main__: app.run(host127.0.0.1, port8000)采集端调用示例curl -X POST http://127.0.0.1:8000/api/episodes \ -H Content-Type: application/json \ -d {task_name: grasp_cup, episode_id: 001, operator_id: alice}这个接口只解决元数据注册和目录创建。真正的大文件上传建议走独立上传接口或者直接共享存储目录避免 JSON 请求体太大导致超时。6.2 批量任务与其列队批量采集的关键不是并发跑几十个 ROS 节点而是定义好“任务清单”。把任务描述写到 YAML 文件里采集程序读取后自动生成批次tasks: - name: grasp_cup episodes: 100 scene: table_clean objects: [cup, bottle, can] image_height: 720 image_width: 1280 - name: open_door episodes: 50 scene: kitchen objects: [] image_height: 720 image_width: 1280采集程序按 YAML 里的任务逐条执行。每个 episode 结束后把完成状态写进一个task_progress.json这样即使进程中断也能从上次断点继续不重复采集。6.3 失败重试与产物校验批量任务一定会有失败比如机械臂走到奇异点、相机断连、操作者中途放弃。建议在任务队列里增加“重试次数”字段失败后自动标记而不是混进正常数据。对于已经生成的文件要做自动校验import requests files {file: open(grasp_cup_001.h5, rb)} resp requests.post( http://127.0.0.1:8000/api/upload, filesfiles, data{episode_id: grasp_cup_001} ) print(resp.json())上传前先做好基础校验避免无效文件占用带宽。校验逻辑可以在采集端本地执行文件存在、文件大小超过阈值、HDF5 能正常打开、关节数据非空。数据平台收到文件后再做第二轮校验两次都通过才能进入“待标注”环节。7. 资源占用与性能观察7.1 存储占用与压缩策略机器人操作数据最占空间的是视觉数据。以常见 720p RGB-D 相机、30 帧每秒为例一小时原始帧数据可能达到数 GB 到几十 GB具体取决于压缩方式、是否保存深度图以及图像编码格式。这个数字只是本地采集的通用估算不是 Figure 的官方数据。降低存储占用可以这样处理使用 H.264/H.265 视频编码保存 RGB 流而不是逐帧 PNG。深度图先做可视化压缩或者降采样后再保存。关节状态和力传感器数据使用 NumPy 格式不用每帧转 JSON。只保留有效操作片段剔除开始时长时间待机和结束后空闲的视频。7.2 采集端算力观察采集阶段的 CPU 开销主要集中在相机解码、控制频率和数据序列化上。GPU 只有在跑视觉识别或接入大模型时才有明显压力显存占用按模型规格动态变化。更稳妥的判断是采集端先不接重模型把数据录好训练阶段再单独分配 GPU 资源。如果想在采集的同时做实时动作识别需要提前压测。看到比较稳的方法是在小批量数据上验证延迟而不是直接上高分辨率实时推理。观察资源占用时可以开三个终端分别看nvidia-smi htop df -h对比写入速度、显存占用和磁盘剩余空间能快速定位瓶颈。如果htop显示 CPU 满载而磁盘写入不高说明数据处理流程有问题优先精简序列化过程。如果df -h显示磁盘快速下降说明压缩策略需要优化。7.3 常见性能瓶颈瓶颈位置表现优化方向磁盘写入采集几秒后卡顿、丢帧换 NVMe SSD降低分辨率或帧率CPU 解码图像回调延迟持续升高使用硬件编码减少图像预处理传感器同步关节数据与图像时间差越来越大使用统一时间源开启 ROS2 sim time网络传输多机采集上传卡顿改本地共享存储或分时段上传8. 常见问题与排查方法问题现象可能原因排查方式解决方案相机图像黑屏或全绿相机权限失败或曝光异常查看相机话题检查/dev/video0权限给用户加入 video 组重启相机节点关节数据为空机械臂驱动节点未启动ros2 topic list查看关节话题启动对应驱动节点验证话题输出动作与图像不同步时间戳未对齐打印动作和图像时间戳使用统一 sim time开启时间同步服务磁盘占用增长过快图像未压缩查看文件大小和帧数改用视频编码限制保存帧率批量任务中途中断进程崩溃、磁盘满、网络断查看任务进度文件与日志增加断点续传和失败重试模型训练 loss 不稳定数据动作分布差异大或标签错误抽样可视化动作轨迹增加数据清洗、统一操作标准、剔除标注错误遥操作延迟明显控制频率过高、网络链路差测量端到端延迟降低消息频率使用有线网络上传文件超时请求体过大查看服务端日志改用分片上传或共享存储9. 最佳实践与使用建议9.1 先跑通最小闭环第一周不要追求规模先搭一条“采集—上传—读取—简单模型训练—推理”的最小闭环。用几十条数据就能验证格式是否统一、模型能不能收敛。一旦格式不兼容后续大批量数据只会放大问题。9.2 数据多样性比绝对数量重要机器人操作数据不像图片分类数据加几千张就可能提升明显。它更依赖任务场景的多样性不同光照、不同物体颜色、不同摆放位置、不同操作者习惯。在设计批量任务时与其只录一个工位不如安排多个场景、多台设备并行采集。这也贯穿一个核心观点不是把某一个人操作的数据堆到 10 万条而是让不同环境下的示范数据都能覆盖到。9.3 给每条轨迹打元数据每个 episode 至少包含这些信息episode_id: grasp_cup_001 task_name: grasp_cup scene: table_clean operator_id: operator_a robot_model: arm_a camera_model: rgbd_camera_01 teleop_device: leader_arm_02 fps: 30 created_at: 2025-01-01T10:00:0008:00 authorized: true license: internal_only元数据越完整后续做数据治理和数据筛选就越容易。训练阶段可以根据操作者、场景、物体类别做子集划分定位模型失败的来源。9.4 合规与授权必须前置涉及人脸、声音、家居环境、商业办公区域的素材必须在采集前确认知情同意涉及第三方数据集、机器人驱动、动作捕捉资产时要检查许可证。凡是不能确认来源和授权的内容一律不进训练集。发布模型权重前还需要进一步检查训练数据中是否包含可识别个人信息。9.5 数据清洗要尽早做数据清洗不是可选流程。原始遥控操作数据里经常包含空转、碰撞、重复运动和标注错误。建议在数据入库前设置三步检查程序自动校验基本字段、模型或规则筛选明显异常片段、人工抽检视觉样本。多轮清洗后的数据集训练效果会明显好于“原样入库”。10. 总结与下一步Figure 给机器人囤数据这件事最值得关注的不是机器人本身而是数据采集的工业化和规范化程度。对中小团队来说先不要急着复刻一个庞大的全球采集网络更实际的做法是把“一条轨迹怎么录、一批任务怎么调度、一条数据怎么校验、一份授权怎么把关”这四个基础问题解决掉。建议你拿到本文后第一步先在仿真环境搭建采集服务用 20 到 50 条数据跑通最小闭环。最容易踩的坑是传感器时间不同步、磁盘写入跟不上采样频率、任务标签缺失这三类问题越早暴露越好。后续可以从三个方向继续扩展一是接入更多传感器模态把力反馈和深度图纳入训练二是用仿真平台生成合成数据再迁移到真机三是把采集端 API 与组织内部的数据管理平台打通让数据采集、清洗、标注、训练成为一条自动流水线。真正拉开差距的往往是数据管线而不是模型参数。
返回列表