第3章:随机误差建模——Allan方差分析法

各位同学,欢迎来到随机误差建模这一章。

说实话,IMU的误差分两类:一类是确定性误差,比如零偏、尺度因子,这些我们能用标定手段干掉;另一类是随机误差,说白了就是噪声——它没有固定规律,但又有统计特征。今天我们要聊的Allan方差分析法,就是用来“解剖”这些随机噪声的利器。

3.1 为什么需要Allan方差?

我在做低成本MEMS IMU项目时,遇到过一个问题:陀螺仪的输出数据看起来“挺干净”,但积分后姿态漂移得厉害。后来才发现,噪声的“颜色”不一样,光看时域波形根本看不出来。

Allan方差最早是用于原子钟频率稳定度分析的,后来被引入IMU领域。它的核心思想很简单:通过不同时间尺度上的方差变化,来识别噪声的类型和强度

核心价值:Allan方差能帮我们从一堆随机数据中,分离出5种典型噪声成分——量化噪声、角度随机游走、零偏不稳定性、速率随机游走、速率斜坡。

3.2 Allan方差分析法的步骤

嗯,这里我直接说步骤,你跟着做就行。我在项目里至少跑了上百次Allan方差分析,流程早就烂熟于心了。

  1. 采集静态数据:IMU静止放置,采样率固定(比如100Hz),采集时长至少2小时。我建议至少4小时,数据越长,低频段分析越准。
  2. 计算角增量/速度增量:对于陀螺仪,计算每个采样间隔内的角增量;对于加速度计,计算速度增量。
  3. 分组平均:将数据按不同时间长度τ分组,每组内取平均。τ从最小采样间隔开始,逐步增大。
  4. 计算方差:对每个τ,计算相邻两组平均值的差值的方差,再除以2。
  5. 绘制双对数曲线:横轴为τ(对数坐标),纵轴为Allan方差σ²(τ)(对数坐标)。

你想想看,这个过程其实就是在问:如果我把数据按不同时长做平均,噪声的波动程度会怎么变化?

3.3 Allan方差曲线解读

曲线画出来后,怎么读?我刚开始看的时候也是一头雾水,后来总结了一个口诀:看斜率,辨噪声

下面这张SVG图,是我自己画的Allan方差典型曲线,包含了5种噪声成分的斜率特征:

Allan方差典型曲线(双对数坐标) 相关时间 τ (log) Allan方差 σ²(τ) (log) 10⁻² 10⁻¹ 10⁰ 10¹ 10² 量化噪声 (斜率 -1) 角度随机游走 (斜率 -1/2) 零偏不稳定性 (斜率 0) 速率随机游走 (斜率 +1/2) 速率斜坡 (斜率 +1) 量化噪声 角度随机游走 零偏不稳定性 速率随机游走 速率斜坡

这张图怎么看?我带你走一遍:

  • 量化噪声:斜率 -1,出现在短时间尺度(τ很小)。说白了就是ADC量化带来的误差,低成本IMU里比较明显。
  • 角度随机游走:斜率 -1/2,这是最常见的噪声成分。我在做行人导航时,这个参数直接决定了零速修正的频率。
  • 零偏不稳定性:斜率 0,曲线的最低点。这个值就是IMU的“零偏稳定性”,是选型时最关键的指标之一。
  • 速率随机游走:斜率 +1/2,出现在长时间尺度。说明零偏在缓慢漂移,温度变化或老化效应会导致这个。
  • 速率斜坡:斜率 +1,这是确定性趋势项,不是随机噪声。如果出现这个,说明你的数据里有线性趋势,需要先做去趋势处理。

我的经验:实际IMU的Allan曲线往往是这5种噪声的叠加。你看到的曲线可能只有2-3个明显的斜率段,这很正常。别硬套5段,能识别出主要成分就够了。

3.4 基于Allan方差的噪声参数提取

曲线看懂了,接下来就是提取参数。说白了,就是从曲线上读出每个噪声成分的系数。

我常用的方法是:最小二乘拟合。在双对数坐标下,对每个斜率段做线性拟合,然后反算出噪声系数。

下面给出一段Python代码,这是我项目里一直在用的,你直接拿去用:

import numpy as np
import matplotlib.pyplot as plt

def allan_variance(data, fs):
    """
    计算Allan方差
    data: 原始数据(角增量或速度增量)
    fs: 采样率 (Hz)
    """
    N = len(data)
    max_m = int(np.log2(N)) - 1
    tau = np.zeros(max_m)
    allan_var = np.zeros(max_m)
    
    for m in range(1, max_m + 1):
        # 分组平均
        n = 2**m
        tau[m-1] = n / fs
        
        # 计算相邻组差值的方差
        num_groups = N // n
        if num_groups < 2:
            break
        
        # 取每个组的平均值
        groups = data[:num_groups * n].reshape(num_groups, n)
        means = np.mean(groups, axis=1)
        
        # 计算Allan方差
        diff = means[1:] - means[:-1]
        allan_var[m-1] = 0.5 * np.mean(diff**2)
    
    return tau, allan_var

# 使用示例
fs = 100.0  # 100Hz采样
# 假设gyro_data是你的陀螺仪数据(单位:rad/s)
# tau, avar = allan_variance(gyro_data, fs)

# 绘制双对数曲线
# plt.loglog(tau, np.sqrt(avar))
# plt.xlabel('τ (s)')
# plt.ylabel('Allan Deviation (rad/s)')
# plt.grid(True, which='both', ls='--')
# plt.show()

注意:数据长度直接影响低频段的可靠性。我吃过亏——有一次只采集了30分钟数据,结果速率随机游走那段曲线完全是假的。后来我养成了习惯:至少采集2小时,最好4小时以上。

3.5 参数提取的具体方法

从Allan曲线上提取噪声参数,我总结了下面这张表,你直接对照着用:

噪声类型 斜率 提取方法 单位
量化噪声 -1 在τ=√3处读取σ值,Q = σ / √3 rad 或 m/s
角度随机游走 -1/2 在τ=1处读取σ值,ARW = σ °/√h 或 m/s/√h
零偏不稳定性 0 读取曲线最低点的σ值 °/h 或 m/s²
速率随机游走 +1/2 在τ=3处读取σ值,RRW = σ / √3 °/h/√h 或 m/s²/√h
速率斜坡 +1 在τ=√2处读取σ值,斜率系数 = σ / (τ/√2) °/h² 或 m/s²/h

嗯,这里要特别说一下角度随机游走(ARW)。这个参数在导航里太重要了——它决定了你的姿态在无修正情况下能保持多久。我做过一个无人机项目,ARW是0.5°/√h的IMU,纯惯性飞行30秒后姿态误差就超过5度了。

3.6 避坑指南

最后,分享几个我踩过的坑:

  • 数据预处理不能省:先去掉明显的异常值(比如IMU刚上电时的数据),再做去趋势处理。我曾经因为没去趋势,把速率斜坡当成了随机噪声,结果参数全错了。
  • 采样率要匹配:低成本IMU的采样率通常不高(100-200Hz),这时候量化噪声段可能只有几个点,别强行拟合。
  • 温度影响:Allan方差分析要在恒温环境下做。我试过在空调时开时关的房间里采集数据,结果零偏不稳定性那段曲线抖得跟心电图似的。
  • 多次测量取平均:单次Allan曲线有随机性,我建议至少做3次,取平均曲线再提取参数。

总结一下:Allan方差分析法,说白了就是给IMU的随机噪声“拍X光片”。通过一张双对数曲线图,你就能看清5种噪声的分布情况,然后提取出关键参数。这些参数会直接用在后面的卡尔曼滤波器设计里——比如设置过程噪声协方差矩阵Q。

好了,这一章的内容就到这里。记住,Allan方差分析不是一次性工作——随着IMU老化或温度变化,噪声参数会变。我建议每半年重新做一次分析,更新滤波器参数。


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