3、六面校准原理:为什么要六面?
好,咱们直接切入正题。
很多刚接触MEMS加速度计的朋友都会问一个问题:「校准就校准,为什么要折腾六个面?」
我当年第一次做IMU标定时也这么想。后来在产线上吃过亏,才明白这六个面背后藏着大学问。
3.1 地球重力——我们唯一的「尺子」
说白了,加速度计校准的核心,就是找一个绝对参考。在实验室里,最靠谱的参考就是地球重力。
地球重力是个好东西:
- 方向固定——始终指向地心
- 大小已知——约9.8 m/s²(具体值跟纬度有关,但校准时可查表修正)
- 无处不在——不用额外设备,省成本
但问题来了:重力只有一个方向。而加速度计有三个轴(X、Y、Z)。
你想想看,如果我只把加速度计平放在桌面上,只能得到Z轴对重力的响应。X轴和Y轴呢?它们完全「躺平」,测不到重力分量。
这就是为什么需要六面——让每个轴都「尝一尝」重力的味道。
核心思想:通过翻转加速度计,让每个轴分别指向重力方向和反重力方向,从而获得6个独立的测量方程。这6个方程,就是解出12个误差参数的「钥匙」。
3.2 六面校准的数学模型——12参数模型
好,咱们上点硬货。
一个真实的加速度计,输出值跟真实值之间,存在三种误差:
- 零偏(Bias)——静止时输出不为0
- 比例因子(Scale Factor)——灵敏度不准
- 轴间耦合(Cross-axis)——三个轴没完全正交
这三种误差,一共对应12个参数。我习惯把它们写成矩阵形式:
真实加速度 = K * (测量值 - B)
其中:
K = [Kxx Kxy Kxz] —— 3x3 比例因子+耦合矩阵
[Kyx Kyy Kyz]
[Kzx Kzy Kzz]
B = [Bx, By, Bz]ᵀ —— 3x1 零偏向量
展开写就是:
Ax_true = Kxx*(Ax_raw - Bx) + Kxy*(Ay_raw - By) + Kxz*(Az_raw - Bz)
Ay_true = Kyx*(Ax_raw - Bx) + Kyy*(Ay_raw - By) + Kyz*(Az_raw - Bz)
Az_true = Kzx*(Ax_raw - Bx) + Kzy*(Ay_raw - By) + Kzz*(Az_raw - Bz)
嗯,看着有点复杂。但别怕,咱们有六面校准这个大杀器。
3.3 六面校准的「六步走」
我个人习惯把六面校准分成六个姿态,每个姿态对应一个测量方程:
| 姿态编号 | 放置方式 | 真实加速度 (Ax, Ay, Az) | 说明 |
|---|---|---|---|
| 1 | Z轴向上 | (0, 0, +g) | 平放,正面朝上 |
| 2 | Z轴向下 | (0, 0, -g) | 平放,反面朝上 |
| 3 | X轴向上 | (+g, 0, 0) | 侧立,X轴指天 |
| 4 | X轴向下 | (-g, 0, 0) | 侧立,X轴指地 |
| 5 | Y轴向上 | (0, +g, 0) | 侧立,Y轴指天 |
| 6 | Y轴向下 | (0, -g, 0) | 侧立,Y轴指地 |
每个姿态下,我们记录加速度计三个轴的原始输出。6个姿态,一共得到18个测量值(6姿态 × 3轴)。
小技巧:每个姿态最好多采几秒数据取平均。我一般每个面采10秒,去掉头尾各1秒,中间8秒取均值。这样能有效抑制噪声。
3.4 从6个方程解12个参数——够用吗?
你可能会问:6个姿态,每个姿态提供3个方程,一共18个方程。但未知数只有12个。理论上超定,能解。
但这里有个坑——方程之间不是完全独立的。
举个例子:姿态1(Z轴向上)和姿态2(Z轴向下)提供的方程,本质上是对称的。它们能很好地约束Z轴的零偏和比例因子,但对X-Y平面的耦合信息贡献有限。
所以,六面校准虽然用了6个面,但真正独立的约束条件,刚好够解出12个参数。少一面都不行。
注意:如果你只做5面或4面,某些参数会「欠约束」,解出来的结果可能看起来合理,但实际用起来误差很大。我曾经在快速验证时偷懒只做了4面,结果后续融合算法全偏了,排查了两天才找到原因。
3.5 求解方法——最小二乘法
有了18个方程,怎么解12个参数?
我推荐用最小二乘法。具体步骤:
- 将12个参数排列成一个列向量:θ = [Kxx, Kxy, Kxz, Kyx, Kyy, Kyz, Kzx, Kzy, Kzz, Bx, By, Bz]ᵀ
- 根据每个姿态的真实加速度和原始测量值,构建误差方程
- 用最小二乘法求解:θ = (HᵀH)⁻¹Hᵀz
代码实现(Python伪码):
import numpy as np
# 假设已经采集了6个面的数据
# raw_data: 6x3 矩阵,每行是 (Ax_raw, Ay_raw, Az_raw)
# true_data: 6x3 矩阵,每行是 (Ax_true, Ay_true, Az_true)
def calibrate_6face(raw_data, true_data):
# 构建观测矩阵 H 和观测向量 z
# 这里省略具体构建过程,核心是线性化
H = build_H_matrix(raw_data)
z = build_z_vector(true_data)
# 最小二乘求解
theta = np.linalg.inv(H.T @ H) @ H.T @ z
# 从theta中提取K和B
K = theta[0:9].reshape(3, 3)
B = theta[9:12]
return K, B
避坑指南:我曾经直接用原始数据做最小二乘,结果K矩阵对角线元素接近1,但非对角线元素大得离谱。后来发现是数据没做归一化。建议先把原始数据减去均值,再除以标准差,数值稳定性会好很多。
3.6 六面校准的SVG流程图
下面这张图,是我自己总结的六面校准核心逻辑。你看一遍就能记住整个流程:
3.7 实际应用中的注意事项
最后,分享几个我在产线上积累的经验:
- 放置精度很重要——六面校准假设每个面都严格水平或垂直。实际中很难做到绝对精准,但尽量控制在±1°以内。我见过有人用手扶着传感器做校准,结果误差大得离谱。
- 温度影响不可忽视——加速度计的零偏和比例因子都会随温度变化。如果校准环境温度跟实际使用环境差太多,校准效果会打折扣。我一般会在恒温箱里做校准,或者至少记录环境温度。
- 重复性验证——校准完成后,随便选一个面重复测几次。如果修正后的输出波动超过±0.01g,说明校准质量有问题,需要排查。
一句话总结:六面校准就是用地球重力这把「尺子」,通过6个姿态的测量,解出加速度计的12个误差参数。少一面,参数就解不全;多一面,纯属浪费。六面,刚刚好。