3、加速度计标定:六面法标定流程,零偏与尺度因子计算,标定结果验证

加速度计标定,说白了就是让传感器学会说“人话”。

你想想看,一个裸的加速度计,它输出的原始值跟真实的重力加速度之间,差着零偏、尺度因子,还有安装误差。如果不标定,你算出来的姿态角全是歪的。我刚开始做飞控那会儿,就吃过这个亏——飞机悬停时总往一边飘,查了半天,最后发现是加速度计零偏没校准。

嗯,今天我们就来聊聊最经典的标定方法:六面法。

核心思路:利用重力加速度作为已知参考,把加速度计的六个面(±X、±Y、±Z)分别对准重力方向,采集数据,然后反算出零偏和尺度因子。

六面法加速度计标定流程 六面法加速度计标定流程 1. 传感器预热 & 水平台 2. 六面静态数据采集 3. 零偏 & 尺度因子计算 4. 标定结果验证 5. 残差过大?重新采集 ⚠️ 关键前提 水平台精度 < 0.1° 传感器充分预热(5分钟) 每面采集至少 200 个样本

3.1 六面法标定流程

六面法这个名字听起来挺唬人,其实操作很简单。你需要一个水平台,或者至少一个你知道绝对水平的平面。我个人习惯用大理石平台,精度够。

具体步骤:

  1. 预热:上电后等 5 分钟,让传感器温度稳定。我见过有人冷启动直接标定,结果温度一变化,零偏全漂了。
  2. 水平校准:把 IMU 放在水平台上,记录 Z 轴向上时的数据。这就是第一个面。
  3. 翻转:依次将 IMU 的 +X、-X、+Y、-Y、-Z 面朝上,每个面保持静止,采集 200~500 个样本。
  4. 取均值:每个面的数据取平均,得到 6 个平均加速度值:A_x+, A_x-, A_y+, A_y-, A_z+, A_z-。

我的小技巧:每个面采集时,别急着开始。等数据稳定了再录,大概等 2~3 秒。我曾经用抖动的手拿着 IMU 翻转,结果数据里全是高频噪声,算出来的尺度因子偏差了 2%。

3.2 零偏与尺度因子计算

好,数据到手了。现在我们来算零偏和尺度因子。

先明确一下模型。对于每个轴,加速度计的输出可以写成:

A_meas = S * A_true + B

其中:

  • A_meas 是测量值(原始 ADC 读数或电压)
  • A_true 是真实加速度(单位 g)
  • S 是尺度因子(单位:LSB/g 或 V/g)
  • B 是零偏(单位:LSB 或 V)

对于六面法,我们利用重力加速度 g 作为已知参考。当某个轴朝上时,该轴的真实加速度为 +1g;朝下时为 -1g。其他两个轴理论上为 0g。

以 Z 轴为例:

  • Z 轴朝上:A_z+ = S_z * (+1) + B_z
  • Z 轴朝下:A_z- = S_z * (-1) + B_z

解这个二元一次方程组:

S_z = (A_z+ - A_z-) / 2
B_z = (A_z+ + A_z-) / 2

同理,X 轴和 Y 轴也一样。就这么简单。

注意:这里假设了安装误差已经很小,或者我们暂时忽略交叉轴耦合。如果要求更高精度,需要引入 12 参数或 9 参数模型,但六面法只解决零偏和尺度因子。

下面是一个完整的 Python 计算示例:

import numpy as np

# 假设采集到的六面均值数据(单位:LSB)
data = {
    'x+': 16450, 'x-': 15830,
    'y+': 16520, 'y-': 15790,
    'z+': 16980, 'z-': 15260
}

# 计算零偏和尺度因子
S_x = (data['x+'] - data['x-']) / 2
B_x = (data['x+'] + data['x-']) / 2

S_y = (data['y+'] - data['y-']) / 2
B_y = (data['y+'] + data['y-']) / 2

S_z = (data['z+'] - data['z-']) / 2
B_z = (data['z+'] + data['z-']) / 2

print(f"X: S={S_x:.2f}, B={B_x:.2f}")
print(f"Y: S={S_y:.2f}, B={B_y:.2f}")
print(f"Z: S={S_z:.2f}, B={B_z:.2f}")

输出结果:

X: S=310.00, B=16140.00
Y: S=365.00, B=16155.00
Z: S=860.00, B=16120.00

你看,Z 轴的尺度因子明显比 X/Y 大,这是因为 Z 轴量程通常不同。零偏都在 16100 左右,说明传感器一致性还不错。

3.3 标定结果验证

算完了,别急着收工。验证这一步,我建议你认真做。

验证方法:

  1. 回代检查:用标定后的参数重新计算每个面的加速度,看是否接近 ±1g 和 0g。
  2. 模长检查:在任意姿态下,加速度计输出的模长应该接近 1g。如果偏差超过 0.02g,说明标定有问题。
  3. 静态倾角检查:把 IMU 放在已知角度的斜面上,对比计算出的倾角与实际角度。

我一般会用模长检查作为快速验证。具体做法:

# 标定后的数据
def calibrate(raw_x, raw_y, raw_z):
    x_cal = (raw_x - B_x) / S_x
    y_cal = (raw_y - B_y) / S_y
    z_cal = (raw_z - B_z) / S_z
    return np.array([x_cal, y_cal, z_cal])

# 随机取一组静态数据
raw = np.array([16150, 16180, 16900])
cal = calibrate(*raw)
norm = np.linalg.norm(cal)
print(f"标定后模长: {norm:.4f} g")  # 期望接近 1.0000

避坑指南:我曾经遇到过一次,模长检查总是 1.02g,怎么都降不下来。后来发现是水平台本身有 0.5° 的倾斜。记住,你的参考基准必须比传感器精度高一个数量级。

如果验证不通过,别急着改参数。先检查数据采集过程:

  • 每个面是否真的静止了?
  • 翻转时有没有引入冲击?
  • 温度是否稳定?

嗯,六面法虽然简单,但做好也不容易。我个人习惯在每次飞控上电后,先跑一遍快速标定(只做零偏),每周做一次完整六面法。这样既能保证精度,又不会太耗时。

最后,给你一个参考表格,对比不同标定方法的适用场景:

方法 标定参数 所需设备 精度 耗时
六面法 零偏 + 尺度因子 水平台 中等(0.5% 以内) 10 分钟
多位置法 零偏 + 尺度 + 安装误差 转台 高(0.1% 以内) 30 分钟
椭球拟合法 零偏 + 尺度 + 交叉轴 任意旋转 中等(受运动影响) 5 分钟

对于大多数飞控应用,六面法已经足够。如果你做的是高精度导航,那得上转台。但那是另一节课的内容了。