简介:一款基于交叠式Allan方差(Overlapped Allan Variance)的陀螺仪数据处理MATLAB例程,面向嵌入式、航空航天、机器人等需要评估惯性传感器稳定性的开发与研究人员,解决传感器随机漂移和噪声特性的量化分析问题。资源体积仅1KB,总计1个m脚本文件,代码结构简洁,属于开箱即用的轻量级实现,在MATLAB环境中无需额外依赖即可运行。脚本按经典OAVAR流程组织:对原始数据按采样间隔分段、采用重叠窗口提升样本利用率,再通过均值序列、相邻平均值差异平方和累加平均得到各时间尺度下的Allan方差,并自动绘制对数坐标图,直观呈现角度随机游走、零偏不稳定性和速率随机游走等关键噪声系数,为后续噪声辨识与误差补偿提供直观依据。已有222人学习这一例程;读者将其与自定义陀螺仪数据结合实践,既能快速掌握交叠式Allan方差的计算逻辑,也能为传感器选型或算法验证提供实用参考基准。
1. 陀螺仪数据里藏着噪声底,交叠式Allan方差把它摊开来看
做惯IMU惯性测量单元的人都有体验:拿一颗陀螺仪静止放在桌上,采集上电后的角速度输出,看到的是一条毛刺很多的曲线,零偏在抖动,随机游走更是看不见。你要是直接看时域波形,或者算个标准差,根本分不清是白噪、闪烁噪声还是随机游走。要看清传感器长期稳定性,业界标准做法是画Allan方差曲线。gyro_olavar_t.zip里的gyro_olavar_t.m就是干这个的——用交叠式Allan方差(Overlapped Allan Variance, OAVAR)把陀螺仪的噪声分量按积分时间拆开,让你一眼看出哪些误差源主导,哪些靠滤波能压掉。适合做惯性导航、机器人姿态估计、光电稳像、以及任何需要评估陀螺仪性能的活。
2. Allan方差与交叠式Allan方差:时域二阶统计为什么比标准差更有说服力
2.1 标准差为什么无法描述传感器的"长期漂移"
标准差假定数据是独立同分布的,可陀螺仪的噪声序列有很强的时序相关性。零偏不稳定性、角度随机游走、速率斜坡,这些误差源在不同积分时间下呈现不同特性。你算一个全局标准差,等于把这些特性混在一起取了个均值。更麻烦的是,标准差随样本数量增加并不会收敛到一个稳定值——陀螺仪静止放出两分钟和放出两小时,标准差能差好几倍。因为低频漂移在长时间尺度上持续累积,标准差无法区分"短时抖动"和"缓慢漂移"。
Allan方差则把时间序列按不同块长重新统计。它先对原始测量做积分,得到角增量或相位累积,然后考察相邻两个块的平均值之差。这个差值对块长敏感:块长很短时主要反映高频噪声,块长拉长时低频噪声逐渐显现。把不同块长对应的方差画成对数-对数曲线,各类噪声就分布在不同斜率的区域里。
2.2 从普通Allan方差到交叠式Allan方差
普通Allan方差的做法是将数据切成互不重叠的块,对每块求平均,再计算相邻块平均值的差异平方。问题在于块长较长时,互不重叠的块数少,统计样本不足,方差估计的置信度低。交叠式Allan方差让相邻块之间可重叠,例如块长为 n 时,以 1 个样本为步长滑动取块,样本利用率大幅提高。这样在长积分时间下,仍然有足够多的平均次数来保证方差估计稳定。
从数学上看,普通Allan方差定义为:
[ \sigma^2_A(\tau) = \frac{1}{2(M-1)} \sum_{i=1}^{M-1} \left( \bar{\theta}_{i+1} - \bar{\theta}_i \right)^2 ]
其中 ( \tau ) 是积分时间,( \bar{\theta}_i ) 是第 i 个非重叠块内角增量平均值。交叠式则把所有可能起点都利用起来:
[ \sigma^2_o(\tau) = \frac{1}{2 n^2 (N - 2n + 1)} \sum_{j=1}^{N-2n+1} \left( \theta_{j+2n} - 2\theta_{j+n} + \theta_j \right)^2 ]
这里 ( \theta_k ) 是累积角增量,( n ) 是每个块内的样本数。这个式子里的二阶差分相当于两次数字积分,能有效消除恒定漂移的影响。gyro_olavar_t.m正是基于这个公式实现。
2.3 为什么要用累积角增量而不是原始角速度
直接对角速度序列做相邻平均差分会引入不必要的噪声。Allan方差理论上要求输入是速率积分——也就是陀螺仪输出的累加角度。实际采集到的角速度数据必须先做累加得到角度增量序列,再执行二阶差分运算。这样做的好处是,角速度零偏在积分后成为一个线性项,二阶差分会将线性项完全消除,于是零偏本身不影响方差曲线,只有零偏不稳定性(随时间缓慢变化的部分)才会在特定积分时间上凸起。
gyro_olavar_t.m中通常的做法是先用cumsum对角速度做累加,再进入交叠循环。这一步是很多初学MATLAB的人容易漏掉的。
3. gyro_olavar_t.m 代码逐段拆解:从原始数据到方差曲线
3.1 脚本结构与函数入口
gyro_olavar_t.m是一个可独立运行的MATLAB脚本或函数。实际下载包里可能同时包含测试数据文件和一个绘图脚本。核心计算部分一般封装成一个函数,输入为角速度序列和采样率。我把它整理成下面这个可复现的版本:
function [tau, avar, error] = gyro_olavar_t(data, fs, factor) % GYRO_OLAVAR_T 交叠式Allan方差计算 % data : 陀螺仪角速度序列,单位 rad/s 或 deg/s % fs : 采样频率,单位 Hz % factor : 可选参数,控制最大积分时间与总时长的比例,默认0.8 % 返回值 % tau : 积分时间数组 % avar : 交叠式Allan方差,对应每个tau % error : 估计误差,用于误差棒绘图 if nargin < 3 factor = 0.8; end N = length(data); if N < 4 error('数据长度至少需要4个样本'); end theta = cumsum(data); % 角增量积分,去掉数据中的任何线性趋势 maxM = floor(log2(N * (1 - factor))) + 1; maxM = min(maxM, floor(log2(N/2))); tau = zeros(maxM, 1); avar = zeros(maxM, 1); error = zeros(maxM, 1); K = N - 2*m + 1; % 可滑动窗口总数 for m = 1:maxM n = 2^(m-1); % 块长指数增长,保证对数横轴均匀 tau(m) = n / fs; K = N - 2*n + 1; if K < 1 break; end % 构造二阶差分:theta(i+2n) - 2*theta(i+n) + theta(i) d = theta(1+2*n : N) - 2*theta(1+n : N-n) + theta(1 : N-2*n); avar(m) = sum(d.^2) / (2 * n^2 * K); % 估计误差(OAVAR近似公式) error(m) = avar(m) / sqrt(K); end % 去掉最后因样本不足导致异常的值 valid = (avar > 0); tau = tau(valid); avar = avar(valid); error = error(valid); end代码的核心在d = theta(1+2*n : N) - 2*theta(1+n : N-n) + theta(1 : N-2*n)这一行。MATLAB 向量的索引写法允许同时对三个子序列做减法,省去了显式循环。这里每个元素对应于原序列中一个长度为 n 的滑动窗口起点 j 的二阶差分。求和sum(d.^2)就是公式中的累加项。分母里2*n^2*K对应标准化因子。
参数factor控制最长积分时间不超过总时长的 80%,避免尾部因样本太少出现的虚假波动。指数增长的n让tau在对数坐标上均匀分布,这比线性取块长更能覆盖多个时间量级。
3.2 主脚本里如何调用并绘图
下载包里通常还有个演示脚本,类似:
load('gyro_static.mat'); % 静态采集的陀螺仪数据 fs = 100; % 采样频率 100Hz data = gyro_static(:); % 确保列向量 % 去除前几秒的预热数据 warmup = 10 * fs; data = data(warmup+1:end); [tau, avar, error] = gyro_olavar_t(data, fs, 0.6); figure; loglog(tau, sqrt(avar), 'o-', 'LineWidth', 1.5); hold on; loglog(tau, sqrt(avar)+sqrt(error), 'r--'); loglog(tau, sqrt(avar)-sqrt(error), 'r--'); xlabel('Integration Time \tau (s)'); ylabel('Allan Deviation \sigma(\tau) (rad/s)'); grid on; title('Overlapped Allan Variance Analysis of Gyro');绘图用loglog而不是semilogy,因为横轴纵轴都跨多个量级。纵轴取sqrt(avar)得到Allan标准差,单位与角速率一致,物理可读性更强。误差棒用虚线画出avar ± error,用来判断曲线上的凹陷是否显著。
3.3 输入参数与输出含义对照表
下表列出函数参数和对应物理意义,方便你根据实际数据调整:
| 参数 | 含义 | 建议值 |
|---|---|---|
data | 静止状态下的陀螺仪角速度序列,列向量 | 至少采集 1 小时以上,越长低频段越可信 |
fs | 采样频率 | 与硬件配置一致,通常 50~200Hz |
factor | 最大积分时间比 | 0.6~0.9,越小曲线尾部越短但估计越稳 |
tau | 积分时间(秒) | 输出,从 1/fs 到约 factor * 总时长 |
avar | 交叠Allan方差(平方单位) | 输出,常取其平方根 |
error | 估计标准差 | 输出,用于绘制误差带 |
注意这里的error并非你测量的误差,而是Allan方差估计本身的统计不确定性。当K很小时,error会显著增大,说明曲线尾部的点不可靠。
4. 跑通例程的实操步骤与参数调优:采样率、块长和预热段
4.1 从 zip 解压到 MATLAB 环境准备
gyro_olavar_t.zip解压后,确认里面至少有gyro_olavar_t.m和可能附带的gyro_static.mat或 CSV 数据。把整个文件夹放进 MATLAB 工作路径,比如:
unzip gyro_olavar_t.zip -d ~/matlab_works在MATLAB里用cd ~/matlab_works切换目录,或者用addpath添加。如果你还没有MATLAB环境,常见的做法是先装好 MATLAB 本体,再安装 Signal Processing Toolbox,因为cumsum和向量化操作不需要额外工具箱,但如果后续要做 PSD 对比,则需要 Signal Processing Toolbox。
4.2 数据采集时的关键约束
这个例程对输入数据质量要求很高。第一,陀螺仪必须处于静态——任何角运动都会在积分后产生趋势项,污染低频段Allan方差。第二,采集时间必须足够长。Allan方差能分辨的最低积分时间受总时长限制,假设你想看到 100 秒附近的零偏不稳定性,至少需要 1000 秒以上的数据,且交叠式算法要求总样本数远大于块长。第三,采样频率必须已知且稳定。如果你的陀螺仪驱动不均匀,实际采样间隔有抖动,直接使用理想fs会导致tau准确度下降,最好用时间戳插值重采样。
4.3 参数调优的三种常见方案
方案一:按 2 的幂取块长。这也是gyro_olavar_t.m的做法,好处是tau在对数轴上均匀分布,绘图方便。如果你的数据量很小(比如只有 10000 个点),指数取块会导致长积分时间下只有一两个点,这时可以把指数步长改为 1.1 或 1.2 倍增长,密度更高但计算量线性增加。
方案二:对非平稳数据做去趋势预处理。陀螺仪静止时如果温度漂移明显,角速度积分会带有线性趋势,二阶差分理论上能消除常数偏置,但线性趋势会残留。可以在调用gyro_olavar_t前用detrend(data)去掉线性分量。注意不要在去除趋势前就去均值,去均值再累加等同于对原始数据做补偿,效果一样。
方案三:分段平均。当你有多个时长的静态数据段,可以分别计算每段的 Allen 方差,再在相同tau处取平均。这比拼接成一段更可靠,因为拼接点会引入阶跃噪声。写个循环:
segments = {seg1, seg2, seg3}; % 三个独立静态段 avar_total = zeros(size(tau)); for k = 1:length(segments) [~, avar_k] = gyro_olavar_t(segments{k}, fs, 0.7); avar_total = avar_total + interp1(tau_k, avar_k, tau, 'linear', 0); end avar_total = avar_total / length(segments);这里用interp1将不同段的方差插值到统一tau网格上。注意'linear', 0表示超出范围时补零,避免影响积分区域。这种做法能明显降低低频段的方差波动。
4.4 运行报错与结果异常排查
如果MATLAB报错说数组索引越界,多半是N太小,或者2*n+1大于N。检查maxM的计算逻辑,确保n <= floor((N-1)/2)。如果画出来的曲线不是平滑的下凸或上凸,而是锯齿状,说明data里存在异常尖峰。先做滑动中值滤波:
data = medfilt1(data, 3);如果曲线尾部严重上翘,且error很大,那是样本量不够,应该增加采集时长或降低factor。如果曲线整体偏高,检查陀螺仪有没有开启自动校零功能,有些IMU内置零偏修正,会滤掉低频分量,导致Allan方差低频段被压低,这是正常现象,但你需要记录这个修正后的曲线代表的是"系统级性能"而不是"传感器裸性能"。
5. 进阶:从Allan方差曲线识别随机游走系数与批量处理技巧
拿到gyro_olavar_t.m计算出的曲线后,下一步是从曲线斜率提取噪声参数。典型的Allan方差曲线由几段直线组成:斜率 -1/2 处对应角度随机游走(ARW),斜率为 0 处的水平段对应零偏不稳定性,斜率 +1/2 处对应速率随机游走(RRW),斜率 +1 处对应速率斜坡。用最小二乘拟合各段的斜率,可以量化这些系数。
例如,ARW系数 ( N )(单位 deg/s/√Hz)可以从曲线左侧斜率为 -1/2 的区域内取值:
idx = find(tau > 0.1 & tau < 1.0); % 假设ARW在0.1~1s区间 p = polyfit(log10(tau(idx)), log10(avar(idx)), 1); % 斜率应接近-1,因为var是用平方,偏差-1对应±0.5 N = 10^(p(2)/2) / sqrt(60); % 单位转换到 deg/sqrt(hr)这里p(1)接近 -1,因为Allan方差纵轴是平方单位。取10^(p(2)/2)得到方差曲线的截距,再除以sqrt(60)换算为业界常用的 deg/√hr。零偏不稳定性 ( B ) 则在斜率接近 0 的最低点处读取:
[~, imin] = min(avar); B = sqrt(avar(imin)) / 0.664;系数 0.664 是理论修正因子,用于把Allan标准差换算为零偏不稳定性带宽。
批量处理多颗陀螺仪或不同温度点数据时,建议将gyro_olavar_t封装成一个循环,输出数组存储,并同时计算温度和老化时间作为附加维度。这样可以快速绘制"Allan方差–温度"热力图,筛出异常个体。另一个实用技巧是保存中间结果:每次运行脚本后,用save('avar_result.mat', 'tau', 'avar')保存,避免重复计算大数组。
验证曲线是否可信有一个快速方法:把loglog(tau, avar)中avar最小的点对应的积分时间 ( \tau_{min} ) 乘上总数据时长 ( T ),理论上 ( \tau_{min} \approx T/3 ) 到 ( T/2 ) 之间。如果你得到的最小值出现在远小于 ( T/3 ) 的位置,说明低频部分还有未去除的漂移项,或者数据中存在慢变温度干扰。此时应回去检查预处理步骤,而不是直接调整参数压点。
gyro_olavar_t.m的核心价值在于把一份静态数据拆成物理可解释的噪声成分。会读曲线,比会跑脚本更重要。
本文还有配套的精品资源,点击获取