去年下半年开始我一直在折腾一个具身智能数据采集工位从最底层的传感器SDK一路打通到最终的三维表达。这个过程中踩了不少坑也沉淀了一些比较通用的经验。本来以为Sim-to-Real是最大的门槛做下来才发现光是让一堆传感器在正确的时间、正确的空间里把数据对上就已经能让人掉一层头发。这篇东西不是教科书更像是一份踩坑记录把整个数据采集闭环从硬件选型、SDK接入、时间同步到三维表达梳理一遍希望能给正在搭数据工位的朋友省点时间。先说一下背景我们的场景是机械臂遥操作数据采集夹爪和机械臂关节上装了编码器和力矩传感器并排布了双目相机和一只RGB-D相机另外配了高精度IMU。目标是采集人类演示操作时机械臂的运动轨迹、力反馈和视觉观测然后把数据转成下游策略学习能直接用的三维表达。整个过程看起来不复杂但真正落地的时候涉及的数据流、SDK、格式转换和标定问题非常多。全文我会按硬件拓扑、SDK接入、时间同步、数据处理和三维表达这条主线展开每一部分都会给出我实测过、可复现的方案和参数也会把我在实操中遇到的坑和排查思路一并写清楚。1. 先想清楚数据采集闭环到底在解什么题很多刚接触具身智能的人习惯性把注意力全放在模型和算法上觉得数据采集就是“录一段视频、存几个关节角”。我实际做下来发现数据采集闭环是整个具身智能项目里最琐碎、最容易被低估的环节。如果采集阶段的数据质量不行后面哪怕换再强的模型学习出来的操作策略也是歪的。1.1 为什么具身智能绕不开数据闭环具身智能跟普通CV、NLP任务最大的区别在于它奖励的是一种叫“多模态时间序列”的东西。模型不仅要看到图像还得知道机械臂每一时刻的关节角、末端执行力甚至要知道与环境交互产生的力矩变化。没有一套闭环的采集系统这些模态的数据就是分裂的图像是一份时间戳关节角是另一份时间戳力矩信号又是第三份。等到训练的时候你就会发现各种数据根本对不齐模型完全学不到动力学关系。我的理解里数据采集闭环解决的是三件事一是把多模态传感器在时间上对齐到同一个时钟域二是把各个传感器之间的空间位姿关系标定清楚三是以一种统一的数据格式把它们组织起来为后续三维表达和模型训练做输入。这三个问题如果只靠事后处理会非常痛苦。因为事后哪怕能对齐时间戳也补不回来硬件层面的触发偏斜、曝光延迟和滤波延迟。所以这个闭环一定是要从硬件和SDK层面就开始设计的而不是等数据录完再想办法。1.2 数据闭环的四段链路感知、采集、标注、表达我会把整套系统拆成四段链路来讲感知链、采集链、标注链、表达链。感知链指的是传感器本身包括选型、安装、标定。外参标定和硬件触发设计都属于这一段。采集链是软件层面的事情包括各传感器的SDK拉流、数据缓冲、序列化到磁盘。标注链在具身智能里被很多人忽略——以为只有自动驾驶才需要标注。实际上操作数据也需要语义标注比如物体位姿、操作阶段划分、接触事件标记等。最后一链是表达链把原始观测转换成三维表示点云、TSDF、NeRF或者是带语义的3D高斯。我这里想强调一个容易被忽略的观念这四段不是线性的而是闭环的。你采集出来的三维表达反过来会指导你调整传感器布局和采集密度。比如发现重建出来的物体表面有大量空洞就说明RGB-D相机的视角覆盖有问题需要增加机位或调整机械臂运动路径。所以“闭环”二字不只是说数据从采集到表达的流程也意味着表达的结果要能反馈回采集中去修正。2. 传感器选型与硬件拓扑整套采集系统里传感器选型是最容易让人纠结的因为市面上选择实在太多。我的建议是不要盲目堆传感器先回到任务本身问自己三个问题——你的下游模型需要什么模态这些模态需要什么精度你能接受的预算和开发复杂度是多少2.1 机器人本体需要哪些传感器以机械臂数据采集工位为例我认为最核心的传感器有这么几类位姿类、视觉类、力觉类、接触类。位姿类主要指关节编码器和IMU。关节编码器提供的是机械臂各关节的角度精度可以直接决定末端执行器位姿推算的准确性。通常机械臂内部已经自带关节角读数但如果你要采集末端力或者做遥操作往往会再在末端装一个独立的六维力传感器或者在高自由度的灵巧手上加编码器。IMU的作用是在相机运动剧烈、视觉特征丢失时提供短时间的运动增量约束。视觉类主要是RGB-D相机、双目相机和单目相机。RGB-D相机在小范围场景里很好用但如果操作距离比较远或者环境光太强深度会出现大量空洞。双目相机的深度精度依赖基线长度近距离操作精度尚可但计算量会高一些。力觉类基本上就是六维力/力矩传感器。这个传感器在具身智能里极其重要但很多人一开始都会忽略。其实人类操作的核心能力之一就是“手感”而这在机器人上只能靠力传感器体现。装六维力传感器是为了检测末端和物体接触时的力和力矩这对柔顺操作、插拔这类精细任务至关重要。接触类包括触觉传感器、接近传感器等。触觉传感器在灵巧手上的价值很高但目前成本偏贵不是所有场景都值得装。接近传感器比如红外、超声波常用于检测夹爪接近物品但如果你有高频率的视觉反馈接近传感器很多时候可以省掉。我装的具体配置是一台RGB-D相机用于场景观测和重建、一组双目相机用于近距离操作观测、一个六维力传感器装在机械臂末端法兰、外加每个关节自带的编码器数据。这套配置基本覆盖了绝大多数桌面级操作任务。2.2 多传感器的时间同步硬触发还是软同步这个坑是我踩得最深的一个值得单独拿出来说。多传感器时间同步的本质是每一帧数据和全局时钟之间要有一个偏差而且这个偏差必须小于任务允许的误差。对于低速场景几十毫秒的偏差可能无所谓。但机械臂一旦动起来末端速度可以达到每秒几百毫米几十毫秒的偏差就是几厘米的空间误差这足以让力反馈和视觉完全对不上。时间同步有两种主流实现思路软件软同步和硬件硬触发。软同步的做法是每路传感器独立工作数据打上各自的时间戳之后在后处理阶段用线性插值或最近邻查找对齐。这种方案实现简单但误差取决于各传感器系统的时钟漂移和数据帧率。实验室环境下如果所有设备都通过同一个NTP/PTP服务器同步软同步可以做到几毫秒到十几毫秒的精度。但如果传感器上报时间戳的点距离实际曝光时间有一段延迟比如相机在曝光结束后才打时间戳误差就会明显变大。硬触发则是在硬件层面给所有传感器一个统一的触发信号。比如用单片机产生一个脉宽可调的PWM信号同时去触发多相机的曝光和IMU的数据采样。这样所有传感器就在同一个物理时刻开始数据采集时间戳偏差可以压到微秒级。代价是硬件接线复杂而且不是所有传感器都支持外触发模式。RGB-D相机通常不支持真正的硬外触发因为深度是由IR投影和双摄计算出来的内部处理链路更长。我的经验是能用软同步解决的场景不要轻易上硬触发。先认真做好PTP时间同步和曝光时间戳记录看看误差是否可接受。实在不行再考虑针对特定相机做硬触发改造。纯硬触发对工程团队的要求高很多而且会限制以后换传感器的灵活性。2.3 一个可落地的硬件接线方案分享一下我最终采用的接线方案给想复现的朋友一个参考。主控是一台工控机装Ubuntu 20.04跑ROS 1Noetic。时间源用一台GPS授时模块通过PTP协议给工控机授时同时往下给传感器交换机组播时间。相机和IMU统一走网口或USB接工控机六维力传感器走EtherCAT接实时工控单元。机械臂控制盒会输出实时的关节角数据通过UDP组播给工控机。EtherCAT的力觉数据节点和机械臂控制盒都连接到同一个实时网段以机械臂控制盒的主时钟为时间基准PTP协议的Profile配置成与工业以太网兼容。比较关键的一个点是把力传感器和关节角的时钟当作主时钟而不是把相机当主时钟。因为机械臂控制和力反馈这两个数据流往往需要实时性而视觉数据反正有曝光时间戳在后处理时对齐即可。这套接线不复杂但有一个细节一定要提前确认各设备是否支持指定的时间同步协议。比如一些工业相机只支持IEEE 1588的某个子集有些只支持PTP over UDP有些支持gPTP。电平标准、触发极性、同步帧格式都可能不一样需要提前看SDK文档。3. 从SDK到数据流采好每一条模态硬件接好之后真正投入时间最多的地方就是各传感器的SDK接入。这里没有太多捷径就是老老实实读文档、跑官方示例。但有几个常见问题想提醒一下。3.1 相机SDK颜色与深度流的拉取我的RGB-D相机用的是RealSense系列官方提供的librealsense SDK比较成熟支持跨平台也支持ROS封装。不过用的时候有几个容易踩的坑一是深度流和彩色流的帧率必须单独设置且不一定能够保持严格对应。RealSense内部有深度和色彩对齐机制但如果开了高分辨率USB带宽会成为瓶颈自动降低帧率或者丢帧。二是曝光时间设置的问题。RGB-D相机在暗光环境下会自动拉长曝光这会导致动态模糊。采集机械臂操作数据时机械臂运动速度很快曝光时间高于5毫秒基本就糊了。手动固定曝光参数控制在1到3毫秒能明显提升数据质量。三是深度图自带的时间戳问题。librealsense提供的frame时间戳是主机收到帧的时间不是曝光时间。说明文档里其实提到过可以用Metadata记录曝光时间戳但要从metadata里取需要额外开启metadata支持。我强烈建议开启这个功能对后处理阶段的时间对齐帮助很大。双目相机这边我用的是一个工业双目摄像头SDK提供硬件同步接口和左右目触发同步。它支持通过外部信号触发曝光也可将内部时钟同步到PTP。对精度有高要求时可以用外部触发模式配合单片机产生触发脉冲。3.2 IMU与编码器标定与去噪IMU的数据读取本身不复杂但噪声问题很让人头疼。消费级IMU的零偏并不是固定的会随温度漂移。很多人在做数据采集时直接拿IMU原始加速度和角速度去算姿态会发现静止时角度也在飘。正确的做法是先做静态零偏采集上电后让设备静止一两分钟取平均值作为bias。编码器方面如果是机械臂自带关节角数据一般已经做过标定。但要注意关节角数据的单位可能是弧度也可能是角度还有可能是电机侧角度而不是关节侧角度中间存在减速比。这个一定要看机械臂SDK的说明否则换算出来末端位姿会完全错误。我踩过一个坑机械臂关节角SDK默认返回的是电机角度需要除以减速比才是关节实际角度。当时没注意直接拿去计算运动学发现末端位置和观测到的相差一大截第一反应还以为是标定板出问题了。3.3 力觉传感器最容易被忽略但最值钱的信号力觉数据在数据闭环里是最“便宜”但又最“值钱”的。便宜是因为就一个传感器值钱是因为没有它很多操作任务根本学不会。力传感器读取要关注采样率和滤波这两个问题。采样率建议至少1kHz以上因为接触事件本身很短暂如果采样率太低冲击瞬间的峰值会被丢掉。滤波则要分两层硬件层面的低通滤波和软件层面的滑动平均。过低通太激进的滤波会削掉力的变化细节导致接触瞬间的“手感”丢失。我用的是工业级六维力传感器SDK通过EtherCAT实时读取6通道力/力矩数据。它提供了原始数据、软件滤波后数据以及一个加载校准矩阵后输出的物理单位数据。这里要特别提醒出厂校准矩阵只能保证在理想条件下精度实际安装后会因为安装力矩、连接件重力产生零点偏移。需要在每次采集开始前让机械臂停在固定姿态执行一次自动清零tare。4. 数据预处理与标注闭环传感器数据采回来不代表就能直接送进模型。我见过太多团队在这一步栽跟头——辛苦采了半天数据却因为时间戳不对齐、外参标定不准确导致数据无法使用。数据预处理远不止是“剪一下视频、转一下格式”它是一个典型的工程问题需要花费大量心思。4.1 时间戳对齐与外参标定时间戳对齐我分两步来做。第一步是粗对齐把ROS bag里各话题的时间戳统一转成同一条时间轴的Unix时间。这一步比较简单因为采集系统里所有话题都挂在一个ROS master下统一使用系统时钟。第二步是精对齐因为每路传感器本身有时间延迟即使时间戳对准到同一时刻采样点依然可能错开。我采用的方法是以视觉帧的曝光时刻为基准把IMU和力数据通过线性插值映射到视觉曝光时刻。具体的实现是维护一个环形缓冲区每当收到新的视觉帧就去缓冲区里找到其曝光时间附近最近的IMU和力数据按时间距离做线性插值。外参标定在具身智能数据采集中非常关键。把相机坐标系与机械臂基座关联起来这样才能把图像里的物体位姿转换到机器人操作坐标系。这里我建议用标准的Eye-in-Hand标定法机械臂末端装标定板走几十个姿态相机观察标定板同时记录机械臂末端位姿求解手眼变换矩阵。Eye-in-Hand标定对位姿数量有限制太少结果不稳定太多又耗时。我通常采集50到80个有效样本并用重投影误差做交叉验证误差低于0.5像素才算合格。4.2 三维表达点云、mesh、NeRF与3DGS怎么选数据预处理完成后就到了最能体现“三维表达”价值的部分。三维表达在具身智能里有几类常见选择点云、体素网格、TSDF截断符号距离场、NeRF神经辐射场、3D Gaussian Splatting。点云是最简单的表达直接由RGB-D相机经过外参变换生成。优点是计算量小、透明、可以快速验证外参标定是否正确。缺点是稀疏、无拓扑、对物体材质和反光敏感。TSDF是把点云融合到体素网格中适合处理多视角数据融合。在机械臂数据采集中TSDF经常用来重建桌面操作场景的工作台。它比点云更稠密但受重建分辨率限制体素尺寸通常选5mm到10mm分辨率越高占内存越大。NeRF和3DGS是目前比较热门的三维表达方式。NeRF隐式表达适合做新视角合成但训练耗时、推理较慢。3DGS在渲染质量和速度之间取得了较好的平衡而且可以在不完整视角下逐步优化。对于具身智能来说如果要做比较复杂的操作任务规划3DGS正在成为主流选择。但我必须说一句实话在数据采集闭环里早期建图阶段我建议先用TSDF不要一上来就搞NeRF或3DGS。原因是这些神经渲染方法对输入图像质量和相机位姿精度极其敏感。如果采集的图像有运动模糊、曝光不均或者相机外参有误差重建结果会很差而且很难排查问题。先用TSDF验证整个链路等到数据质量稳定了再上更复杂的表达。4.3 标注闭环不只是画框最后再说标注。具身智能数据的标注远不止语义分割和目标检测它还需要标注操作阶段、接触状态、物体位姿等。我强烈建议在采集时同步设计一套标注协议。举个例子插头插入插座这个任务我们会标注“开始接触”和“完全插入”两个时间点。这两个时间点的判断依据不只是视觉更多是力觉突变——当力觉传感器检测到z轴力出现显著阶跃时说明已经接触。这个标注就不适合人工逐帧去画而是应该写脚本基于力信号自动检测再人工校正。另外物体位姿标注可以借助AprilTag或ArUco码。在物体上贴一个标记算法直接解算位姿这样就不需要人工去画六自由度位姿了。但这要求标记在操作过程中不能被遮挡太多如果机械臂夹爪比较大标记很容易被挡住那就需要多贴几个。5. 常见问题与排查技巧实录数据采集系统的坑非常隐蔽很多时候不是代码报错而是数据“看起来正常但用起来不对”。我把这半年遇到的高频问题整理成一张速查表供大家按图索骥。5.1 多传感器时间戳经常乱跳现象同一台相机采集的深度图和彩色图时间戳不一致且差值忽大忽小IMU时间戳偶尔比当前系统时间还大。排查思路先看所有传感器是否在同一时间源下输入chronyc tracking确认系统时间同步状态。确认每个SDK是否开了硬件时间戳部分相机默认用“主机接收时刻”打时间戳需要手动切换为“传感器曝光时刻”。如果发现时间戳比当前时间还大通常是传感器内部时钟和主机时间有较大偏移建议检查PTP同步进程是否被防火墙拦截或查看网口是否在同一个交换机下。我个人的习惯是每次采集前先录一段“传感器静止”数据让所有设备休止一分钟然后观察各模态时间戳的漂移情况。如果静止状态下时间戳漂移都很大那不用往下走先把同步搞对。5.2 SDK版本兼容性坑现象按官网教程安装最新SDK后部分老设备连不上或者SDK更新后接口名变了导致旧代码编译不过。这个其实很好理解但也很容易让人崩溃。工业设备还好开源SDK经常有新版本把老接口废弃。我踩过的就有RealSense SDK 2.x中期版本把rs2_stream_profile相关API改过嵌入式平台上的SDK更是如此。我的应对策略是固定版本SDK版本、固件版本、驱动版本三者对应关系要在工程文档里明确写清楚并把编译好的依赖库打包存档。对就是完整拷贝和备份。换了新机器直接解压编译好的库而不是重新去网上拉最新代码。5.3 力传感器温漂与零偏现象机械臂静止不动力传感器的读数缓慢飘移几十秒后z轴力明显变大。这个很典型反应力传感器的温漂特性。尤其是长时间运行后电路板发热会改变应变片的基准电压导致零偏漂移。常规做法是在每次数据采集前执行tare清零。但更好的方法是在SDK里启用内置温度补偿或将传感器温度数据同时记录到日志中后处理时做线性补偿。我的做法是每次采集开始前让机械臂停在一个固定姿势执行tare采集结束后再回到固定姿势读取残余偏差如果比较大则把整段数据标记为可疑并重新采集。注意tare清零时机械臂一定要保持静止否则会把运动加速度误当成重力分量导致清零结果错误。5.4 三维重建出现大量空洞现象TSDF重建出的桌上物体出现大片空缺尤其是侧面和底部。原因基本就三个深度图遮挡、深度图噪声、相机位姿漂移。排查方法我总结为三步第一步把采集到的深度图按时间轴回放观察物体侧面是否出现在任何一帧画面里。如果没有出现是视角覆盖不足需要增加相机机位。第二步把深度图和RGB图对齐后叠加显示看深度边缘是否与彩色边缘吻合如果边缘粗大甚至有双影说明深度噪声大。第三步看相机位姿轨迹是否有明显跳变如果有跳变回查外参标定目标检测结果是否有错帧。我踩过一次比较有意思的坑用AprilTag做相机姿态估计因为标定板被夹爪短暂遮挡AprilTag解算错误导致这一段时间相机位姿完全错误。TSDF把这些错误位姿的深度融合进去产生了一团严重的伪影。排查了很久才发现是位姿跳变的问题。5.5 关节角数据与视觉数据空中错位现象末端执行器在图像里的位置和根据关节角推算出来的投影位置误差超过一厘米。这个问题一出现我的第一反应是外参标定出错了但反复检查手眼标定结果误差都很小。后来才发现是关节角的数据频率太低只有30Hz而机械臂运动速度很快按时间戳插值到视觉曝光时刻时误差被放大。解决办法有三个一是提高关节角上报频率尝试打开机械臂的实时模式把频率提到100Hz以上二是在数据后处理阶段用更高阶插值样条插值重建关节角轨迹三是在机械臂控制盒里开启运动学前馈补偿。我最终是改成实时模式把关节角频率提到了125Hz误差明显减小。6. 一些复盘和后续想法整个项目做下来我最深的体会是数据采集闭环不是一个能“一步到位”的事情它更像一个需要持续迭代的工具链。先把最简可用的版本跑起来然后根据数据质量反馈不断修正传感器配置和同步方案这才是比较务实的路线。如果在读这篇文章的你正准备搭一套具身智能数据采集系统我给几个很朴素的建议第一先花时间把时间同步和外参标定做扎实。这是整个闭环的地基地基不稳后面一切重建和训练都是空中楼阁。第二所有传感器SDK版本、驱动版本、配置参数都要写进文档并做版本管理。这个看起来只是工程习惯问题实际上能帮你省掉大量重复排查的时间。第三不要一开始就追求最贵、最全的传感器方案。先用你手头能买到的传感器把数据采回来跑通整个“采集到表达”的流程再逐步升级设备会比一开始就堆高端设备高效得多。第四三维表达选型要跟着任务走。如果只是做策略学习点云或TSDF可能已经足够如果要做高保真重建或仿真迁移3DGS是当前值得投入的方向。但无论选哪种先保证输入数据的质量。最后再分享一个我个人的小习惯每次采集完数据除了常规的质量检查我会抽几段样本直接用可视化工具加载出来把RGB图像、深度图、力信号、关节角轨迹放在同一个界面上一起回放。用眼睛扫一遍能发现很多自动检查发现不了的问题比如力的突变点对应着画面里的接触瞬间时间戳是否对齐一目了然。这个“数据可视化复盘”的习惯算是这一年来最好的投资之一了。希望这篇文章能帮你少走几步弯路也欢迎有类似经验的朋友在评论区交流你们在采集闭环里遇到的那些奇奇怪怪的问题。
阅读完成 · 觉得有帮助?