做机器人定位、自动驾驶感知或者无人机SLAM的时候,IMU标定这几个字几乎是绕不过去的坎。我刚接触那会儿也天真地以为,IMU标定就是把一个传感器拿去测一测、调一调,填一张出厂校准表就完事了。实际在工程里一上手才发现,这边说的“IMU标定”至少包含两个完全不在一个量级上的工作:一个是标IMU本身的误差,另一个是把IMU跟相机、雷达这些传感器之间的相对关系标出来。两个方向用的工具、采集的数据、看的结果完全不一样,很多人一开始就被“标定”这个词搞懵了,最后项目里报错都不知道该查哪一步。
这篇文章我想把这两条路分别讲透。你们可以把它当成一份梳理好的踩坑笔记,也可以直接照里面的流程去开跑。无论你是刚入门做第一版视觉惯性里程计,还是在做相机和激光雷达联合导航的工程落地,看完之后至少能分清“现在卡住的是内参问题还是外参问题”,以及该用哪种标定方式去解决。
1. 两种标定到底在标什么?先把概念分清
1.1 内参标定:让IMU自身读数变可信
IMU内部一般包含三轴陀螺仪和三轴加速度计,部分还带磁力计。理想情况下,陀螺仪静止时输出应该是0,加速度计静止时输出应该是当地重力加速度在三个轴上的投影。但现实中的MEMS器件远远做不到这么干净,零偏、刻度因子、交轴耦合、随机噪声、温度漂移,每一项都会让你融合出来的姿态在几十秒内肉眼可见地飘走。
内参标定要解决的就是这个问题。它干的事可以理解成给IMU建立一个“误差词典”,把某个原始输出对应的真实值估算出来。标定完成之后,软件层拿到IMU原始数据,先套误差模型做补偿,再进入姿态解算或者滤波融合,这样后面做的视觉惯性里程计、激光惯性系统才有意义。
举一个最直接的例子:一个零偏不标定的陀螺仪,静止时可能每秒输出0.01rad/s的角速度,一秒钟的积分偏0.3度左右,看起来不多,但几分钟过去就是十几度的姿态飘移。这在AR头盔或无人机增稳里是灾难性的。
1.2 外参标定:把多个传感器坐标系对齐
外参标定则是另外一回事。这时候IMU本身可能很准,但光准没用,因为机器人系统里不是只有一个传感器。相机看到的画面和IMU测量到的角速度、加速度必须统一到同一个坐标系下,联合标定就是去求IMU坐标系到相机坐标系或者其他传感器坐标系之间的旋转矩阵和平移向量。
这里说的“外参”本质上是一个六自由度的变换关系,包括旋转和平移。很多做融合定位的工程问题,算法选得再先进,外参给得不准,在线标定优化起来也会费很大劲,甚至直接发散。
一句话总结这两种方式:内参标定管的是“这个器件自己读的数准不准”,外参标定管的是“多个传感器之间互相对齐得准不准”。很多项目里用户反馈“IMU标定了但定位还是飘”,通常不是内参没做,而是外参根本没标,或者只标了旋转没标平移。
为了后面展开方便,我把两条路的差异整理成一张表:
| 维度 | 内参标定 | 外参标定 |
|---|---|---|
| 标定对象 | IMU自身误差 | IMU与其他传感器间位姿 |
| 主要参数 | 零偏、刻度因子、交轴耦合、噪声密度 | 旋转R、平移T |
| 常见工具 | imu_utils、kalibr_allan、六位置法 | Kalibr、lidar-imu标定工具、手眼标定 |
| 采集要求 | 静止或精确控制姿态 | 相机与标定板可见、IMU充分激励 |
| 典型输出 | yaml噪声参数、bias稳定性 | 4x4变换矩阵、外参yaml |
| 验证方式 | 静止积分漂移、Allan方差曲线 | 重投影误差、轨迹对比 |
2. 内参标定:静态采集和Allan方差能算出什么
2.1 先搞清楚要标的那些参数
内参标定的第一步不是急着拿工具开跑,而是先把要估的参数列清楚。最常碰到的几类误差是:
- 零偏:零输入时的偏移量,单位通常是deg/h或者deg/s。
- 刻度因子:实测输出与理论输入之间的比例误差。
- 交轴耦合:三个轴的敏感方向不完全垂直导致的互相串扰。
- 零偏不稳定性:描述零偏随时间缓慢波动的量,Allan方差曲线上对应最低点的值,单位是deg/h。
- 角度随机游走:由白噪声积分导致的姿态随机漂移,单位是deg/√h。
- 速率随机游走:角速度噪声积分的随机游走,单位是deg/h^2。
做过惯性器件选型的人应该对这些名词不陌生,但真正在工程里做标定时,很多人只关心噪声密度和随机游走,因为这两个参数要填进卡尔曼滤波器的状态方差初值。零偏和刻度因子则更多在传感器驱动层做补偿。
2.2 静态采集的时长和数据要求
最常见的低成本内参标定方案就是静态采集加Allan方差分析。它的核心假设是IMU静止放置时,真实角速度和加速度都是常数或0,测量值里剩下的变化全部来自噪声和误差项。通过长时间静止数据,可以分离不同时间尺度上的噪声成分。
采集时长是个关键选择。Allan方差曲线要看到从秒级到千秒级的变化趋势,通常需要连续静止至少1小时以上,严谨一些的做法是2到4小时。很多开发板测试时只采了5分钟,出来的Allan曲线后半段全是毛刺,根本拟合不出随机游走项。
比较好的做法是让系统上电预热10分钟以上再开始录bAg,等温度稳定。采集时用三脚架或者直接放在减震台上,避免人走动、空调风直吹这类地面微振动干扰。频率上最好让IMU以200Hz以上输出原始数据,如果只有100Hz也不是不能处理,但拟合出来的高频噪声段会差一些。
2.3 实际跑Allan方差和六位置法
现在开源工具已经比较成熟了,ROS社区里常用的是imu_utils和kalibr_allan。这些工具输入rosbag,输出对应的yaml参数文件,里面就包含噪声密度、随机游走、零偏不稳定性等需要用的结果。
通常的做法是先录一个主题为imu/data的静态rosbag,然后直接运行:
rosbag record -O imu_static.bag /imu/data然后调用imu_utils里的工具,例如:
roslaunch imu_utils imu_utils.launch或者用kalibr_allan的python脚本处理。最终得到类似这样的输出:
# 陀螺仪 gyroscope_noise_density: 1.83e-04 gyroscope_random_walk: 1.02e-05 # 加速度计 accelerometer_noise_density: 5.13e-03 accelerometer_random_walk: 8.43e-05这些值怎么理解?gyroscope_noise_density越小,代表高频抖动越小;gyroscope_random_walk越小,代表长时间积分飘得越慢。填进VIO初始化或惯性导航解算时,这些值会直接决定滤波器对IMU观测的置信度。
除了纯静态Allan方差,工程上还常用六位置法做零偏和刻度因子标定。做法是把IMU在六个标准方向分别静止一段时间,利用重力加速度在三个轴上的不同投影,建立方程组解出零偏和刻度因子。没有转台的情况下,只要有一个比较水平的平面就能做,精度对多数应用来说足够了。
这里补充一句,基于常见实践的提醒:六位置法标定的过程中,每个位置停留时长建议不少于60秒,且切换方向时动作要轻,等稳定后再开始记录。不要用手拿着快速翻转,那样会让加速度计在切换瞬间饱和,污染数据段。
3. 外参标定:Kalibr跑相机-IMU联合标定的完整流水线
3.1 准备标定板和imu.yaml的必要字段
外参标定在视觉惯性系统里最常用的开源方案是Kalibr,它同时支持相机内参标定和相机-IMU外参联合标定。Kalibr以标定板作为视觉观测基准,通过连续图像帧上的角点特征,重建相机的位姿轨迹,再和IMU积分出来的轨迹做联合优化,最终求出摄像头和IMU之间的旋转和平移。
准备工作里最容易被忽略的是标定板文件本身。目标板要选择aprilgrid或者棋盘格,aprilgrid最适合,因为支持部分遮挡情况下的角点辨识。标定板文件里要写清楚类型、行列数和每个格子的边长,单位是米。格式类似:
target_type: 'aprilgrid' tagCols: 6 tagRows: 6 tagSize: 0.05 tagSpacing: 0.3另一个必要文件是imu.yaml,至少要包含IMU的频率、坐标系、噪声密度和随机游走这些信息。Kalibr里这个yaml是优化器的初始化依据,写得不对直接决定标定结果能不能收敛。一个典型的imu.yaml长得像这样:
# 加速度计和陀螺仪频率 rate: 200 accelerometer_noise_density: 5.13e-03 accelerometer_random_walk: 8.43e-05 gyroscope_noise_density: 1.83e-04 gyroscope_random_walk: 1.02e-05这些噪声密度和随机游走参数正好可以用到上一章的内参标定结果,这也是为什么我建议先做内参标定再做外参标定,顺序不要反。
3.2 采集数据:怎么“甩”相机才是关键
很多人以为联合标定就是把相机对着标定板静置拍几张图,然后跑一下Kalibr就行,这是一个很大的误解。外参标定的本质是靠运动激励来同时估计IMU偏置、重力和相机轨迹。如果相机长时间静止不动,IMU没有任何角速度和加速度激励,旋转和平移的可观测性都会大幅下降。
我自己实测下来,比较有效的动作流程是这样的:开始录bag前,先让相机和IMU静止2到3秒,然后开始缓慢平移加旋转,动作要有轴间区分,也就是不要让所有轴一直同时运动。最实用的一种激励方式是画“8”字形轨迹,同时把标定板保持在画面里。记得中间穿插几次停留,但不要停太多。
整个录制过程控制在60到90秒左右就够,时长不是越长越好,因为长时间手持会累,手抖会引入IMU高频噪声。录bag时尽量用低曝光固定快门,避免标定板角点模糊。很多人在室内照明下拍出来的照片暗部噪点严重,角点提取不稳定,联合标定就跑不出结果。
3.3 跑kalibr与结果解读
准备工作做足之后,开始运行联合标定。典型的命令是:
kalibr_calibrate_imu_camera \ --target april_6x6_50x50cm.yaml \ --cam camchain.yaml \ --imu imu.yaml \ --bag dataset.bag \ --time-calibration命令里多提一嘴--time-calibration,这个选项很有用,它会同时估计相机和IMU之间的小时间差。在消费级设备上,IMU和相机的时间同步经常不是严格的,不加这个选项,明明外参是对的,也可能因为20ms的时间错位让优化结果变差。
跑完后会输出一个类似camchain-imucam-dataset.yaml的文件,里面就是标定得到的q_ic和p_ic。q_ic是四元数,表示IMU坐标系到相机坐标系的旋转;p_ic是平移向量。在后续使用中,如果代码里期望的是相机到IMU的变换,记得取逆。
4. 最容易和IMU标定混淆的几个标定
4.1 相机内参标定不是IMU标定
做视觉惯性系统时,很多标定工作容易混在一起。相机内参标定主要标的是焦距、主点、畸变系数这些量,最常用的是张正友标定法,通过拍摄多个姿态下的棋盘格或aprilgrid图片,计算出相机的内参矩阵和畸变参数。它解决的是“像素坐标和相机坐标系里的空间点怎么对应”的问题,和IMU没有直接关系。
但相机内参标定的质量会直接影响IMU外参标定的精度。如果相机内参不准,Kalibr里用标定板恢复出来的相机位姿本身就有偏差,那后面求相机和IMU之间的旋转和平移也不可能准。所以正常的工作流应该是:先标相机内参,再标相机-IMU外参,最后才谈传感器融合。
4.2 手眼标定与九点标定也是“外参”但不是IMU特有的
手眼标定在机械臂领域非常常见,核心是解AX=XB方程,A是一个坐标系的变换,B是另一个坐标系的变换,X就是待求的手眼矩阵。它其实是一类通用的外参标定思路,不局限于IMU和相机之间。网上搜“手眼标定”会搜出一大堆机械臂抓取、相机引导贴合的内容,这类标定解决的是机器人末端执行器或基座与视觉系统的坐标关系,和IMU本身无关。
九点标定同样容易混淆。它通常用在2D平面视觉定位里,通过几个已知点建立图像坐标系和机器人平面坐标系之间的仿射变换或者投影映射,适合上下相机引导贴合、激光切割定位这类场景。严格来说它跟IMU没有任何交集,但很多工程师同时要处理IMU、相机、机械臂多个传感器,混在一起搜索时会产生一种“这些都是同一种标定”的错觉。
简单整理一个鉴别表:
| 标定名词 | 解决什么问题 | 是否关联IMU |
|---|---|---|
| 相机内参标定 | 像素与相机坐标映射 | 不直接关联 |
| 手眼标定 | 相机与机械臂/末端坐标系 | 可用但不特有 |
| 九点标定 | 2D图像与平面坐标映射 | 不关联 |
| 双目相机标定 | 左右相机相对位姿 | 不直接关联 |
| 相机-IMU联合标定 | 视觉与惯性融合外参 | 强关联 |
| IMU内参标定 | 惯性器件自身误差 | 直接关联 |
4.3 ADAS和汽车领域里的“IMU标定”
自动驾驶功能上车时,汽车驾驶辅助标定是一个非常热门的词,里面经常提到IMU。ADAS标定通常包含相机、毫米波雷达、IMU等多个传感器的联合标定,既有静态标定又有动态标定。动态标定里经常要做的是把IMU测到的横摆角速度、纵向加速度与车辆底盘模型输出做对齐,本质上也是一种特殊的“外参+时间延迟”标定。
跟机器人平台还不太一样的是,ADAS领域要求有完整的安全流程和标准,通常会借助四轮定位仪、标定板、雷射标靶这些专业设备。但核心思想没有变:IMU必须和车辆坐标系、传感器坐标系建立确定关系,否则车道线融合、自动泊车这些功能都会出现偏差。
5. 标定结果怎么验证 + 我踩过的坑
5.1 内参结果验证
标定不是跑完工具输出yaml就算结束,验证环节直接决定你敢不敢把这个参数用到产品里。
内参方面最直观的验证方法是静止积分测试。把IMU按标定输出补偿之后静止放置一分钟,观察姿态解算的漂移角速度是否大幅下降。好的MEMS级别的IMU补偿后,静止一分钟的纯积分姿态漂移应该在个位数以内,如果还是几十度级别漂移,通常说明零偏估计不准,或者是温度变化太快导致零偏已经漂走。
Allan方差曲线本身也是一种验证手段。正常曲线应该能从高频段到低频段看出明显的先降后升趋势,最终在某个平台区域出现最低点。如果曲线乱作一团,大概率是数据里混入了大幅振动或者采集时长不够。
5.2 外参结果验证
外参标定结果的验证最常用的是重投影误差。Kalibr会在标定报告里给出视觉残差RMS,经验值上室内标定场景RMS如果大于1个像素,就要警惕标定质量。但仅看RMS不够,因为优化器会把误差分摊到多个参数上,个别参数即使不对RMS也可能压得很低。
更有实际意义的验证方式是把IMU数据投影到图像坐标系里。具体做法是让相机对准一个有明显地平线或铅垂线的场景,把标定出的重力方向通过外参旋转投影到图像上,看这条投影线和画面里的真实垂直方向是否重合。如果角度差超过一两度,说明外参旋转估计有问题。
我还习惯做一次跑图对比,拿标定好的外参并到VIO或者LIO系统里跑一组已知轨迹,再看最终轨迹是否收敛到起点。这个验证非常直观,平移外参错10cm和旋转错1度,在几十米的行驶轨迹上会表现出完全不同的漂移形态。
5.3 我踩过的几个坑
第一个坑是数据同步问题。我第一次做相机-IMU联合标定时,IMU打了时间戳但相机用的是硬件触发,两者之间有一个固定延迟没处理,Kalibr跑了好几次都报“initial batch estimation failed”。后来做了时间标定才解决,从此以后我录bag前都会用示波器或者驱动日志确认时间戳是否一致。
第二个坑是静止阶段和运动阶段的占比。最初采集时我想着多给一些静止段有利于bias估计,结果整段bag里60%都是静止,最后标出来的外参平移不确定性非常大。后来把运动占比提到70%到80%,结果明显稳定很多。
第三个坑是用冷藏过的开发板直接做标定。传感器上电后内部温度还在爬升,零偏随时间明显变化,Allan方差曲线低频频段异常。现在我的标准流程是先通电预热十分钟再录数据,如果项目对温度漂移敏感,还会在标定时加一个简易加热片模拟实际工作温度。
第四个坑是标定板不平整。有些便宜的亚克力板印出来的棋盘格厚薄不均,贴在墙上之后角点位置有亚毫米级波动,视觉重建时产生微小偏差。由于IMU外参标定的平移精度本来就受限,这种误差叠加进去后,标出来的T非常离散。后来换了铝基板加哑光覆膜,角点稳定性好了不少。
最后分享一个实际项目里的体会,有一次我们在车辆平台上做外参标定,车内电子设备温度变化很快,早上标定的T和中午标定的T相差了将近1.5度旋转。排查半天发现不是标定流程出问题,而是IMU壳体温度变了导致内参零偏偏移,带动整个联合优化结果跟着动。从那以后我养成了一个习惯:内参标定和外参标定尽量在同一温度环境下进行,最好把IMU封装好,避免阳光直射或者冷风直吹。标定这种事,看着是数据工程,实际上里面塞满了物理环境的坑,多做几遍、多验证几遍,比依赖任何一次“完美收敛”都可靠得多。