4、IMU误差模型与标定:IMU工作原理、加速度计与陀螺仪误差模型(零偏、尺度因子、交轴耦合)、六面法标定
好,咱们今天聊聊IMU的误差模型和标定。说实话,IMU这东西看着简单,就是个测加速度和角速度的传感器,但真要把它用好,误差模型这块必须吃透。我刚开始做车载项目那会儿,就吃过亏——IMU数据直接拿来用,结果定位飘得亲妈都不认识。后来才明白,不标定的IMU就是个“半成品”。
4.1 IMU工作原理:它到底怎么测的?
IMU的核心就两个东西:加速度计和陀螺仪。加速度计测的是比力,说白了就是物体受到的惯性力减去重力。陀螺仪测的是角速度,也就是你转得有多快。
加速度计内部有个质量块,外面连着弹簧。你加速的时候,质量块会动,弹簧的形变转换成电信号,就得到了加速度值。陀螺仪稍微复杂点,MEMS陀螺仪用的是科里奥利效应——一个振动的质量块,你一转它,它就会产生一个垂直于振动方向的位移,测这个位移就知道角速度了。
嗯,这里要注意:加速度计测的不是重力,是比力。静止的时候它测的是重力加速度g,但如果你在自由落体,它测出来是0。这个细节很多新手会搞混。
核心要点:加速度计输出的是比力(f = a - g),陀螺仪输出的是角速度(ω)。理解这个,后面标定才有意义。
4.2 误差模型:为什么IMU不准?
理想情况下,IMU输出应该和真实值完全一致。但现实嘛,总得有点“瑕疵”。IMU的误差主要分三类:零偏、尺度因子、交轴耦合。我一个个说。
4.2.1 零偏(Bias)
零偏就是IMU静止时,输出不为0。比如加速度计平放着,按理说z轴应该输出g,x和y轴输出0。但实际测出来,x轴可能有个0.05 m/s²,y轴有个-0.03 m/s²。这就是零偏。
陀螺仪也一样,静止时角速度应该是0,但实际可能有个0.01 rad/s的输出。这个零偏会随时间漂移,温度一变它也变。我在项目中遇到过,IMU刚上电和运行半小时后,零偏能差好几倍。所以标定不是一次性的,最好每次上电都做。
零偏的数学模型很简单:
a_measured = a_true + b_a + noise
ω_measured = ω_true + b_g + noise
其中b_a是加速度计零偏,b_g是陀螺仪零偏。单位分别是m/s²和rad/s。
4.2.2 尺度因子(Scale Factor)
尺度因子就是增益误差。你输入1g的加速度,它输出可能是1.02g;输入2g,输出2.05g。这个比例不对,就是尺度因子问题。
说白了,就是IMU的“刻度”不准。陀螺仪也一样,你转10°/s,它可能输出9.8°/s。这个误差通常用百分比表示,比如2%的尺度因子误差,意味着100°/s的输入会输出102°/s。
数学模型加进来:
a_measured = s_a * a_true + b_a + noise
ω_measured = s_g * ω_true + b_g + noise
s_a和s_g就是尺度因子,理想情况下等于1。实际可能在0.98到1.02之间。
4.2.3 交轴耦合(Cross-axis Sensitivity)
这个稍微绕一点。理想情况下,IMU的三个轴应该是完全正交的,x轴只测x方向的加速度,y轴只测y方向的。但实际制造时,三个轴不可能绝对垂直,总会有点偏差。
比如x轴方向有加速度,y轴也能测到一点。这就是交轴耦合。我见过最夸张的一次,一个低端IMU,x轴加速度有10%串到了y轴上。这种数据做融合,姿态能偏到姥姥家。
完整的误差模型长这样:
a_measured = M_a * a_true + b_a + noise
ω_measured = M_g * ω_true + b_g + noise
其中M是一个3x3的矩阵,包含了尺度因子和交轴耦合:
M = [s_xx, m_xy, m_xz;
m_yx, s_yy, m_yz;
m_zx, m_zy, s_zz]
对角线是尺度因子,非对角线是交轴耦合系数。理想情况下,M是单位矩阵。
个人经验:我建议标定时至少估计12个参数(3个零偏 + 3个尺度因子 + 6个交轴耦合)。有些低成本IMU,交轴耦合能到5%以上,忽略它后果很严重。
4.3 六面法标定:最经典的加速度计标定方法
六面法,顾名思义,就是把IMU放在六个不同的姿态下采集数据。这六个姿态分别是:x轴朝上、x轴朝下、y轴朝上、y轴朝下、z轴朝上、z轴朝下。
为什么是这六个?因为每个姿态下,重力在某个轴上的投影是已知的。比如z轴朝上时,理论上加速度计输出应该是[0, 0, g];z轴朝下时是[0, 0, -g]。利用这些已知值,就能反推出误差参数。
具体步骤是这样的:
- 把IMU固定在一个水平平台上,确保姿态准确
- 记录每个姿态下至少10秒的静态数据,取平均
- 六个姿态的数据凑齐后,用最小二乘法求解
我曾经犯过一个低级错误:用三脚架手动翻转IMU,结果每次翻转后平台没放平,标定出来的参数全是错的。后来我学乖了,用精密转台或者至少用水平仪确认一下。
六面法的数学模型:
对于每个姿态i,有:
a_measured_i = M_a * a_true_i + b_a
其中a_true_i是已知的(重力在三个轴上的投影),a_measured_i是实测值。
写成矩阵形式:
[a_measured_x, a_measured_y, a_measured_z] = M_a * [a_true_x, a_true_y, a_true_z] + b_a
六个姿态,12个方程(每个姿态3个轴),求解12个未知数。
代码实现大概这样:
import numpy as np
# 六个姿态的理论值(假设g=9.81)
g = 9.81
true_acc = np.array([
[g, 0, 0], # x朝上
[-g, 0, 0], # x朝下
[0, g, 0], # y朝上
[0, -g, 0], # y朝下
[0, 0, g], # z朝上
[0, 0, -g] # z朝下
])
# 实测值(示例数据)
meas_acc = np.array([
[9.85, 0.12, -0.08],
[-9.78, 0.09, 0.05],
[0.15, 9.82, -0.10],
[-0.11, -9.79, 0.07],
[0.08, -0.06, 9.88],
[-0.05, 0.04, -9.76]
])
# 构建最小二乘问题
# 这里简化处理,实际需要解12个参数
# 可以用线性最小二乘或非线性优化
# 推荐用scipy.optimize.least_squares
避坑指南:我曾经用六面法标定一个工业级IMU,结果发现标定后误差反而变大了。排查了半天,原来是标定过程中温度变化了5度,零偏漂移把标定结果全毁了。所以标定一定要在恒温环境下做,或者至少记录温度做补偿。
4.4 陀螺仪标定:比加速度计麻烦一点
陀螺仪的六面法不太一样。因为陀螺仪测的是角速度,静止时所有轴输出都应该是0。所以六面法只能标定零偏,标不了尺度因子和交轴耦合。
要标定陀螺仪的尺度因子和交轴耦合,需要转台。让IMU绕每个轴以已知角速度旋转,记录输出,然后解方程。如果没有转台,也可以用地球自转来标定——但地球自转只有15°/h,信号太弱,对低精度IMU基本没用。
我个人的做法是:对于消费级IMU,陀螺仪只标零偏,尺度因子和交轴耦合用出厂参数。对于工业级或战术级IMU,必须上转台做全参数标定。
陀螺仪零偏标定很简单:静止采集30秒数据,取平均就是零偏。注意要扣除地球自转的影响(如果你在赤道附近,地球自转在水平轴上的投影最大,大约15°/h)。
总结一下:
- 加速度计:六面法标定12个参数(3零偏+3尺度+6交轴)
- 陀螺仪:静止法标零偏,转台法标全参数
- 温度影响:零偏随温度变化明显,建议做温度补偿
- 标定频率:每次上电最好重新标零偏,全参数标定可以3-6个月做一次
嗯,IMU误差模型和标定这块,说白了就是“知己知彼”。你知道它哪里不准,才能想办法补偿。六面法是最基础的方法,但也是最实用的。我到现在做项目,第一件事就是拿六面法把加速度计标一遍,心里才有底。
下一章咱们聊聊多传感器时空同步,那个更刺激——激光雷达和相机的时间戳对不上,融合出来的点云全是重影。到时候我给你们讲讲我踩过的坑。