搞机器人和具身智能这一年多,团队在Physical AI数据采集上花的功夫,比模型调参还多。以前总觉得数据采集就是把相机架上、录出来、存下来,直到我们在不同场景跑了两三个项目之后才反应过来:物理世界的数据采集,不是拍视频,是生产能用来训练的“示范动作数据”。也正是在这个阶段,我们把方案从一堆USB相机慢慢换成了带边缘算力的立体视觉模块。手边正好在折腾ZED X Nano,把自己的思考过程整理出来,给同样在做Physical AI数据采集、脑部/腕部视觉方案选型的同行一个参考。
1. 从实验室到产线:Physical AI数据采集为什么不再依赖USB相机
1.1 早期采集系统的“能跑”与“扛不住”
先说背景。我们第一版采集系统是典型的“主机+多路USB相机”结构:工控机里插一张USB3.0的扩展卡,机器人的腕部装一个工业USB摄像头,桌面旁边再架两个全局快门USB相机,分别负责可以看到整个场景的第三人称视角和对应目标物体的特写视角。当时逻辑很简单,因为团队最不缺的就是普通USB摄像头,USB接口兼容性又好,插上就能用,SDK成熟,甚至不需要专门写采集程序。
这套系统在小批量、短周期、动作单一的任务上确实能跑起来。比如一个“抓取-放置”任务,我们只需要在固定工位上录2000条数据,当时大概折腾了一周半,问题不算大。可是后续当任务变成“倒水、分类整理、开瓶盖”这种需要手眼协调、又需要在不同工位间移动的场景时,问题开始集中爆发。我先记一下当时最头疼的几个现象:四个摄像头同时采集1080p@60fps大概带宽快吃满一张USB3.0卡;偶尔某个相机会自动断开;到了布置多工位的产线上,USB线超过5米要接延长线然后开始丢帧。这些问题不是个例,是几乎每轮采集中都会碰到。
1.2 USB相机真正的瓶颈:带宽、同步、线缆与后处理
很多文章一谈USB就被“带宽”两个字带过去,但实际踩坑后会发现,带宽只是其中最表层的问题。拿1080p RGB图像来说,一帧不压缩的RGB888数据大概是1920x1080x3字节,约6.2MB,60fps下单相机就需要372MB/s左右的吞吐,半双工的USB3.0实际有效带宽一般到不了400MB/s,单个相机占满之后其他设备就得排队。也就是说,一根USB 3.0线在60帧1080p彩色未压缩模式下,一个相机的压力都很大,更不用说腕部相机加多个全局相机同时跑。
真正让USB方案在Physical AI数据采集中难以为继的,其实是时间同步。机器人数据采集需要把关节角、力矩、末端速度和图像帧对齐到同一个时间基准,否则训练出来的策略在仿真迁移到真机时会有严重的时序错位。USB相机通常靠外部触发线或者软件时间戳来做同步,但软件同步的抖动在Windows/Linux非实时系统下经常是几毫秒到十几毫秒,而机器人控制周期本身可以到1kHz甚至更高,也就是说一个控制循环里图像可能已经滞后了十几帧。对单手抓取这种低速动作可能还能容忍,可一旦动作里包含快速插拔、液体倾倒、柔性物体捏取,这个抖动就无法接受了。
还有一个很少有人提前重视的问题是线缆和接口可靠性。产线上机械臂高速运动,腕部相机跟着来回摆动,USB线在拖链里反复弯曲,半年内断了好几次。更麻烦的是,USB线缆超过3米之后信号完整性明显下降,我们试过5米延长加带供电的USB hub,偶尔会在采集到一半时掉设备,重启之后又不一定能枚举上。排查起来极其费时,你甚至无法确定是线、口、扩展卡驱动还是供电的问题。
后处理开销也是不能忽略的一块。裸流RGB传输到主机后,视频编码、压缩、归档全都要吃掉CPU或GPU资源。即便是用RTX 4090解码,要同时处理四路1080p视频再叠加机器人的状态数据,对数据流水线来说也够忙。如果数据规模到几十万个episode,这一步的资源浪费就会被放大得非常明显。所以从本质上说,USB相机是一套“把原始图像搬运到主机再处理”的方案,它适合开发调试,却不适合作为Physical AI数据采集的主力架构。
1.3 数据采集不只是“拍照”,而是高质量示范数据生产
Physical AI的数据采集和传统机器视觉的数据采集有一个本质区别:传统视觉采集要的是“图像本身”,目标是分类、检测、分割;而Physical AI的数据采集,尤其是训练操作技能策略时,要的是“示范动作的可复现信息”。一个episode通常包含视觉观测、本体感觉观测、动作指令,甚至语言指令。策略模型要从这样一组多维度的时序数据中学会状态到动作的映射。
也就是说,每一帧图像必须和关节反馈真正对齐,还必须保证图像覆盖末端操作区域,同时尽量减少主机后处理带来的延迟和损失。这时“能拍照”已经远不够,采集设备得是一台“能感知、能计算、能同步的传感单元”。也正是从这条思路出发,我们开始尝试把感知计算下放到靠近执行器的地方,于是腕部视觉模块逐渐代替了那些USB摄像头。
2. 腕部视觉的需求倒逼传感架构演进:从“主机看”到“手眼看”
2.1 腕部视觉对硬件的苛刻要求
把相机固定在机械臂末端,在机器人学术圈一直叫eye-in-hand构型,中文语境里有人叫腕部视觉,有人叫末端视觉。这两年因为“数据采集热”,我们更常叫它“手眼”或“腕部第一人称视角”。这个安装位置天然对硬件提出了几个USB相机特别难满足的要求。
第一是重量和体积。末端每多100g,机械臂的动态特性和安全限速都会受影响,尤其在协作臂上非常敏感。USB工业相机加上镜头、沉重外壳,重量很难做得轻,而且它是“相机本体+镜头”的分体结构,安装尺寸也不规则,蹩手蹩脚。第二是功耗和散热。USB相机设计时基本默认数据流是主机侧解码,相机本体做很少的计算,一旦要在末端做深度或AI推理,发热量就会上来。第三是抗振和连接稳定性。机械臂启停和加减速的冲击很大,USB插头在振动中容易接触不良,而这个问题的排查又很让人崩溃。
还有一个长期被忽视的细节:外参稳定性。机械臂UNIX手眼标定做完之后,相机相对末端Link的姿态必须保持不变。USB相机如果只是靠一个支架夹住,稍微受一点碰撞或者线缆拉扯,外参就变了,标定全部作废。腕部视觉模块就是为了这个工况设计的,一体化外壳、多个定位面、靠谱的安装结构,外参稳定性比普通USB相机好一个量级。
2.2 ZED X Nano的设计取舍:边缘算力与模块化
ZED X Nano是Stereolabs在750万像素模块化立体相机这条线上针对边缘AI和机器人场景出的产品。它最大的特点就是把NVIDIA Jetson Orin Nano这颗能在边缘端做深度估计和AI推理的芯片直接放在相机模组内。第一次用的时候我有种很直观的感受:它不像是“相机”,更像是一个“视觉感知模块”,因为它在输出端默认给出的就不是一帧孤零零的RGB图,而是带深度、支持AI处理的“感知数据”。
这颗Orin Nano能跑实时立体深度估计算法,还能跑目标检测、语义分割这类轻量级模型。这意味着很多原本必须在主机上做的计算,比如深度图生成、图像校正、神经网络推理,现在在相机端就完成了。回传到主机的只是在时间上严格对齐的深度图、RGB图以及AI推理结论。相比USB相机裸流回传,主机侧不存在解码瓶颈问题。
功耗方面,ZED X Nano的整机功耗可以做到很低的水平,比“工业USB相机+主机GPU做后处理”的模式低得多。低功耗对机械臂末端还有一个隐性的好处:末端不容易积热,长时间连续采集中也不会因为传感器过热降频。这一点在数据采集车连续跑8小时时格外重要。
2.3 生态之外:为什么固定基线立体方案适合操作场景
腕部视觉如果只用单目彩色图,那么在训练策略时通常还要额外估计深度或者仅靠二维像素处理。固定基线的立体相机则直接提供从相机坐标系出发的深度,虽然基线短意味着远处深度精度有限,但在机械臂末端操作范围内恰好够用。因为这种视觉主要覆盖的是“手面前0.3米到1.5米左右”的操作区域,这个距离内立体视觉的深度精度表现出色。
另一个好处是时间同步的工程实现路径更完整。ZED X Nano内部自带IMU,并且在硬件层面对双目图像、IMU和深度数据做了同步,系统对外还提供与UTC时间对应的硬件时间戳。这个设计在构建统一时间基准的采集系统时省了很多功夫,不用再手工给图像叠加时间戳。可以说,它直接把“多传感器对齐”从一个软件问题,降低成一个配置问题。
3. 实操记录:把ZED X Nano接入我们的采集管线
3.1 硬件连接与系统准备
我们这套采集系统大致由三台设备组成:一台高性能数据采集工作站,一个安装到机械臂末端的腕部视觉模块,还有一台运行遥操作主手的控制主机。实际操作的时候,ZED X Nano通过官方支持的网口方式连接到采集工作站,供电和数据走一根线,这种连接方式比USB线缆在拖链中的稳定性强很多。虽然它也能提供调试用的USB接口,但我们在产线数据采集场景里更信任网口方案,毕竟网线在工业场景的部署和维护经验更丰富。
系统层面我建议直接用Ubuntu 20.04或22.04,NVIDIA驱动版本尽量和官方SDK保持一致。ZED X Nano在Jetson上预置了JetPack环境,主机侧安装一下对应的ZED SDK即可。装好后第一件事是用官方工具查看设备健康状态,确认双目帧率、IMU频率、温度都正常。这一步别跳过,我们第一次因为固件太旧导致时间戳不输出,排查了大半天,最后才发现升级SDK后还要升级相机固件。
3.2 时间同步与多模态数据流对齐
Physical AI数据采集系统的核心难题,就是怎样把不同传感器的数据流放到同一条时间线上。我们的视觉数据来源包括ZED X Nano的深度、彩色和IMU,机器人控制数据来源包括电机关节角、力矩、末端速度,遥操作主手还要提供三至六自由度的位姿指令。这几个来源在系统中各自有自己的频率:视觉30fps,IMU(在我配置下)200Hz,关节控制1kHz,如果每一层时间基准不一致,后面对齐就是一场灾难。
我们的做法是以ZED X Nano的硬件时间戳为视觉基准,然后让机器人控制侧的数据在采集时就打上同一套UTC时间。这样后期可以用线性插值把慢速的视觉数据对齐到高频控制数据上。具体实现中,我在机器人状态回调里读取系统单调时钟,再把单调时钟换算成UTC,视觉SDK拿到的帧得到的是自主时钟对应的UTC,两者就可以放到同一个时间轴上。这个链路如果你用的是纯USB方案,会麻烦很多,因为普通USB相机本身没有高精度硬件时钟,你能拿到的只是“接近接收时刻”的软件时间戳,抖动完全不可控。
在数据流处理上,不要图省事直接把图像丢给Python的list再转NumPy,大几G的缓存会把内存挤爆。要成熟的做法是边收边写,把每一帧图像编码后写入磁盘,同时把对应的状态数据写成CSV或JSONL。这样即使半途崩溃,已经写入的数据也不会丢失,应该说这算我们当时做得比较对的决定之一。
3.3 标定:从出厂参数到手眼标定
ZED X Nano的关键参数在出厂时已经做了标定,包括双目内参、畸变系数、外参、IMU到左目的变换。这一步省了不少事,用官方工具可以一键获取这几个参数,根本不需要自己对着一张棋盘格反复拍。需要特别注意的是,ZED SDK升级时相机固件可能会一起升级,这时个别标定文件可能被重建或覆盖,务必在升级前备份相机标定结果。
比较麻烦的是手眼标定。我们的机械臂末端安装了一个法兰转接板,视觉模块固定在这个转接板上。理论上要解一个AX=XB的方程,实际操作中我建议采集多组机械臂末端位姿与相机观测的标定板位姿,然后选择支持多姿态求解的开源标定库。如果标定出来重投影误差大于2个像素,多半是标定板姿态变化不够大,或者机械臂读数本身误差大。我踩过一次坑:标定过程中机械臂低速运动,视觉模块和支架之间轻微位移,结果标定结果多了一个微小的旋转误差。后来我们在所有安装螺丝和接触面贴了防松胶垫,外参稳了很多。
3.4 数据落盘与数据集格式设计
数据落盘格式我们几经改版,现在固定为:视频流用压缩格式存储,深度图用16bit PNG,RGB图用JPEG,每一条轨迹对应一个文件夹。目录结构类似这样:
episode_00001/ color_left/ depth_left/ imu.csv robot_state.csv obs_time.csv meta.jsonmeta.json记录任务类型、语言指令、操作员ID、控制器配置等信息。这样做的目的是让数据后续进入训练管线时可以按需读取,不必一次性载入内存。ZED X Nano侧输出的彩色图和深度图是自带时间戳的,我们按帧序号写入文件,后期通过obs_time.csv把机器人状态与图像帧关联起来。
这里有一个建议:如果你训练的是视觉-语言-动作模型建议你再额外录一段固定频率的全局视角视频,用来做回放和筛选。只靠腕部视角会丢掉很多上下文信息,比如初始物体摆放、自己手臂的动作,对后续判断数据质量很有帮助。ZED X Nano当然不能代替全局相机,但它们在系统里负责的职责完全不同。
4. 常见问题与排查技巧实录
光看宣传材料永远不知道一个硬件在真实采集里会有什么脾性。这里记录几个我们实际遇到并解决的问题,也给准备上腕部视觉方案的同行一个速查参考。
| 问题现象 | 可能的根因 | 排查与解决 |
|---|---|---|
| 采集一段时间后深度图出现空洞 | 操作距离太近/太远,表面反光或透明材质 | 调整安装位置,保持操作区域在深度有效范围内;透明物体考虑红外结构光方案 |
| 数据流偶尔掉帧 | 网口带宽不足或交换机丢包 | 改用直连网口,确认没有其他设备抢占,关闭Wi-Fi省电策略 |
| 时间戳偶尔跳变 | 系统时间同步漂移 | 部署PTP或定期NTP校准,采集前先核对UTC偏差 |
| 机械臂运动时图像有撕裂 | 卷帘快门效应 | 操作速度放慢或选择全局快门模式;ZED X Nano此类模块本身快门特性偏全局化,但动态场景仍要留意 |
| 手眼标定结果重复性差 | 安装松动或标定板姿态变化不充分 | 加固安装,采集至少15到20组姿态,覆盖不同空间位置和朝向 |
| 推理模型掉帧/显存不足 | Orin Nano侧算力被深度估计占满 | 关闭不必要的AI模块,只保留立体深度和IMU,减少模型输入分辨率 |
另外还有两个经验想单独拿出来说。
第一,不要为了“省流量”在相机端开太强的H.265压缩。深度图本身对压缩噪声非常敏感,如果压缩质量参数太低,边缘会出现预测误差。最好是把RGB做适度压缩,深度图保持无损16bit PNG,或者直接用官方容器格式保存。
第二,数据采集环境里强烈建议把工控机的CPU调频策略设为性能模式。看似只是一个小参数,但采集时线程调度非常看重低延迟,政府模式或者平衡模式会导致某些周期任务间歇性卡顿,表现出的现象就是视频帧晚到几十毫秒。我们当初就因为Linux默认的调度器配置,在长时间采集里遇到间歇性卡顿,排查了很久。
5. 关于腕部视觉架构演进的一点思考
回到最初的问题:Physical AI数据采集开始抛弃USB相机,本质上不是因为USB接口不好,而是因为任务对数据质量、同步稳定性、边缘算力和安装可靠性的要求,已经从“能录就行”进化到“能训练可用策略”了。USB相机低成本、低门槛的优势依然存在,但它作为一个兼顾高带宽、高同步精度、可嵌入执行器端的感知架构,已经触及天花板。
ZED X Nano这类带边缘算力的立体视觉模块,之所以能在腕部视觉场景里站稳,是因为它把深度感知、AI推理、IMU时间同步这些功能集中到一个靠近数据源头的模块里,从结构上降低了系统复杂度和主机侧压力。当然,它的价格肯定不会比几十块钱的USB摄像头便宜,所以选型时还是要看场景:如果你做的是低速、离线、固定工位的数据采录,USB相机仍然是经济之选;但如果你在跑一整条产线或一排机械臂的连续数据采集,需要可靠性和时间对齐,那这类边缘视觉模块的优势非常明显。
我个人在实际操作中的体会是,Physical AI的数据采集问题,最终都会变成“系统设计问题”。选择哪款相机只是其中一个因素,更重要的是想清楚数据的用途、不同传感器的时序关系以及整个流水线的稳定边界。腕部视觉的演进会继续,因为末端本身就在变得越来越智能,ZED X Nano是个不错的样本,但一定不会是终点。