三、Allan方差分析

0 原理解释

http://blog.sciencenet.cn/blog-3392538-1123730.html

在Allan方差分析中,共有5个噪声参数:量化噪声、角度随机游走、零偏不稳定性、速度随机游走和速度爬升。不同段的Allan方差曲线代表了不同的误差参数,我们要求解的 零偏噪声(Bias) 对应的曲线段的 斜率就是0

DraggedImage-2.png

Allan方差分析方法可以估计由频率漂移、温度误差、过程噪声等引起的系统误差或缺陷的时域信号的震荡稳定性。

DraggedImage-3.png

DraggedImage-4.png

 

 

1. 概述

在上一篇文章,我们对器件误差的成分进行了分析,并且介绍了最主要的五种误差成分在“方差-时间间隔”的双对数曲线上的直观表现及产生这种表现的原理。同时也提到,在两种误差分析方法中,Allan方差方法比直接方差统计要更有优势,所以本篇文章我们就一起讨论下Allan方差的具体实现方式。

2. 实现方式

Allan方差识别误差的方式是画“方差-时间间隔”双对数曲线,这包含三方面:方差、时间间隔、双对数(好像是一句废话,哈哈)。在测试中,我们按照一定的周期T采集了一段时间数据,根据这些离散的数据,便能计算其方差。这个周期T和方差在二维坐标系中便构成了一个点的横纵坐标。为了得到曲线,我们需要得到更多这样的点,把周期缩短是不可能了,因为不能凭空提高已有数据频率,所以只能把周期拉长。

如果我们对每两个相邻的数取平均,合并成一个,便构成了周期为2T的离散数据,同样也可以得到它的方差,也即又多得到了一个点。按照这样的方法,循环下去,可以得到周期为4T、8T、16T对应的点,直到数据少到无法再合并为止,这样就得到系列的点,也就是曲线了。这样做出来的曲线,其横纵坐标都会很长,各个点之间的间隔也极其不均匀,这也就是为什么用双对数曲线的原因了。

3. 参数拟合

我们先给出一张Allan方差曲线图,对着图来说吧。

在理论上,图中的曲线是由五个直线组成的,五个直线的参数分别包含了我们想要提取的五项误差。所以,只要把直线公式拟合出来,那么参数自然就知道了。我们把上一篇文章的公式再放过来看一下。

从公式上可以看出,我们只要找到直线在任一横坐标处的值,便可提取参数,方便起见,一般取横坐标为1处的值,因为这样,公式右边和时间相关的项就是零。

总结:

Allan方差分析的一个用途是分析陀螺的性能或对比不同陀螺的性能, 相比于其它分析法Allan法还是很好用的,比较全面。另一个用途是获得噪声参数,用于组合导航的Kalman滤波噪声参数设置。不是所有的Allan方差噪声系数都有用,主要有用的是角度随机游走系数(用于设置Q阵)和零偏不稳定性系数(用于设置一阶马氏过程的方差),其实这两个系数量级大小差不多就行了,太精细也没用。毕竟Allan方差分析的只是一个样本,你再采一个样本试试,肯定会有差异的;此外采集的是陀螺的静态性能数据,鬼知道实际动态应用的时候陀螺误差会变化多大,存在数量级差别都很有可能。这里需要的是理论指导下的工程和经验,而不是教条主义

4. 代码实践

我们使用开源系统imu_utils为例,来看提取参数的具体实现方式。

开源代码地址:https://github.com/gaowenliang/imu_utils

1) 代码思路

以上我们拟合直线,再求交点的方式,适合人工操作,按这种方式,给出一个曲线图,很快就可以计算出各误差参数。而对于机器来讲,则似乎不太适合,首先让它把曲线自适应地分成五段就要费一番功夫,此时就需要换一种思路。既然曲线是五条直线组成,而五条直线的公式已知,那么五条直线加一起不就是曲线的公式了吗,有了曲线公式,又有了曲线实际数据,那么这就变成了一个曲线拟合问题,用优化的方式就可以直接解决。比较来讲,这两种方式无好坏之分,只能说一个更适合人工,一个更适合机器,为各自量身打造。

2) 代码细节

首先是把原始数据划分成不同的时间间隔,思路就是上面提到的倍增法

int mode = numData / 2;
unsigned int maxStride = 1;
int shft  =0;
while(mode){
    mode = mode >> 1;
    maxStride = 1 << shft;
    shft++;
}

然后每一个间隔下都计算一个方差,并把方差和真实曲线建立残差模型。

for ( int i = 0; i < num_samples; ++i ) {
    ceres::CostFunction* f = new ceres::AutoDiffCostFunction< AllanSigmaError, 1, 5 > (new AllanSigmaError( sigma2s_tmp[i], m_taus[i] ) );
    problem.AddResidualBlock( f, NULL, param );
}

其中残差的计算如下:

// 计算残差
template< typename T >
bool operator( )( const T* const _paramt, T* residuals ) const {
    T _Q   = T( _paramt[0] );
    T _N   = T( _paramt[1] );
    T _B   = T( _paramt[2] );
    T _K   = T( _paramt[3] );
    T _R   = T( _paramt[4] );
    T _tau = T( tau );

    T _sigma2    = calcSigma2( _Q, _N, _B, _K, _R, _tau );
    T _dsigma2   = T( calcLog10( _sigma2 ) ) - T( calcLog10( sigma2 ) );
    residuals[0] = _dsigma2;
        
    return true;
}

// 叠加五个直线,得到曲线方程
template< typename T >
T calcSigma2( T _Q, T _N, T _B, T _K, T _R, T _tau ) const {
    return  _Q * _Q / ( _tau * _tau )
          + _N * _N / _tau
          + _B * _B
          + _K * _K * _tau
          + _R * _R * _tau * _tau;
}

最后,通过迭代优化,就可以直接计算出那五个参数了。

 

5. MATLAB程序 (转载于:https://blog.csdn.net/u012325601/article/details/60882949

博客所对应的ALLAN方差的matlab源码地址为:https://github.com/XinLiGH/GyroAllan

allan.m文件

function [T,sigma] = allan(omega,fs,pts)
[N,M] = size(omega);             % figure out how big the output data set is
n = 2.^(0:floor(log2(N/2)))';    % determine largest bin size
maxN = n(end);
endLogInc = log10(maxN);
m = unique(ceil(logspace(0,endLogInc,pts)))';    % create log spaced vector average factor
t0 = 1/fs;                                       % t0 = sample interval
T = m*t0;                                        % T = length of time for each cluster
theta = cumsum(omega)/fs;       % integration of samples over time to obtain output angle θ
sigma2 = zeros(length(T),M);    % array of dimensions (cluster periods) X (#variables)
for i=1:length(m)               % loop over the various cluster sizes
    for k=1:N-2*m(i)            % implements the summation in the AV equation
        sigma2(i,:) = sigma2(i,:) + (theta(k+2*m(i),:) - 2*theta(k+m(i),:) + theta(k,:)).^2;
    end
end
sigma2 = sigma2./repmat((2*T.^2.*(N-2*m)),1,M);
sigma = sqrt(sigma2);

 nihe.m文件

function C=nihe(tau,sig,M)
X=tau';Y=sig';
B=zeros(1,2*M+1);
F=zeros(length(X),2*M+1);

for i=1:2*M+1
    kk=i-M-1;
    F(:,i)=X.^kk;
end

A=F'*F;
B=F'*Y;
C=A\B;

gyro_data.m文件

clear
clc
close all
 
% --------------------.bin文件得读取方式 ---------------------%  
fip=fopen('201214204200_imu.bin','rb');
[data,num]=fread(fip,[7 624300],'double');%inf表示读取文件中的所有数据,[M,N]表
fclose(fip)
data = data';
    
% --------------------.txt文件得读取方式 ---------------------% 
% data = importdata("imu.txt");          %读取名字为 imu.txt 的文件
 
datanumber = 624300;                   % 注释后面的,先看一下自己的数据大小
IMU_raw_data = zeros(datanumber,7); 
IMU_raw_gyro_data = zeros(datanumber,3); 

 for i = 1:1:datanumber
  IMU_raw_data(i,1:7) = data(i,1:7)*200;               %(1)IMU增量变成角速度; 否则不用*200
  IMU_raw_gyro_data(i,1:3) = IMU_raw_data(i,2:4)*3600; %(2)把 deg/s 转为 deg/h 
 end
  
[A, B] = allan(IMU_raw_gyro_data, 100, 100);           %求Allan标准差,用100个点来描述
 
loglog(A, B, 'o');                                   %画双对数坐标图
xlabel('time:sec');                                  %添加x轴标签
ylabel('Sigma:deg/h');                               %添加y轴标签
legend('X axis','Y axis','Z axis');                  %添加标注
grid on;                                             %添加网格线
hold on;                                             %使图像不被覆盖
 
C(1, :) = nihe(A', (B(:,1)').^2, 2)';                %拟合
C(2, :) = nihe(A', (B(:,2)').^2, 2)';
C(3, :) = nihe(A', (B(:,3)').^2, 2)';
 
Q = sqrt(abs(C(:, 1) / 3));                           %量化噪声,单位:deg/h
N = sqrt(abs(C(:, 2) / 1)) / 60;	                  %角度随机游走,单位:deg/h^0.5
Bs = sqrt(abs(C(:, 3))) / 0.6643;	                  %零偏不稳定性,单位:deg/h
K = sqrt(abs(C(:, 4) * 3)) * 60;	                  %角速率游走,单位:deg/h/h^0.5
R = sqrt(abs(C(:, 5) * 2)) * 3600;	                  %速率斜坡,单位:deg/h/h
 
fprintf('量化噪声      X轴:%f Y轴:%f Z轴:%f  单位:deg/h\n', Q(1), Q(2), Q(3));
fprintf('角度随机游走  X轴:%f Y轴:%f Z轴:%f  单位:deg/h^0.5\n', N(1), N(2), N(3));
fprintf('零偏不稳定性  X轴:%f Y轴:%f Z轴:%f  单位:deg/h\n', Bs(1), Bs(2), Bs(3));
fprintf('角速率游走    X轴:%f Y轴:%f Z轴:%f  单位:deg/h/h^0.5\n', K(1), K(2), K(3));
fprintf('速率斜坡      X轴:%f Y轴:%f Z轴:%f  单位:deg/h/h\n', R(1), R(2), R(3));
 
D(:, 1) = sqrt(C(1,1)*A.^(-2) + C(1,2)*A.^(-1) + C(1,3)*A.^(0) + C(1,4)*A.^(1) + C(1,5)*A.^(2));	%生成拟合函数
D(:, 2) = sqrt(C(2,1)*A.^(-2) + C(2,2)*A.^(-1) + C(2,3)*A.^(0) + C(2,4)*A.^(1) + C(2,5)*A.^(2));
D(:, 3) = sqrt(C(3,1)*A.^(-2) + C(3,2)*A.^(-1) + C(3,3)*A.^(0) + C(3,4)*A.^(1) + C(3,5)*A.^(2));
 
loglog(A, D);   %画双对数坐标图

运行结果 (放置10个小时左右

 

  量化噪声        X轴:0.003226 Y轴:0.004128 Z轴:0.001843  单位:deg/h
角度随机游走   X轴:0.003048 Y轴:0.004053 Z轴:0.004220  单位:deg/h^0.5
零偏不稳定性   X轴:0.273572 Y轴:0.353873 Z轴:0.277789  单位:deg/h
角速率游走      X轴:2.661679 Y轴:5.058015 Z轴:3.378206  单位:deg/h/h^0.5
速率斜坡          X轴:1.636452 Y轴:4.985344 Z轴:7.571720  单位:deg/h/h

 注意:当Allan标准差的拟合多项式中的拟合系数是负值时,所得误差项的拟合结果随着相关时间的微小改变变化很大,拟合误差很大,可信度差。

 

参考文献下载地址如下 

链接:https://pan.baidu.com/s/1TTzZywJb1tdaVWuI-XMclw 密码:l7p4

6. 一些实践经验

至此为止,我们应该已经弄清了器件误差提取方法,然而,实践总是会给人惊喜,出现一些意料之外,而且我们也不必完全拘泥于理论,要看我们的目的是什么。

1)  有的时候不一定五个斜率全都能体现出来,我们知道,每个斜率对应一项误差,如果某项误差相对于其他项的量级比较小,那么曲线中就没有他什么事了,直接被掩盖,极端情况下,一个曲线只有一个斜率也是有可能的。

2)  Allan方差对误差项提取的比较多,但是很多误差项的分析都是为了提高器件生产工艺用的,每种误差成分产生的原理不同,通过分析哪种误差成分为主,我们就知道为了提高精度,应该重点改进哪项工艺。如果只是为传感器融合找个方差的参数,大可不必计算那么细致,在图上看一下大致量级,就可以直接用了,因为参数早晚都是要调的。严格来讲,滤波的方差其实应该用白噪声强度,它不属于这五项误差的任何一项,但是很多时候手册上不给出这个强度值,而方差参数在用的时候都会结合系统再一次进行调整,所以有些时候直接用零偏不稳定性做方差初值也不是不可以。

3)  随机游走这种东西理论上是可以建模,但是实际滤波模型中却很少使用,甚至不建议使用。一是、因为它并不是构成零偏趋势项的主要成分,往往都被温变等的趋势掩盖,即使做了温补也是这样。二是、因为Allan方差识别出的参数并不完全准确,这会带来模型误差,不准确的模型还不如没有模型,因为它会使滤波变得不稳定,效果反而变差。

 

 

根据 Allan  方差图,获得 IMU 参数过程:
https://download.csdn.net/download/qq_41764205/10640809?utm_medium=distribute.pc_aggpage_search_result.none-task-download-2~aggregatepage~first_rank_v2~rank_v29-6-10640809.nonecase&utm_term=allan%E6%96%B9%E5%B7%AE%E5%88%86%E6%9E%90&spm=1000.2123.3001.4430

 

https://blog.csdn.net/chenshiming1995/article/details/105549405?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase

四、IMU误差标定之基于转台的标定

  • 15
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值