☰
IMU标定怎么做?多位置任意姿态静止标定法详解
2026/10/5 7:02:12 网站建设 项目流程

做机器人、无人机或者自动驾驶的朋友,对IMU应该都不陌生。但真正上手做过SLAM、组合导航或者位姿估计的人,迟早都会撞上一堵墙:IMU的原始数据直接拿来用,效果惨不忍睹。零偏、尺度误差、安装轴偏差,这些看不见摸不着的家伙会把你的积分结果一点点带偏,最后轨迹歪到姥姥家。而大多数人卡住的第一道坎,就是标定。

市面上主流的IMU标定方案无非两条路:要么买高精度转台,把IMU固定在转台上做精密角速度激励,成本高、操作繁琐;要么用所谓的“六面静止法”,把IMU摆成六个特定姿态,靠重力作为参考来标定加速度计。前者贵,后者对摆放精度要求极高,稍有不慎姿态没放正,标出来的参数反而更差。所以很多人标完发现,怎么比不标还飘?

这篇文章要聊的,就是那个在论文和工程社区里被反复验证过的、不需要任何外部设备、对摆放精度不敏感、实现起来又很友好的方法——多位置任意姿态静止标定法。它的核心思路很简单:IMU静止时,加速度计测量到的比力的大小,理论上一定等于当地重力加速度。不管你怎么摆、摆成什么奇怪的角度,这个约束永远成立。利用这个物理约束,配合一批任意姿态下的静止观测数据,就能用最小二乘把加速度计的零偏、尺度因子和轴间非正交误差一并解出来。陀螺仪的零偏也可以通过静止数据的均值直接估计。整个过程不需要转台、不需要水平仪、不需要任何外部基准,只需要一个能采集数据的开发板或者机载电脑就能完成。这套方法做下来,我实测过多次,标定后的加速度计残差能压到0.001 g以内,对大多数SLAM和组合导航场景已经非常够用。

这篇文章适合谁?如果你是做LIO(LiDAR-Inertial Odometry)、VIO(Visual-Inertial Odometry)、行人导航或者位姿解算的工程师或研究生,正在为IMU数据质量发愁,这篇文章可以给你一套完整可复现的标定流程,从原理到代码到坑点全覆盖。哪怕你只是刚接触IMU的小白,只要照着步骤走一遍,也能拿到一份显著改善的数据。

1. 为什么必须做IMU标定:误差从哪来、不标的后果

很多初学者会有一个错觉:IMU芯片出厂前不是校准过的吗?为什么拿到的数据还是不准?这个问题我当年也困惑过。后来拆了几颗MEMS IMU的Datasheet才搞清楚,芯片厂出厂时的“校准”其实只做了非常基础的电气校准和温度补偿,真正决定传感器精度的机械安装误差、刻度非线性误差,尤其是三轴之间的非正交误差,通常不会在出厂时被充分修正。而且这些误差参数还会随温度、焊接应力、结构形变而改变,你每次重新打板、重新装配,i这些参数都要重新标。

1.1 零偏、尺度因子和轴偏差:三个绕不开的误差源

把IMU的误差模型拆开看,对纯惯性导航和融合定位影响最大的就三类:零偏(Bias)、尺度因子(Scale Factor)和轴间非正交误差(Misalignment)。

零偏最好理解,就是IMU静止时,输出并不归零,而是有一个恒定的偏置。对加速度计来说,这个偏置直接叠加在重力测量上,会导致水平姿态角出现倾斜误差。对陀螺仪来说,零偏更是致命,因为角速度积分一次就是角度,哪怕只有0.01 rad/s(约0.57°/s)的零偏,100秒后姿态就偏了57度。这就是很多人做完纯积分位姿解算后发现角度疯狂漂移、尤其是yaw方向慢漂的头号原因——不是算法不对,是陀螺零偏没标干净。

尺度因子是测量值与真实值之间的比例关系误差。比如你真实转了1 rad/s,传感器输出是0.98 rad/s,那尺度因子就是0.98。这个误差源在加速度计上通常表现为三个轴各自不统一,导致静止时合成矢量的大小虽然是g,但方向会偏。在陀螺仪上则表现为转动量测偏大或偏小,积分的总角度不对。

轴间非正交误差是最容易被忽略、但影响非常大的一项。理论上IMU的三轴应该是两两正交的,但实际封装和焊接过程中,Z轴与XY平面的垂直度很难保证,X和Y轴之间的直角也可能偏离90度。这个偏差会导致一个轴在旋转时,会在另外两个轴上产生串扰信号,比如你绕Z轴转,X轴陀螺却读到了角速度分量。这种串扰在融合算法里很难被在线估计掉,必须靠标定来补偿。

1.2 不标定的实际危害:轨迹畸形、外参失效、融合崩溃

不标定就直接用,最直观的后果是积分轨迹畸变。加速度计零偏会让速度持续累积,即使静止状态,速度也会随时间线性增长;陀螺仪零偏会让姿态缓慢旋转,导致后续所有坐标变换全部出错。做过纯IMU积分的人应该都有这种体验,静止放置几秒钟,位置就“飞”出去了,姿态角也在慢慢旋转,这就是所有误差源叠加的直观表现。

更隐蔽的危害体现在多传感器融合系统里。比如做LiDAR-Inertial或者Camera-Inertial系统,IMU内参(零偏、尺度、轴偏差)不准,会直接影响IMU与外传感器之间的外参标定结果。很多人做相机IMU联合标定或者LiDAR-IMU外参标定时发现结果要么收敛很慢,要么反复横跳,最后查来查去,问题出在IMU内参压根没标好。外参标定本质上是在估计两个传感器坐标系之间的变换,如果IMU本身的观测数据就带系统误差,那么等价于把一个不确定的变换也丢进了优化问题里,整条链路都会被拉歪。

所以我的建议一直很明确:无论做什么上层算法,IMU内参标定一定要放在最前面,这属于“脏活累活”,但绕不开,而且一次标定做好,后续能省下无数调试时间。

2. 不靠外部设备的标定原理:重力就是唯一的基准

这个方法的魅力就在于,它把复杂的标定问题变成了一个几乎零成本的数据拟合问题。不需要转台,不需要光学平台,不需要水平仪,唯一依赖的物理基准就是重力。有人可能会问,重力会不会因为经纬度和海拔不同而变化?会,但变化幅度极小。青岛的重力和西藏的重力也就差0.5%左右,做标定这种精度需求,直接取9.81 m/s² 或者用当地理论重力值都可以,影响在可接受范围内。

2.1 静止观测的物理本质:加速度计测的是比力

要理解这个标定方法,首先得把一个概念搞明白:加速度计在静止状态下,测量的不是“加速度”,而是比力(Specific Force),也就是支撑力产生的反作用力。放在桌面上静止时,加速度计测量到的不是0,而是向上的1 g。因为加速度计里的质量块被重力往下拉,却被外壳的机械约束推着保持静止,这个机械约束施加的力在加速度计坐标系里是竖直向上的。

这意味着什么?意味着当你把IMU以任意姿态静止放置时,加速度计三轴输出的矢量和的大小(模长)严格等于当地重力加速度值。矢量方向随姿态变化,但模长永远是g。这就是整个标定方法最核心的物理依据:不管你怎么放,只要静止,输出矢量的模长不变,恒等于g。

这跟拿一把尺子去量物体一样,重力就是一个“标准尺”。你的IMU姿态千变万化,但尺子的长度永远不变。如果我们能测出大量不同姿态下加速度计的原始输出,就能通过这些“长度恒定”的约束,反推出加速度计三轴各自的零偏、尺度因子和轴间非正交角度。

2.2 多位置法为什么能用最小二乘解参数

把误差模型写成数学形式。设加速度计真实比力(在IMU坐标系下投影)为 a_true,测量输出为 a_meas,常用的线性误差模型可以写成:

a_meas = S * K * (a_true + b)

展开写就是:

[ax_m] [sx mxy mxz] [ax_t + bx] [ay_m] = [myx sy myz] * [ay_t + by] [az_m] [mzx mzy sz ] [az_t + bz]

其中 sx、sy、sz 是三个轴的尺度因子,mxy 等六个参数表示轴间非正交耦合,bx、by、bz 是零偏。我们做标定,就是要估计出这九个参数。

现在问题是,我们不知道 a_true 的真实方向,只知道它的模长是 g。所以把等式两边取模长平方,就得到一个关于九个未知参数的约束方程:

|a_meas|² = g²

把误差模型代入这个约束,展开之后是一个包含九个未知参数的非线性方程。针对每一个静止姿态,我们采集一组 a_meas,就能列出一个这样的方程。理论上9个方程就能解9个未知数,但这里存在一个工程常识:解非线性方程组的数值稳定性极差,而且对初始值非常敏感。更稳妥的做法是,采集几十组甚至上百组不同姿态下的静止数据,把问题转化成一个最小二乘优化问题,让所有姿态下的残差平方和最小。

为什么这里能用最小二乘而不是更复杂的算法?因为问题天然满足最小二乘的两个前提:一是约束方程连续可导,二是误差近似服从高斯分布且独立同分布。采集的数据量足够大时,随机噪声会被平均掉,系统误差则会被拟合出来。这也是这个“任意姿态法”比传统“六面法”更稳健的原因——六面法要求每个面都精准对齐水平/垂直,摆放误差会直接带入解算,而任意姿态法采集大量位姿,单个身位的摆放误差只会贡献一个噪声样本,对整体拟合结果几乎无影响。

2.3 陀螺仪标定的边界:能标什么、不能标什么

这里必须泼一盆冷水:标题说的“无需外部设备的鲁棒标定”,主要针对的是加速度计内参和陀螺仪零偏。陀螺仪的尺度因子和轴间非正交误差,靠静止多位置法是标不出来的。因为陀螺仪测量的是角速度,静止时角速度恒为零,只有地球自转分量(约15°/小时),这个量级对消费级MEMS陀螺来说完全淹没在噪声里,根本无法作为基准。

那陀螺仪的尺度因子和非正交误差怎么办?在实际工程里,有两种常见处理方式。一种是借助外部设备,比如转台或者机械臂,施加已知角速度激励,通过对比输出反推参数。另一种就是依靠多传感器融合系统在线估计,比如LIO和VIO系统在优化过程中通常会把陀螺仪零偏和尺度因子作为状态量的一部分,随着系统运行不断更新。

所以我的建议是:如果你只做纯IMU航位推算,至少要把零偏标干净,这是投资回报率最高的一步。如果你做的是带有视觉或激光雷达的融合系统,靠在线估计把其余参数慢慢学出来,也是一种可行路径,但内参标定作为初值仍然非常重要。

3. 实操流程:从数据采集到参数求解的完整步骤

原理聊完了,下面是实操部分。这一套流程我在多个IMU型号上都验证过,包括MPU6050、ICM20602、BMI088、ADIS16470等,流程基本通用,只要你的IMU能输出原始加速度计三轴数据和陀螺仪三轴数据即可。

3.1 数据采集的姿势设计和时长建议

采集数据的核心要求是:在足够多的不同姿态下,每个姿态保持静止足够长的时间。

具体做法是,把IMU模组固定在手机、木板或者任何你觉得顺手的小平台上,让平台可以自由放在桌上、墙上、斜面上。每摆放好一个姿态,等待传感器读数稳定后,连续采集5到10秒的数据(建议至少3秒以上)。然后换一个完全不同的姿态,再采集5秒。如此反复,采集30个以上不同姿态的数据。

这里有几个关键细节要特别提醒。第一,每个姿态之间最好尽量拉开差异,比如绕三个轴旋转覆盖不同的俯仰、横滚、航向角组合,尽量让加速度计三个轴的读数组合覆盖更大的球面区域。如果采集的姿态都集中在某个平面附近,参数的条件数会比较差,解出来的结果也不稳定。第二,数据采集过程中务必确保设备真正静止,如果采集时手还在抖、数据还在晃,这些样本会直接影响拟合质量。建议每次换姿后停留1到2秒,等晃动衰减后再开始采集。第三,采集环境要避开明显的振动源,比如不要放在运行的电机旁边,不要放在桌子上有人在敲键盘的抖动环境中。

按每个姿态10秒、30个姿态来算,整个采集过程大约5到6分钟,从工程角度来说完全不算负担。这比转台标定动辄几个小时的流程要轻量太多了。

3.2 数据处理与参数求解(附Python实现)

数据采集完成后,先把每个静止段内的数据做平均处理,得到一组代表该姿态的加速度计三轴测量值 a_meas。这一步能有效去除传感器的高频随机噪声。然后把所有姿态的平均值按行堆叠成一个矩阵,进行参数求解。

我自己常用的是Python + NumPy直接写,核心思路是用SciPy的优化工具做最小二乘拟合。下面这个代码可以直接拿来改改用。

import numpy as np from scipy.optimize import least_squares # data: shape (N, 3),每一行是一个姿态下加速度计三轴平均输出,单位 m/s^2 # G: 当地重力加速度值,一般取 9.81 def imu_acc_calib(data, G=9.81): n = data.shape[0] # 初始化:尺度默认1,非正交耦合默认0,零偏默认0 x0 = np.array([1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) def residual(x): sx, sy, sz, mxy, mxz, myx, myz, mzx, mzy = x bx, by, bz = x[6], x[7], x[8] # 补偿后的真实比力估计 a_pred = np.zeros((n, 3)) a_pred[:, 0] = (data[:, 0] - bx) / sx a_pred[:, 1] = (data[:, 1] - by) / sy a_pred[:, 2] = (data[:, 2] - bz) / sz # 模型里把非正交耦合近似为小角度旋转补偿 # 这里采用简化模型:非正交项作为交叉轴比例耦合 a_real = np.zeros((n, 3)) a_real[:, 0] = a_pred[:, 0] + mxy * a_pred[:, 1] + mxz * a_pred[:, 2] a_real[:, 1] = myx * a_pred[:, 0] + a_pred[:, 1] + myz * a_pred[:, 2] a_real[:, 2] = mzx * a_pred[:, 0] + mzy * a_pred[:, 1] + a_pred[:, 2] # 约束:模长等于 G return np.linalg.norm(a_real, axis=1) - G res = least_squares(residual, x0, method='lm') return res.x # 使用示例 # x = imu_acc_calib(acc_data) # sx, sy, sz, mxy, mxz, myx, myz, mzx, mzy, bx, by, bz = ...

这个实现里我用了简化模型,把非正交耦合表达为交叉轴的比例项,好处是初值好给、收敛快、代码短。真正严格的误差模型应该用旋转矩阵表示非正交性,但工程上这两种表达在小角度假设下结果差异极小,完全够用。

陀螺仪零偏的估计就更简单了。同样利用静止段数据,但取的是陀螺仪三轴输出的平均值,即:

bias_gyro = mean(gyro_data, axis=0)

也就是把所有静止段的陀螺仪原始角速度输出求平均。这个平均结果就是陀螺仪的常值零偏估计。静止时间越长、累积的姿态越多,平均下来零偏估计越精确。

3.3 标定结果验证:残差分析和重复性测试

参数解出来了,很多人就直接用了,这其实是个坑。标定结果必须经过验证,否则参数收敛到局部最优而你毫不知情,直接跑上层系统的时候才会发现问题,那时候排查成本就高了。

第一个验证指标是拟合残差。把标定后的参数代回误差模型,反算出每个姿态下补偿后的比力矢量的模长,算一下与G的差值。如果平均残差在0.001 g到0.005 g这个量级,说明模型拟合得不错。如果残差到0.05 g甚至更高,说明采集数据里有异常姿态或者模型本身不适配,需要重新采集。

第二个验证指标是重复性测试。把IMU重新摆放姿态,采集一组和标定时完全不同的静止数据,用刚才标定的参数做补偿,看看补偿后的模长与G的偏差。如果前一组残差很小、这组测试数据却很拉胯,说明标定过拟合了,通常是因为采集姿态分布不够广,或者采集数据量太少。

再一个非常实用的验证方式,是直接观察静止时IMU经过标定补偿后的输出稳定性。把IMU放平,采集补偿后的加速度计三轴数据和陀螺仪三轴数据,观察一段时间,好的标定结果会让加速度计X/Y轴读数趋近0、Z轴读数趋近G,陀螺仪三轴读数趋近0且波动很小。这一条每个人都能直观感受,不需要任何额外工具。

4. 常见问题与排查技巧实录

标定流程本身不复杂,但我在实际使用中确实踩过不少坑,也在各种社区交流群里看到过不少同行踩坑后一头雾水。下面这些问题是我遇到过的或者被问过很多次的,统一整理出来,希望能帮你少走弯路。

4.1 标定后yaw依然缓慢漂移是正常现象

这个问题在标题相关热词里出现了,说明很多人标完IMU之后发现yaw还是慢慢在飘,于是怀疑标定流程有问题。但我必须说清楚:这是正常现象,别慌。

yaw方向的持续慢漂,本质上是航向角不可观导致的。在没有外部参考的情况下,纯IMU的yaw只能靠陀螺仪积分获得,陀螺仪的零偏确实会被标定掉大部分,但残留下来的零偏残差和随机游走依然存在,积分到一定时间就会导致yaw漂移。这不是标定能解决的,是纯惯性导航的通病。可以说,哪怕你用了转台把陀螺仪尺度因子标得再精准,纯积分250秒后yaw照样漂,只是漂多漂少的问题。

解决yaw漂移的正确思路,是引入外部观测约束,比如磁力计、视觉、激光点云匹配或者GPS航向。这也解释了为什么LiDAR-IMU、Camera-IMU这套组合在业界会这么流行——它们本质上就是在用外部传感器持续修正IMU的积分漂移,其中yaw方向的修正尤为关键。如果你在做纯IMU位姿解算,建议先降低对yaw精度的预期,把精力放在短期姿态稳定性和高频响应的优化上。

4.2 重力对齐、外参标定和IMU内参标定的执行顺序

“IMU重力对齐”是热词里另一个高频出现的概念。很多人会把重力对齐和内参标定混为一谈,其实这是两件事。重力对齐(Gravity Alignment)通常指在系统启动阶段,通过加速度计静止时的输出来估计当前姿态相对于重力方向的初始横滚角和俯仰角,也就是常说的“初始姿态对准”。它依赖的是加速度计的测量精度,所以内参标定的结果会直接影响初始姿态对齐的精度。可以说,内参标定是重力对齐的前提。

还有一个执行顺序问题值得提醒。如果你要做LiDAR-IMU或者Camera-IMU联合标定,一定先做IMU内参标定,再做外参标定。外参标定过程中,IMU的观测数据会被反复用于构建约束方程,如果内参含系统性误差,外参优化就相当于在输入端掺了噪声,结果往往是外参收敛了但精度很差。更麻烦的是,这种误差很难从外参结果里直接看出来,因为优化残留也被吸收进了外参里。我自己就吃过这个亏,联合标定结果反复验证都对不上,最后回头重标IMU内参,问题立刻解决。

4.3 温漂、振动和采样率:三个容易翻车的细节

温漂是所有MEMS传感器都绕不开的话题。IMU零偏随时间、温度漂移,这个特性决定了“一次标定、终身使用”在严苛环境下不成立。如果你的设备经常在温差很大的环境中使用,比如从室内冷空调环境拿到室外暴晒环境,建议做一次“快速温度标定”:在不同温度节点下各静止采集一段数据,看陀螺零偏的变化幅度。如果变化明显,可以考虑在算法里加入温度补偿项,或者至少在系统热稳定后再执行初始对准。

振动是另一个容易翻车的点。多位置法要求静止,但“静止”的判断标准是什么?我的经验是看陀螺仪输出方差。电磁屏蔽不好的IMU,放置在电机旁边静止时,陀螺仪输出可能依然有较大抖动,这种环境下采集的数据质量很差。判断方法很简单:在数据采集脚本里实时打印陀螺仪三轴的方差,如果某个姿态下方差明显偏大,就换一个位置重新采集。

采样率这件事看着不起眼,实际影响也不小。IMU数据采集尽量使用高频模式,比如400 Hz到1000 Hz,然后在静止段内取平均,这比低频采集能更好地抑制随机噪声。但要注意,采集过程中IMU的姿态必须严格不变,如果稍微有微小的移动,高频数据反而会把细微的角运动也采集进来。所以严谨的流程是:确认静止——采集高频原始数据——对静止段做时域平均得到一个样本。这个小流程很多人嫌麻烦直接省了,结果标定效果大打折扣。

最后再分享一个小技巧。如果你标定完发现残差始终偏大,先别急着怀疑算法,检查一下数据里是不是混入了“切换姿态过程中”的过渡数据。我的做法是,每个姿态的数据采集之前加一个自动检测逻辑,用滑动窗口计算加速度计输出的方差,连续若干ms方差稳定小于阈值才启动采集,这样能彻底避开手持切换姿态时的晃动段。这个细节在自动化采集脚本里尤其重要,能帮你省掉大量人工筛选数据的力气。

IMU内参标定这件事,做得好的人可能觉得不值一提,但真的能踏踏实实把误差模型讲清楚、把数据采集流程走完整、把结果验证做到位的人,其实不多。希望这一篇能让你在标定这条路上少走弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询