2、传感器建模:加速度计与陀螺仪的数学模型、Allan方差分析基础、随机游走与偏置不稳定性

好,咱们进入正题。传感器建模这事儿,说白了就是给加速度计和陀螺仪画个「像」——你得知道它怎么工作,它有哪些臭毛病,然后才能想办法治它。我当年刚入行时,总觉得建模是理论派干的事,直到有一次做无人机飞控,零漂把姿态算偏了十几度,飞机差点炸了……嗯,从那以后我再也不敢跳过建模这一步了。

2.1 加速度计的数学模型

加速度计测的是什么?不是速度,是比力。这个比力包括运动加速度和重力加速度。理想情况下,它的输出很简单:

a_meas = a_true + g + b_a + n_a

其中:

  • a_true —— 真实的运动加速度
  • g —— 重力加速度(9.8 m/s²)
  • b_a —— 偏置(零偏),单位 m/s²
  • n_a —— 测量噪声,通常建模为高斯白噪声

你想想看,如果偏置 b_a 是 0.01 m/s²,积分 100 秒后速度误差就是 1 m/s,位置误差更是平方增长。这就是为什么零漂抑制这么重要。

实际模型更复杂一些:

a_meas = S * (a_true + g) + b_a + n_a + 非线性项 + 温度漂移

其中 S 是尺度因子矩阵,包含交叉耦合。不过咱们做零漂抑制时,重点盯着 b_a 和 n_a 就行。

2.2 陀螺仪的数学模型

陀螺仪测的是角速度。模型和加速度计很像:

ω_meas = ω_true + b_g + n_g
  • ω_true —— 真实角速度
  • b_g —— 陀螺偏置,单位 °/s 或 rad/s
  • n_g —— 角度随机游走噪声

我个人习惯把陀螺仪偏置看作「慢性毒药」。加速度计偏置影响位置,但陀螺仪偏置影响姿态,姿态一错,整个导航就全完了。我在做车载导航时遇到过,陀螺偏置只漂了 0.1°/s,10 分钟后航向偏了 60 度,车直接导航到对面车道去了……

避坑指南: 我曾经以为 MEMS 陀螺仪静态时偏置是常数,后来发现温度一变,偏置能跳一个数量级。所以建模时一定要把温度补偿考虑进去。

2.3 Allan方差分析基础

Allan 方差是什么?说白了就是一把「尺子」,用来量传感器的噪声成分。它能把白噪声、随机游走、偏置不稳定性这些成分一一拆开。

计算步骤很简单:

  1. 采集一段静态数据(比如 2 小时,100 Hz)
  2. 按不同时间长度 τ 分段
  3. 计算每段的均值,再求方差
  4. 画出 log(τ) - log(Allan 标准差) 曲线

这条曲线长什么样?我画个图给你看:

Allan 方差曲线(典型 MEMS 陀螺仪) 相关时间 τ (s) 10⁰ 10¹ 10² 10³ Allan 标准差 (°/s) 角度随机游走 (斜率 -1/2) 偏置不稳定性 (平坦区) 速率随机游走 (斜率 +1/2) τ₁ τ₂

这张图怎么看?我教你个口诀:

  • 左段斜率 -1/2 —— 角度随机游走(白噪声积分的结果)
  • 中间平坦区 —— 偏置不稳定性(这是零漂抑制的重点!)
  • 右段斜率 +1/2 —— 速率随机游走(低频噪声)

实战要点: 平坦区的最低点对应的 τ 值,就是传感器的最佳积分时间。比如 τ = 100 s 时 Allan 方差最小,说明积分 100 秒时噪声最低。我一般用这个值来设计滤波器的截止频率。

2.4 随机游走与偏置不稳定性

这两个概念容易搞混,我分开讲。

角度随机游走(ARW): 陀螺仪白噪声积分后,角度误差会像醉汉走路一样随机漂移。单位是 °/√h。数值越小越好,比如 0.01 °/√h 算高端 MEMS 了。

偏置不稳定性(BI): 这是偏置在长时间尺度上的缓慢波动。单位是 °/h。我见过一些低端传感器,BI 能到 10 °/h,静止 1 小时偏置漂了 10 度,这还怎么用?

为什么会有这些噪声?说白了就是物理限制:

  • 热噪声 → 白噪声
  • 1/f 噪声 → 偏置不稳定性
  • 温度梯度 → 速率随机游走

注意: 很多人以为 Allan 方差分析一次就够了。我踩过这个坑——同一颗芯片,不同温度下的 Allan 曲线完全不一样。建议至少做 3 组温度点(低温、常温、高温)的测试。

2.5 实战:用 Python 做 Allan 方差分析

光说不练假把式。我给你一段代码,可以直接跑:

import numpy as np
import matplotlib.pyplot as plt

def allan_variance(data, fs):
    """
    计算 Allan 方差
    data: 传感器静态数据 (1D array)
    fs: 采样率 (Hz)
    """
    n = len(data)
    max_m = int(np.log2(n)) - 1
    tau = []
    adev = []
    
    for m in range(1, max_m):
        # 按 2^m 个点分组
        cluster_size = 2**m
        num_clusters = n // cluster_size
        
        # 计算每组的均值
        clusters = data[:num_clusters * cluster_size].reshape(-1, cluster_size)
        means = np.mean(clusters, axis=1)
        
        # Allan 方差
        allan_var = 0.5 * np.mean((means[1:] - means[:-1])**2)
        allan_std = np.sqrt(allan_var)
        
        tau.append(cluster_size / fs)
        adev.append(allan_std)
    
    return np.array(tau), np.array(adev)

# 模拟陀螺仪数据(含白噪声 + 偏置不稳定性)
fs = 100  # 100 Hz
t = np.arange(0, 7200, 1/fs)  # 2 小时
white_noise = np.random.normal(0, 0.01, len(t))  # 白噪声
bias_drift = np.cumsum(np.random.normal(0, 1e-6, len(t)))  # 偏置漂移
data = white_noise + bias_drift

# 计算 Allan 方差
tau, adev = allan_variance(data, fs)

# 画图
plt.figure(figsize=(10, 6))
plt.loglog(tau, adev, 'b-', linewidth=2)
plt.xlabel('τ (s)')
plt.ylabel('Allan 标准差 (°/s)')
plt.grid(True, which='both', alpha=0.3)
plt.title('Allan 方差分析结果')
plt.show()

我的经验: 实际数据采集时,记得先让传感器预热 10 分钟。我试过冷启动直接采,前 20 分钟的数据全是温度漂移,Allan 曲线根本没法看。

2.6 小结:建模的意义

传感器建模不是纸上谈兵。它告诉你三件事:

  1. 偏置有多大 —— 决定要不要做零漂抑制
  2. 噪声结构什么样 —— 决定用什么滤波器
  3. 最佳积分时间 —— 决定系统更新频率

我见过太多人上来就调滤波器参数,调了半天效果不好。其实根源在于没搞清楚传感器本身的噪声特性。先做 Allan 方差分析,再建模,最后设计滤波器——这个顺序不能乱。

嗯,这一章就到这里。建模是基础,下一章咱们聊怎么用这些模型来设计零漂抑制算法。


公众号:蓝海资料掘金营,微信deep3321