☰
IMU标定避坑指南:从零偏建模到壳体失准角,飞控落地的关键一步
2026/10/2 16:53:32 网站建设 项目流程

前阵子帮一个做飞控的团队排查落地漂移问题,我问他们的IMU标定是怎么做的。对方说得很顺畅:模块平放一分钟取平均值当零偏,六个方向各停十秒算比例因子,然后直接装到无人机上。我一听就知道问题出在哪了——这套流程只能算"测了个静态零偏",而真正意义上的IMU内参标定要覆盖的误差项,比这多一个数量级。这几年接触的无人机、机器人、自动驾驶项目里,我越来越确信一件事:中文互联网上能搜到的IMU标定教程,大部分是错的,或者说严重不完整。这篇文章我就从工程实际的角度拆一拆,到底错在哪、正确做法长什么样,以及那些总被跳过的误差项是怎么一步步毁掉你的状态估计的。

不说废话,先给结论:IMU标定这件事,核心干扰不是"你没停够时间",而是"你的模型根本没建全"。我见过太多团队把时间精力花在延长静置时间、反复翻转采集上,却连加速度计和陀螺仪之间的壳体安装误差是什么都不知道。这种标定流程跑完后,在桌子上看数据好像很稳定,一上机器人、一上飞机,姿态几分钟就飘走。下面我从最简单的误区开始,按误差项逐个拆。

1. 中文教程的病灶:把"测零偏"当成"标定IMU"

1.1 一个典型的中文教程流程,以及它到底解出了什么

大多数网上教程是这样教你的:

  1. IMU平放,开机静止一分钟,记录加速度计三轴均值,当作零偏。
  2. 找出重力方向对应的轴(比如Z轴),用输出减掉9.8,算出该轴比例因子。
  3. 三个轴分别朝上、朝下各测一次,取平均值作为该轴比例因子。
  4. 陀螺仪呢?静止放置,取三轴输出均值,当作陀螺零偏。

这套流程有没有用?有一点用,前提是你对精度的要求低到只求"符号别反、大概别飘得太离谱"。但放在LIO(激光惯性里程计)、VIO(视觉惯性里程计)、组合导航这种需要长期低漂移的场景里,它是远远不够的。为什么?因为一颗MEMS IMU真实的误差模型远比"零偏+比例因子"复杂。以工程上常用的简化模型为例:

加速度计输出大致可以写成:

a_meas = S_a * (I + M_a) * a_true + b_a + n_a

其中,S_a是三个轴的比例因子矩阵(3个参数),M_a是交轴耦合/非正交误差(完整形式是3x3矩阵,考虑对称性至少6个独立参数),b_a是零偏(3个参数),n_a是噪声。这还只是"静态模型",没算温度、非线性、振动整流这些动态项。

陀螺仪更复杂一些:

w_meas = S_g * (I + M_g) * w_true + b_g + G_g * a_true + n_g

注意最后多了一项G_g * a_true。这一项叫g敏感度(g-sensitivity)或者振动整流误差(VRE),意思是陀螺仪的输出会受外部加速度影响。无人机激烈机动、车载剧烈颠簸时,这一项的影响会被直接放大。

你看,光是内参部分,正经标定至少要覆盖十几个参数。而网上教程教的那套"平放取均值、六面取差值",能解出来的仅仅是零偏和粗略比例因子,而且是建立在"三个轴完全正交、陀螺仪完全不受加速度影响"这个根本不成立的前提上。

1.2 把"校准"当"标定"的命名混淆

还有一个很常见的概念混淆。很多人会把"标定板标定"“九点标定”“IMU标定”混在一起搜,因为都带"标定"两个字。实际上这三个东西完全是不同领域的操作:

  • “标定板标定”是相机标定,比如张正友标定法,用棋盘格或者AprilGrid计算相机内参和畸变。
  • “九点标定”最常见的是触摸屏/机械臂示教器的线性校正,用九个已知点拟合二维变换。
  • IMU多位置法/速率法标定则是惯性传感器的误差辨识。

它们没有任何通用步骤,只是中文里都叫"标定"。如果你在搜教程时发现文章在讲棋盘格拍摄或者触摸屏点选,赶紧退出去找下一篇。这不是术语之争,而是说明很多中文教程的作者自己就没分清楚这些概念。

2. 加速度计标定:六面法只能算入门,交轴误差藏得最深

2.1 六面静止法的数学本质,以及它为什么会在倾斜姿态下崩掉

先给六面法说句公道话:它的原理本身没问题,就是用重力作为已知激励。当加速度计某个轴竖直朝上时,该轴的理论真值是+1g(或者-1g,取决于定义方向),其他轴理论为0。如果假设三个轴完全正交,那么只需要测量六个方向,就能解出每个轴的比例因子和零偏。

比如X轴朝上时,输出a_x_up = s_x * 1g + b_x;X轴朝下时,输出a_x_down = s_x * (-1g) + b_x。两式相减得到比例因子,相加得到零偏。这个逻辑很漂亮。

问题在于:MEMS加速度计的三轴并不是正交的"理想轴"。由于MEMS工艺里硅片蚀刻的角度偏差、封装应力、贴片时的胶层不均匀,三根敏感轴之间可能有0.1°到1°量级的非正交角。这个量级的交轴误差,在静态测量1g重力时,最坏情况下会给别的轴贡献1g * sin(1°) ≈ 0.017g的误差。表面上看,0.017g好像不大——换算成姿态角误差大约是1°。但注意,这个误差是系统性偏置,不是随机噪声,它不会因为你多测几次就消除,而且会随姿态变化以不同方式混入解算结果。在紧耦合的LIO/VIO系统里,1°的姿态偏差经过几分钟积分,位置漂移可能是几十米。

更麻烦的是,六面法的模型里根本没有交轴耦合项。你用六面法解出的"比例因子"和"零偏",实际上是真实比例因子、零偏加上交轴误差的混合结果。在水平姿态下可能表现良好,一旦飞行器做大角度倾斜、旋转,残差就会暴露出来。

2.2 多位置法怎么建完整模型

正确思路是放弃"每个轴单独解"的简化,直接用一个统一的最小二乘模型去估计所有参数。工程上常用的是九位置法或者十二位置法,优先推荐十二位置以上,因为冗余观测能平滑噪声并且覆盖更多姿态。

模型是:

meas_n = S_a * (I + M_a) * ref_n + b_a

其中ref_n是第n个位置下,由夹具姿态和重力方向严格算出的理论比力向量。把待求的12个参数(3个零偏、3个比例因子、6个交轴耦合项)排成向量,所有位置的测量值排成观测向量,就得到一个线性方程组,用最小二乘一步解完。

我贴一段简化版的核心代码,方便你理解建模过程:

import numpy as np # meas: (N,3) 每个位置下加速度计的实测比力,单位g # ref: (N,3) 由夹具姿态计算出的理论重力向量投影,单位g N = meas.shape[0] A = np.zeros((3 * N, 12)) y = np.zeros(3 * N) for i in range(N): y[i*3:i*3+3] = meas[i] # bias项 A[i*3+0, 0] = 1.0 A[i*3+1, 1] = 1.0 A[i*3+2, 2] = 1.0 # scale因子 A[i*3+0, 3] = ref[i, 0] A[i*3+1, 4] = ref[i, 1] A[i*3+2, 5] = ref[i, 2] # 交轴耦合项 A[i*3+0, 6] = ref[i, 1] A[i*3+0, 7] = ref[i, 2] A[i*3+1, 8] = ref[i, 0] A[i*3+1, 9] = ref[i, 2] A[i*3+2, 10] = ref[i, 0] A[i*3+2, 11] = ref[i, 1] coef, _, _, _ = np.linalg.lstsq(A, y, rcond=None)

这只是示意。实际工程里还要处理单位统一、坐标方向约定、异常值剔除。但模型从"3轴独立"变成"12参数联合估计"这一步,是质的差别。

2.3 实际操作里最容易翻车的三个地方

第一,夹具。别用手拿着模块翻来翻去,手温会造成温漂,手指的微小抖动也会污染数据。做一个简单的L型角铝夹具,把IMU固定在上面,再把夹具放到大理石平台或调平过的桌面上。水平精度用气泡水平仪不够,最好用数显倾角仪确认参考面误差在0.05°以内。

第二,静置时间。MEMS加速度计输出里含有噪声,每个位置至少要记录20到30秒然后取平均,只取前两秒数据会吃进很大的随机噪声。我见过有人每个位置停3秒就换方向,最后解出来的参数方差大到下一轮实验完全无法重复。

第三,激励充分性。十二位置法不是随便转出十二个姿态就行,要保证姿态在三维空间里分布均匀,比如立方体的6个面加8个顶角的一部分。如果你的十二个位置全都集中在"Z轴朝上附近",重力向量始终近似平行于Z轴,那X轴、Y轴的比例因子和交轴项就完全没有被激励,解出来等于猜。

3. 陀螺仪标定必须上转台:静态法测不了比例因子

3.1 为什么静止放置对陀螺仪来说几乎毫无意义

这是中文教程里第二大误区。很多教程说"陀螺仪标定就是静止放置,把输出均值当作零偏",然后就没有然后了。问题是,陀螺仪是角速度传感器,它的比例因子、非正交误差、g敏感度都需要已知的角速度输入作为激励。静止放置时角速度真值是0,你只可能测出零偏和噪声,其他误差项一个都测不到。

就算只测零偏,静止一分钟也不够。MEMS陀螺仪的零偏不只是固定值,还包括零偏不稳定性(bias instability)和缓慢的温变漂移。严格点说,一开机电热还没平衡时测出的零偏,和跑半小时后的零偏可能差好几个°/s的量级。所以哪怕只标零偏,也建议至少让IMU上电预热15分钟,再静止采集5到10分钟取平均。

3.2 速率转台标定的标准流程

正确的陀螺仪标定,至少要有单轴速率转台,能输出稳定的已知角速度。流程是这样的:

  1. 把IMU固定在转台上,让待标定的轴(比如Z轴)尽量对准转台旋转轴。夹具安装误差需要测量并记录,最好控制在0.1°以内。
  2. 设置一系列转速点。工程上通常正转、反转各取至少4到5个点,比如±30、±60、±120、±240°/s。每个点稳定后记录60秒以上的输出均值。
  3. 对每个轴的每个速率点,得到一组"设定角速度 vs 实测输出"。用正反两个方向的点一起做线性拟合,斜率就是比例因子,截距就是零偏,拟合残差的非线性度就是刻度非线性误差。

下面是一组典型数据的形态:

设定转速(°/s)正向输出(°/s)反向输出(°/s)
3030.42-30.35
6060.88-60.71
120121.60-121.30
240243.00-242.50

对这组数据做直线拟合,斜率大约是1.0128,也就是说该轴的比例因子误差是1.28%。这个量级的比例因子误差,不标定的话,在240°/s转速下会带来约3°/s的输出误差,累积几十秒就是几十度,根本不是算法能扛住的。

3.3 被忽略的g敏感度和振动整流

如果你觉得转台做完就结束了,那还差一步。MEMS陀螺仪有一项非常隐蔽的误差:输出会随比力(specific force)变化,也就是前面模型里的G_g * a_true项。你可以做一个很简单的实验:把IMU分别水平放置、竖直侧放、倒置,每次静止采一分钟陀螺仪Z轴输出,会发现三次结果不一样。这种差异在便宜的消费级IMU上可能达到±0.5°/s甚至更大。

标定g敏感度的方法,是把IMU以不同姿态安装在转台上(或者用六维转台),在每个姿态下维持零角速度,测出陀螺仪零偏的变化量,然后用这些数据拟合一个3x3矩阵。这个矩阵在实际飞行里非常关键,因为无人机螺旋桨振动和高G机动会持续产生比力,g敏感度会直接把振动整流成虚假角速度,灌进姿态解算里。

所以我的建议是:如果你的产品要上无人机、车载或者任何高振动场景,别省掉g敏感度标定。中高端模组(比如频响和稳定性都做得不错的EM系列石英IMU,以及一些带出厂校准的工业级模组)g敏感度会小一些,但依然建议实测,而不是信规格书。

3.4 顺便说一句:Allan方差不是标定

中文教程里还有一个高频混淆:把Allan方差分析当成标定。Allan方差是一种分析手段,用来从静态数据里提取量化噪声(angle random walk)、零偏不稳定性(bias instability)、速率随机游走(rate random walk)等噪声参数。它对系统辨识和算法滤波调参非常有用,但它不是标定——它不会给你任何误差修正系数。如果你看到一篇文章用Allan方差算完就说"IMU标定完成",那它只完成了噪声谱分析,误差模型一项都没解。

4. 壳体安装误差:加速度计和陀螺仪根本不在同一坐标系

4.1 一个被中文教程整体跳过的问题

不知道你有没有想过:IMU外壳上标的坐标系,加速度计的三个敏感轴和陀螺仪的三个敏感轴,真的是完全重合、完全正交的吗?

大概率不是。MEMS IMU内部,加速度计芯片和陀螺仪芯片是两颗不同的裸片(die),各自贴装到基板上。贴片机的精度、焊料的厚度、封装应力,都会让加速度计坐标系和陀螺仪坐标系之间存在一个很小的角度差,通常称为壳体失准角(housing misalignment)或轴间失准角。典型值在0.1°到1°之间。对很多算法工程师来说,他们拿到IMU的SDK,默认加速度计坐标系就等于陀螺仪坐标系。这个假设在低速运动中问题不大,但在剧烈旋转运动里会变成持续的姿态误差源。

举一个具体场景:无人机做绕Z轴快速偏航运动,比如90°/s的偏航。如果加速度计的X轴和陀螺仪的X轴之间有0.5°的安装偏差,那么陀螺仪测到的角速度会被错误地投影一部分到加速度计坐标系上,换算成姿态四元数时,原本应该只有Z轴转动的运动,会混入几分X轴的伪转动。姿态误差持续累积,融合算法里的重力向量方向被一点点带偏,最后表现就是水平漂移和锥形运动误差。

4.2 在没有六维转台的情况下怎么标壳体安装误差

很多人看到"壳体安装误差"就摇头,觉得自己的实验室里没有六维转台。实际上,有一种简化方法只需要水平转台就能做,精度足够大多数应用:

  1. 把IMU固定在水平转台上,让壳体Z轴竖直(用夹具和水平仪保证)。
  2. 让转台绕垂直轴旋转,同时记录加速度计和陀螺仪的输出。
  3. 在匀速旋转阶段,加速度计测的是重力向量在其坐标系里的方向——如果IMU的加速度计坐标系Z轴不是严格竖直,那么X轴和Y轴会测出一个很小的重力分量;陀螺仪测的是旋转角速度向量在其坐标系里的方向。两者在水平面上的投影方向之差,就是加速度计坐标系和陀螺仪坐标系之间的相对偏航失准角。
  4. 重复这个实验,但把IMU分别侧倾、俯仰固定,即可分离出完整的三个失准角分量。

如果没有转台,也可以用"已知角度旋转法":先把IMU放在可读取角度的云台上,绕一个轴旋转已知角度(比如90°),用加速度计推算旋转轴方向,再用陀螺仪积分推算旋转轴方向,两者之差就是壳体失准角在测量中的体现。手动云台精度差一些,但至少能暴露0.5°以上级别的失准,比完全忽略强得多。

4.3 壳体系、载体坐标系和"外参"的边界

这里提醒一句:壳体安装误差是IMU内部两颗芯片之间的关系,属于内参。而IMU作为整体装在无人机机架、机器人底盘上时,IMU坐标系和机体坐标系之间的关系,属于外参(也叫boresight安装角,以及杆臂lever arm)。很多教程把"装机后要把IMU装水平"这种活儿也塞进"IMU标定"里,倒也不算错,但你要清楚它和你用转台标内参是两码事。lidar和IMU之间的外参标定,更是另外一个完全不同的数学问题,下面细说。

5. lidar/相机与IMU的外参标定:手眼方程和时间同步

5.1 从内参到外参:T_imu_lidar是怎么解出来的

内参标定解决的是"传感器自己测得准不准",外参标定解决的是"多个传感器坐标怎么对齐"。现在做LIO(激光惯性里程计)、多传感器融合定位、BEV感知,都绕不开lidar和IMU的外参标定。比如你的激光雷达在车顶,IMU在车体中间,两者之间有一个固定的位姿变换,记作T_imu_lidar,包含3x3旋转矩阵和3x1平移向量。

经典做法是利用手眼标定方程,AX = XB。A是从lidar帧间配准得到的lidar运动变换,B是从IMU预积分得到的IMU运动变换,X就是待求的T_imu_lidar。数学上通常先把旋转解出来,再代入求平移(类似Tsai-Lenz法的思路)。工程上已经有一些开源工具可以直接用:比如lidar_align,LIO-SAM这类紧耦合SLAM里也内置了对外参的在线估计模块,还有针对多雷达和IMU联合标定的更完整工具链。

实际操作里,我看到最多的问题不是数学推导,而是采集数据质量太差。手眼标定对运动激励要求很高:你得让载体做包含三轴旋转和三轴平移的充分激励。如果只在水平面上绕圈,旋转激励只有Z轴,X轴、Y轴的旋转外参参数就是欠约束的,解出来方差很大。我建议采集时做几组"8字绕行+俯仰点头+侧倾摇摆"的组合动作,速度不要太快,但要能明显激励所有轴。

5.2 时间同步和轨迹退化,两个最容易被忽视的坑

外参标定对时间同步非常敏感。如果lidar和IMU的时间戳没有对齐到同一个时钟,哪怕只差20毫秒,在快速旋转运动中解出的外参会带上虚假的旋转量,而且是"同一组数据换个运动又变"的那种不稳定结果。所以做外参标定前的第一件事,是确认时间戳单调性、频率稳定性,以及消息到达链路有没有异常抖动。ROS/ROS2里可以用message_filters做近似时间同步,但根本上还是建议硬件PPS同步,或者至少保证两个传感器的主机时钟经过PTP/NTP校准。

另一个坑是lidar退化场景。手眼标定依赖lidar帧间配准,如果你的数据采集发生在长走廊、空旷停车场这类几何退化环境里,lidar配准本身的误差就有几厘米和零点几度,外参标定结果会被直接污染。经验是采集时尽量选有丰富几何特征的场景,比如货架、树木、建筑转角。我在矿山场景里给雷达和IMU做标定时就吃过这个亏——矿山巷道有大量重复纹理和长直墙,配准退化严重,后来换到有破碎岩壁和支护结构的区域才稳定。

5.3 相机-IMU外参的连带提醒

相机和IMU的外参标定,主流工具是Kalibr,或者一些基于手眼标定的开源包。这里有个特别容易犯的连环错:相机内参没标好就一起联合优化。标定板拍摄、畸变系数求解(张正友法这类)、相机内参标定,应该在进入相机-IMU联合标定之前独立完成,并且评估好重投影误差。否则,内参、外参、IMU误差项在同一个非线性优化里会互相补偿,最后每个参数都偏离真实值,但整体残差看起来还挺漂亮。这就是典型的"过拟合式自欺欺人",换一组数据立刻现原形。

6. 采样率、温度与最终验证:标定成果落地的最后一公里

6.1 无人机IMU采样率达不到200Hz,到底伤在哪

热词里有一条问"无人机imu采样率达不到200hz会造成什么影响",这其实问到了融合系统设计的一个核心参数。以10Hz的lidar为例,两帧点云之间是100ms。IMU如果200Hz,间隔5ms,一帧lidar之间要积分200步;如果只有100Hz,积分100步;如果只有50Hz,积分50步。

问题不只是积分步数变少,更是时间分辨率和混叠。IMU积分是数值积分,姿态角速度在积分间隔内的变化被近似为恒定值,采样率越低,这个近似误差越大。更本质的麻烦是:旋翼无人机的机架振动通常在50到300Hz之间,如果IMU采样率只有50Hz,这些振动会被混叠到低频,变成一个缓慢晃动的虚假角速度,滤波器看到的就是"机身自己在慢慢晃",而滤波器又无法分辨这是振动混叠还是真实运动,结果就是轨迹上叠加规律的、无法消除的波动。

工程上有句话叫"200Hz是实战型IMU采样率的底线",倒不是说公式上200Hz有什么魔法,而是对典型无人机机动带宽(一般十几Hz以下)和机架振动频率(大几十到几百Hz)来说,200Hz采样配合合适的抗混叠滤波,能把混叠影响压到可以接受的水平。如果你的IMU只有100Hz,可以考虑在模拟前端加低通滤波来压振动,但响应延迟又会牺牲控制带宽,两难。所以选型阶段让采样率尽量不低于200Hz,比事后用算法补救省心太多。ROS/ROS2里做IMU数据采集时,记得检查话题实际发布频率和时间戳间隔,很多时候代码里配了200Hz,跑起来因为线程调度或者USB传输问题实际只有120Hz,这类问题靠肉眼是看不出来的。

6.2 标定结果怎么验证,才算真正的"标定成功"

标定完千万别看仪表盘数字就收工。我自己的验证习惯分三步:

第一步,静置验证。标定后的IMU固定放置5分钟,用标定参数补偿加速度计和陀螺仪输出后,积分的速度和姿态漂移应该很小。理想情况下水平方向速度漂移不超过每秒几个cm/s的累积,姿态角漂移不超过零点几度/分钟。如果积分速度按秒级持续增长,说明零偏或比例因子还有残差。

第二步,已知角度旋转验证。把IMU放在有角度读数的转台或者云台上,绕某轴旋转90°、180°,回到原位,比较陀螺仪积分姿态和真实姿态之差。这个测试能暴露出单纯静置发现不了的比例因子误差和非正交误差。

第三步,融合系统端到端验证。把标定后的IMU接入你的LIO/VIO算法,跑同一段数据,对比标定前后的里程计残差、回环误差。如果标定有效,优化后的残差和轨迹漂移应有明显下降。我见过一个项目标定前后残差从1.2%下降到0.5%,效果肉眼可见。

6.3 温度是最后一条隐藏尾巴

几乎所有MEMS IMU都有温度相关零偏漂移。常温下标定好的参数,到了冬天室外,零偏可能偏移一个可观量级。如果你的产品使用温度范围比较宽,标准的"一次标定走天下"是站不住脚的。工程做法是温箱分段标定:温箱里从-40℃到85℃跑若干个温度点,每个温度点重复静态零偏采集,拟合出零偏随温度的曲线,在软件里做温度补偿。没有温箱的话,至少也要记录标定时的环境温度,并且明确标定参数只适用于相近温度范围。我在实际项目里被这个坑坑过不止一次:夏天标定完的参数,冬天飞无人机,起飞后一分钟就出现明显的偏航漂移,后来一查就是陀螺零偏随温度变了。

另外,工业现场如果IMU带CAN接口,用CANape这类标定工具批量下载标定参数到设备里,是成熟量产流程的标配。不过工具只是辅助,模型正确性才是根本。

最后分享一个我做标定踩过几次坑之后养成的习惯:任何一次标定实验,我都会把传感器上电时间、环境温度、夹具编号、采集数据时长一起记录下来,贴在实验记录本上。因为MEMS的标定参数本质上是"某颗料在某个温度、某个安装条件下的快照",没有这些上下文,三个月后你会看着一堆标定系数完全想不起来它是在什么条件下测出来的,还得重新返工。这个习惯帮我省了不知道多少重复劳动,也希望你们用得上。

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

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

立即咨询