3、六面校准原理:为什么要六面?

好,咱们直接切入正题。

很多刚接触MEMS加速度计的朋友都会问一个问题:「校准就校准,为什么要折腾六个面?」

我当年第一次做IMU标定时也这么想。后来在产线上吃过亏,才明白这六个面背后藏着大学问。

3.1 地球重力——我们唯一的「尺子」

说白了,加速度计校准的核心,就是找一个绝对参考。在实验室里,最靠谱的参考就是地球重力。

地球重力是个好东西:

  • 方向固定——始终指向地心
  • 大小已知——约9.8 m/s²(具体值跟纬度有关,但校准时可查表修正)
  • 无处不在——不用额外设备,省成本

但问题来了:重力只有一个方向。而加速度计有三个轴(X、Y、Z)。

你想想看,如果我只把加速度计平放在桌面上,只能得到Z轴对重力的响应。X轴和Y轴呢?它们完全「躺平」,测不到重力分量。

这就是为什么需要六面——让每个轴都「尝一尝」重力的味道

核心思想:通过翻转加速度计,让每个轴分别指向重力方向和反重力方向,从而获得6个独立的测量方程。这6个方程,就是解出12个误差参数的「钥匙」。

3.2 六面校准的数学模型——12参数模型

好,咱们上点硬货。

一个真实的加速度计,输出值跟真实值之间,存在三种误差:

  1. 零偏(Bias)——静止时输出不为0
  2. 比例因子(Scale Factor)——灵敏度不准
  3. 轴间耦合(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个参数?

我推荐用最小二乘法。具体步骤:

  1. 将12个参数排列成一个列向量:θ = [Kxx, Kxy, Kxz, Kyx, Kyy, Kyz, Kzx, Kzy, Kzz, Bx, By, Bz]ᵀ
  2. 根据每个姿态的真实加速度和原始测量值,构建误差方程
  3. 用最小二乘法求解:θ = (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流程图

下面这张图,是我自己总结的六面校准核心逻辑。你看一遍就能记住整个流程:

六面校准核心逻辑 步骤1:六面数据采集 6个姿态 × 3轴原始输出 步骤2:构建观测方程 18个方程,12个未知数 步骤3:最小二乘 求解12参数 步骤4:输出12参数 K矩阵(9个) + B向量(3个) 误差来源 零偏 · 比例因子 · 轴间耦合 验证:用校准参数修正后,各轴输出应为±g

3.7 实际应用中的注意事项

最后,分享几个我在产线上积累的经验:

  • 放置精度很重要——六面校准假设每个面都严格水平或垂直。实际中很难做到绝对精准,但尽量控制在±1°以内。我见过有人用手扶着传感器做校准,结果误差大得离谱。
  • 温度影响不可忽视——加速度计的零偏和比例因子都会随温度变化。如果校准环境温度跟实际使用环境差太多,校准效果会打折扣。我一般会在恒温箱里做校准,或者至少记录环境温度。
  • 重复性验证——校准完成后,随便选一个面重复测几次。如果修正后的输出波动超过±0.01g,说明校准质量有问题,需要排查。

一句话总结:六面校准就是用地球重力这把「尺子」,通过6个姿态的测量,解出加速度计的12个误差参数。少一面,参数就解不全;多一面,纯属浪费。六面,刚刚好。

专注资料整理