深入浅出理解Allan方差分析方法

一、参考资料

深入浅出理解卡尔曼滤波

二、Allan方差分析方法

1. 引言

传统的误差指标往往是采用均值误差(反映整个误差序列有无宏观偏置)、标准差(反映整个误差序列的波动情况),以及均方根(RMS,可以认为是宏观偏置与波动情况的综合)。如下图所示,它们都是反映误差序列的整体情况的指标,其中含有短时间快速变化和长时间缓变的各个成份,无法细分出不同时间尺度上的误差波动情况
在这里插入图片描述

Allan方差是一个相对而言直观形象、朴实无华的概念,它当初是在实践中针对高精度时钟稳定性分析的需求而提出的。Allan方差适用于分析惯导(和时钟)看重长期稳定性的传感器,Allan方差曲线对中长期时间尺度上的误差特性有很强的表现力。Allan方差相比于普通的方差具有更好的描述长时间误差的优势,因此,Allan方差被用来当作IMU噪声标定的标准方法

2. Allan方差的概念

Allan方差,又称为阿伦方差阿兰方差,Allan方差法是20世纪60年代由美国国家标准局的David Allan提出的基于时域的分析方法。

设计Allan方差分析方法的目的,是为了实现这样一种分析:对惯性传感器误差的关注,主要体现在不确定性和稳定性,具体来说,是不同时间尺度的稳定性。例如,战术武器领域关心的是多少秒到多少分钟时间尺度的稳定性,潜水艇领域关心的是天、轴周、月时间尺度的稳定性。那么有没有什么方法,将不同时间尺度上的不确定性,分门别类的表现出来,Allan教授针对这个问题,提出了Allan方差分析方法。

Allan方差是时频分析惯性导航领域常用的一种误差分析方法,它有效地刻画了待研究的误差时间序列在不同时间尺度上的波动水平(不稳定性),并可根据不同时间尺度上的Allan方差值所构成的曲线的形状特征来辨识其中包含的随机过程模型。Allan方差分析方法对中长期的随机波动具有很强的表现力,它完全可以作为一个通用的时间序列分析工具来推广到其它应用领域。

在我们对惯性导航器件(陀螺和加速度计)进行误差分析时,常采用Allan方差分析方法。这是当初从时频领域(高精度时钟的频率稳定性)借鉴来的一种时间序列分析方法非常适合于对中长期波动(不稳定性)进行定量描述和分析,因此正是我们惯性器件误差分析所需要的。

3. Allan方差计算过程

Allan方差是将误差序列在某个指定的时间尺度上的波动情况进行了精确提取,其具体计算步骤如下:
在这里插入图片描述

Step 1 分块

按窗口长度 τ = ( n − 1 ) t 0 \tau=\left(\left.n-1\right.\right)t_0 τ=(n1)t0 将序列 y 分成 N c N_c Nc 块(clusters),每块包n个数据点,块间无重叠。

Step 2 块平均

分别计算各块内n个数据点的均值,记为: y ‾ k = 1 n ∑ i = ⁡ k k + n − 1 y i \begin{aligned}\overline{y}_k=\frac1n\sum_{i\operatorname{=}k}^{k+n-1}y_i\end{aligned} yk=n1i=kk+n1yi

Step 3 计算Allan方差

相邻块的平均值求差。
σ 2 ( τ ) = 1 2 ( N c − 1 ) ∑ k = 1 N c − 1 ( y ˉ k + 1 − y ˉ k ) 2 \begin{aligned}\sigma^2(\tau)=\frac{1}{2(N_c-1)}\sum_{k=1}^{N_c-1}(\bar{y}_{k+1}-\bar{y}_k)^2\end{aligned} σ2(τ)=2(Nc1)1k=1Nc1(yˉk+1yˉk)2

Step 4 统计RMS值

根据Step 3求得的差值,统计RMS值。

(可选)Step 5 绘制Allan方差曲线

改变块长度,重复1~3,并画出Allan标准差随块长度变化的双对数曲线,称为Allan方差曲线。从图中可知,每个时间块,对应一个Allan方差,将所有的不同块时间和对应的Allan方差连起来,即绘制成Allan标准曲线。那么,Allan方差分析就是分析Allan标准曲线。

4. Allan方差图读取误差系数

Allan方差法可用于5种随机误差的标定:

  • 量化噪声:误差系数为 Q Q Q,Allan方差双对数曲线上斜率为-1的线段延长线与t=1的交点的纵坐标读数为 3 T Q \frac{\sqrt{3}}{T}Q T3 Q
  • 角度随机游走:其误差系数 N N N,Allan方差双对数曲线上斜率为 − 1 / 2 -1/2 1/2的线段延长线与 t = 1 t=1 t=1交点的纵坐标读数即为 N T \frac{N}{\sqrt{T}} T N
  • 零偏不稳定性:其误差系数 B B B,Allan方差双对数曲线上斜率为0的线段延长线与t=1交点的纵坐标读数为 2 ln ⁡ 2 π B \sqrt{\frac{2\ln2}{\pi}}B π2ln2 B ,一般常取底部平坦区的最小值或取 t = 1 0 1 t=10^1 t=101 t = 1 0 2 t=10^2 t=102 处的值;
  • 角速率随机游走:其误差系数 K K K,斜率为1/2的线段延长线与 t = 1 t = 1 t=1交点的纵坐标读数为 K T / 3 \frac{K}{\sqrt{T/3}} T/3 K
  • 角速率斜坡:其误差系数 R R R,斜率为1的线段延长线与 t = 1 t=1 t=1交点的纵坐标读数为 R T 2 \frac{RT}{\sqrt{2}} 2 RT
    在这里插入图片描述

假设各种误差源统计独立,那总的艾伦方差为各种误差源之和,即将量化噪声的平方 σ Q σ_Q σQ、角度随机游走的平方 σ R A W σ_{RAW} σRAW、零偏不稳定性的平方 σ b i a s σ_{bias} σbias、角速率随机游走的平方 σ R R W σ_{RRW} σRRW、角速率斜坡的平方 σ R R σ_{RR} σRR的总和。
在这里插入图片描述

5. Allan方差分析

通过块内求平均,去除短时间的不确定性;通过相邻块间求差,去除长时间的不确定性。

如果我们只对某一时间尺度上的误差(即误差波动)感兴趣的话,那么比这个时间尺度更小的细节变化(短时间快速跳动)和比这个时间尺度更大的宏观变化(长时间缓慢漂移)就都不关心了,希望在我们的误差指标中都被消除掉。而Allan方差是这样做到的:

  1. 通过分块确定所要考察的时间块长度;

  2. 利用块内求平均的办法把短于块长度的那些快速变化成份(细节)都抹掉;

  3. 再利用相邻块求差的办法把长于两块长度的那些缓慢变化成份(宏观)都抹掉;

  4. 最后对差值序列统计其方值(这是处理任何随机样本的标准操作),这样统计出来的就是介于1倍块长度和2倍块长度这样一个很窄的时间尺度范围内的误差波动情况。

6. Allan方差曲线

如果我们对误差序列的各个时间尺度上的成份都感兴趣的话,可以将块长度由短到长,“扫描”一遍,得出一组Allan方差值,然后画个“Allan方差 vs. 块长度”的曲线,这样就能全面反映被研究的误差序列的特性了。具体的,实际上是“Allan方差的开方(Allan Deviation) vs. 块长度”的双对数曲线,以便在更大的范围上有更强的表现力。以下是一张经典的高精度陀螺的Allan方差示意图。
在这里插入图片描述
在这里插入图片描述

从Allan方差曲线上,我们可以根据曲线的形状特征来识别出不同类型的随机误差(即随机过程模型)并提取其参数。例如:斜率为-1/2的直线段代表白噪声。具体可参见IEEE制定的一个关于陀螺测试的技术标准中的附录C内容[1]。这个附录中还给出了一个从Allan方差曲线中分析陀螺的多种随机误差的案例(如上图)。但我想提醒大家,实际的Allan方差曲线往往只能表现出少数两三个主要误差类型,因为其它误差都被这几个主要误差给淹没了。而由于我们在工程上关心的恰恰也就是主要误差源,因此我们并不受此困扰。更多的使用Allan方差分析过程中的注意事项可参考西工大严恭敏老师的博文《Allan方差分析的使用要点》,写得非常精准务实。

7. Allan方差的应用

Allan方差分析方法并不局限于对惯性器件和时钟误差的分析,也可推广到其它误差序列分析;而且它也不局限于是对误差序列进行分析,也可应用于任何时间序列的分析(例如建筑形变、地质演化等)。

8. Allan方差与ROS

下面是读取bag包,并获取Allen方差的图片,会生成对应的Allen方差图。这里主要参考了allan_variance_ros 对应的C++文件。

sudo pip install allantools
#!/usr/bin/env python
import rospy
import sys
import allantools
import rosbag
import numpy as np
import csv
import rospkg
import os
import matplotlib.pyplot as plt  # only for plotting, not required for calculations
import mathdef getRandomWalkSegment(tau,sigma):m = -0.5 # slope of random walk"""""""""""""""""""""""""""""""""" Find point where slope = -0.5 """"""""""""""""""""""""""""""""""randomWalk = Nonei = 1idx = 1mindiff = 999logTau = -999while (logTau<0):logTau = math.log(tau[i],10) logSigma = math.log(sigma[i],10)prevLogTau = math.log(tau[i-1],10)prevLogSigma = math.log(sigma[i-1],10)slope = (logSigma-prevLogSigma)/(logTau-prevLogTau)# 随机漫步的斜率diff = abs(slope-m)# 当前斜率与目标斜率的差值if (diff<mindiff):mindiff = diff# 更新最小差值idx = ii = i + 1""""""""""""""""""""""""""""""" Project line to tau = 10^0 """""""""""""""""""""""""""""""x1 = math.log(tau[idx],10)# 当前点的横坐标y1 = math.log(sigma[idx],10)# 当前点的纵坐标x2 = 0y2 = m*(x2-x1)+y1return (pow(10,x1),pow(10,y1),pow(10,x2),pow(10,y2))def getBiasInstabilityPoint(tau,sigma):i = 1while (i<tau.size):if (tau[i]>1) and ((sigma[i]-sigma[i-1])>0): # only check for tau > 10^0breaki = i + 1return (tau[i],sigma[i])def main(args):rospy.init_node('allan_variance_node')t0 = rospy.get_time()""""""""""""""" Parameters """""""""""""""bagfile = rospy.get_param('~bagfile_path','~/data/static.bag')# 输入的bag文件路径topic = rospy.get_param('~imu_topic_name','/imu')# 输入的imu topic名称axis = rospy.get_param('~axis',0)# 输入的轴,0为x轴,1为y轴,2为z轴sampleRate = rospy.get_param('~sample_rate',100)# 输入的采样频率isDeltaType = rospy.get_param('~delta_measurement',False)# 是否是delta measurementnumTau = rospy.get_param('~number_of_lags',1000)# 输入的tau数目resultsPath = rospy.get_param('~results_directory_path',None)# 输出的结果路径""""""""""""""""""""""""""" Results Directory Path """""""""""""""""""""""""""if resultsPath is None:paths = rospkg.get_ros_paths()path = paths[1] # path to workspace's develidx = path.find("ws/")# 找到路径workspacePath = path[0:(idx+3)]# 取到workspace的路径resultsPath = workspacePath + 'av_results/'# 结果输出路径if not os.path.isdir(resultsPath):os.mkdir(resultsPath)print("\nResults will be save in the following directory: \n\n\t %s\n"%resultsPath)""""""""""""""""""" Form Tau Array """""""""""""""""""taus = [None]*numTau# 初始化tau数组cnt = 0;for i in np.linspace(-2.0, 5.0, num=numTau): # lags will span from 10^-2 to 10^5, log spacedtaus[cnt] = pow(10,i)# 将tau数组赋值,维度在10^-2 到 10^5cnt = cnt + 1"""""""""""""""""" Parse Bagfile """"""""""""""""""bag = rosbag.Bag(bagfile)N = bag.get_message_count(topic) # 在bag文件中找到该topic的消息数量data = np.zeros( (6,N) ) # 初始化数据矩阵,维度为6*Nif isDeltaType:scale = sampleRateelse:scale = 1.0cnt = 0for topic, msg, t in bag.read_messages(topics=[topic]):# 遍历bag文件中的消息data[0,cnt] = msg.linear_acceleration.x * scaledata[1,cnt] = msg.linear_acceleration.y * scaledata[2,cnt] = msg.linear_acceleration.z * scaledata[3,cnt] = msg.angular_velocity.x * scaledata[4,cnt] = msg.angular_velocity.y * scaledata[5,cnt] = msg.angular_velocity.z * scalecnt = cnt + 1bag.close()print ("[%0.2f seconds] Bagfile parsed\n"%(rospy.get_time()-t0))""""""""""""""""""" Allan Variance """""""""""""""""""if axis is 0:currentAxis = 1 # 循环通过所有轴1-6else:currentAxis = axis # 只需循环一次,然后中断while (currentAxis <= 6):# taus_used 对应了是否可以使用taus的数组,adev是allan deviation degree的缩写,为allan偏差;adev_err是allan偏差的误差;adev_norm是allan偏差的标准化;(taus_used, adev, adev_err, adev_n) = allantools.oadev(data[currentAxis-1], data_type='freq', rate=float(sampleRate), taus=np.array(taus) )# 计算allan variancerandomWalkSegment = getRandomWalkSegment(taus_used,adev)# 计算random walk segmentbiasInstabilityPoint = getBiasInstabilityPoint(taus_used,adev)# 计算bias instability pointrandomWalk = randomWalkSegment[3]# 获取random walk segment的纵坐标biasInstability = biasInstabilityPoint[1]# 获取bias instability point的纵坐标"""""""""""""""" Save as CSV """"""""""""""""if (currentAxis==1):fname = 'allan_accel_x'title = 'Allan Deviation: Accelerometer X'elif (currentAxis==2):fname = 'allan_accel_y'title = 'Allan Deviation: Accelerometer Y'elif (currentAxis==3):fname = 'allan_accel_z'title = 'Allan Deviation: Accelerometer Z'elif (currentAxis==4):fname = 'allan_gyro_x'title = 'Allan Deviation: Gyroscope X'elif (currentAxis==5):fname = 'allan_gyro_y'title = 'Allan Deviation: Gyroscope Y'elif (currentAxis==6):fname = 'allan_gyro_z'title = 'Allan Deviation: Gyroscope Z'print ("[%0.2f seconds] Finished calculating allan variance - writing results to %s"%(rospy.get_time()-t0,fname))f = open(resultsPath + fname + '.csv', 'wt')try:writer = csv.writer(f)writer.writerow( ('Random Walk', 'Bias Instability') )writer.writerow( (randomWalk, biasInstability) )writer.writerow( ('Tau', 'AllanDev', 'AllanDevError', 'AllanDevN') )for i in range(taus_used.size):writer.writerow( (taus_used[i],adev[i],adev_err[i],adev_n[i])  )finally:f.close()"""""""""""""""" Plot Result """"""""""""""""plt.figure(figsize=(12,8))ax = plt.gca()ax.set_yscale('log')ax.set_xscale('log')plt.plot(taus_used,adev)plt.plot([randomWalkSegment[0],randomWalkSegment[2]],[randomWalkSegment[1],randomWalkSegment[3]],'k--')plt.plot(1,randomWalk,'rx',markeredgewidth=2.5,markersize=14.0)plt.plot(biasInstabilityPoint[0],biasInstabilityPoint[1],'ro')plt.grid(True, which="both")plt.title(title)plt.xlabel('Tau (s)')plt.ylabel('ADEV')for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +ax.get_xticklabels() + ax.get_yticklabels()):item.set_fontsize(20)plt.show(block=False)plt.savefig(resultsPath + fname)currentAxis = currentAxis + 1 + axis*6 # increment currentAxis also break if axis is not =0inp=input("Press Enter key to close figures and end program\n")if __name__ == '__main__':main(sys.argv)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样来实现流量削峰方案

削峰从本质上来说就是更多地延缓用户请求&#xff0c;以及层层过滤用户的访问需求&#xff0c;遵从“最后落地到数据库的请求数要尽量少”的原则。 1.消息队列解决削峰 要对流量进行削峰&#xff0c;最容易想到的解决方案就是用消息队列来缓冲瞬时流量&#xff0c;把同步的直…

uview ui 1.x ActonSheet项太多,设置滚动(亲测有效)

问题&#xff1a;ActionSheet滚动不了。 使用uview ui &#xff1a;u-action-sheet, 但是item太多&#xff0c;超出屏幕了&#xff0c; 查了一下文档&#xff0c;并没有设置滚动的地方。 官方文档&#xff1a;ActionSheet 操作菜单 | uView - 多平台快速开发的UI框架 - uni-a…

Spring Cloud--从零开始搭建微服务基础环境【三】

&#x1f600;前言 本篇博文是关于Spring Cloud–从零开始搭建微服务基础环境【三】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;…

使用Fiddler模拟网络

Fiddler已经预置提供了模拟Modem速度的选项&#xff0c;其位置位于&#xff1a; Rules->Performances->Simulate Modem Speeds 勾选该选项后&#xff0c;所有通过Fiddler代理的流量都会变得用56k modem上网一般。 要直观观察限速后的效果&#xff0c;最好使用运行在浏览…

Linux用一键安装包部署禅道(18.5版本)

一、安装 禅道软件下载地址&#xff1a;禅道官方下载地址 - 禅道开源项目管理软件 - 禅道开源项目管理软件 请根据自己的需要下载对应的版本。 官方教程地址: (推荐)Linux用一键安装包 - 禅道使用手册 - 禅道开源项目管理软件 注&#xff1a;Linux 一键安装包必须直接解压到 …

2023-9-3 分解质因数

题目链接&#xff1a;分解质因数 #include <iostream>using namespace std;void divide(int n) {for(int i 2; i < n / i; i ){if(n % i 0){int res 0;while(n % i 0){n / i;res ;}cout << i << << res << endl;}}if(n > 1) cout &l…

linux 内存一致性

linux 出现内存一致性的场景 1、编译器优化 &#xff0c;代码上下没有关联的时候&#xff0c;因为编译优化&#xff0c;会有执行执行顺序不一致的问题&#xff08;多核单核都会出现&#xff09; 2、多核cpu乱序执行&#xff0c;cpu的乱序执行导致内存不一致&#xff08;多核出…

匠心新品:大彩科技超薄7寸WIFI线控器发布,热泵、温控器、智能家电首选!

一、产品介绍 此次发布一款7寸高清全新外壳产品&#xff0c;让HMI人机界面家族再添一新成员。该产品相比其他外壳有以下5个大改动&#xff1a; 1 表面玻璃盖板使用2.5D立体结构&#xff1b; 2 液晶盖板采用一体黑设计&#xff0c;且液晶屏与触摸板是全贴合结构&#xff1b; …

卡片介绍、EMV卡组织、金融认证---安全行业基础篇2

一、卡片介绍 卡片是一种用于存储和传输数据的可携带式物品&#xff0c;通常由塑料或纸质材料制成。卡片通常具有特定的尺寸和形状&#xff0c;以适应各类读写设备。不同类型的卡片可以用于不同的应用&#xff0c;如身份验证、支付、门禁控制等。 接触卡 接触卡是一种需要与读…

SpringBoot 整合 RabbitMQ

1. 创建 SpringBoot 工程 把版本改为 2.7.14 引入这两个依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springfr…

【高效编程技巧】编程菜鸟和编程大佬的差距究竟在哪里?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《C语言进阶》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言1.如何写出好的代码&#xff1f;1.2 如何分析一个函数写的怎么样 2. 代码板式的重要性2.1 代码…

C#---第21: partial修饰类的特性及应用

0.知识背景 局部类型适用于以下情况&#xff1a; 类型特别大&#xff0c;不宜放在一个文件中实现。一个类型中的一部分代码为自动化工具生成的代码&#xff0c;不宜与我们自己编写的代码混合在一起。需要多人合作编写一个类 局部类型的限制: 局部类型只适用于类、接口、结构&am…

Python Qt学习(九)MainWindow

源代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file qt_mainwindow.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do n…

【UE 材质】常用向量运算节点——点积、叉积、归一化

目录 一、点积 二、叉积 三、归一化 一、点积 点积&#xff0c;也称为内积或数量积&#xff0c;是一种用于计算两个向量之间关系的操作。对于两个三维向量 A&#xff08;a1,a2,a3&#xff09;和 B(b1,b2,b3)&#xff0c;它们的点积可以用以下公式表示&#xff1a; ABa1​⋅…

大数据课程K13——Spark的距离度量相似度度量

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Spark的距离度量和相似度度量; ⚪ 掌握Spark的欧氏距离; ⚪ 掌握Spark的曼哈顿距离; ⚪ 掌握Spark的切比雪夫距离; ⚪ 掌握Spark的最小二乘法; 一、距离度量和相似度度量 1. …

【Grasshopper基础15】“右键菜单似乎不太对劲”

距离上一篇文章已经过去了挺久的&#xff0c;很长时间没有写GH基础部分的内容了&#xff0c;原因其一是本职工作太忙了&#xff0c;进度也有些落后&#xff0c;白天工作累成马&#xff0c;回家只想躺着&#xff1b;其二则是感觉GH基础系列基本上也介绍得差不多了&#xff0c;电…

1分钟实现 CLIP + Annoy + Gradio 文搜图+图搜图 系统

多模态图文搜索系统 CLIP 进行 Text 和 Image 的语义EmbeddingAnnoy 向量数据库实现树状结构索引来加速最近邻搜索Gradio 轻量级的机器学习 Web 前端搭建 文搜图 图搜图 CLIP图像语义提取功能&#xff01;

数据结构 -作用及基本概念

为什么要使用数据结构 学习数据结构是计算机科学和软件工程领域中非常重要的一门课程。以下是学习数据结构的几个重要原因&#xff1a; 组织和管理数据&#xff1a;数据结构提供了一种组织和管理数据的方式。通过学习不同的数据结构&#xff0c;你可以了解如何有效地存储和操作…

Python Tcp编程

网络连接与通信是我们学习任何编程语言都绕不过的知识点。Python 也不例外&#xff0c;本文就介绍因特网的核心协议 TCP &#xff0c;以及如何用 Python 实现 TCP 的连接与通信。 TCP 协议 TCP协议&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#…

从入门到精通,30天带你学会C++【第六天:与或非三兄弟和If判断语句(博主目前最长文章,2514字)】(学不会你找我)

目录 前言 计算机里的真和假 与或非三兄弟 与运算&#xff08;&&&#xff09; 具体说明表格&#xff1a; 举个栗子1&#xff1a; 或运算&#xff08;||&#xff09; 具体说明表格&#xff1a; 举个栗子2&#xff1a; 非运算&#xff08;!&#xff09; 具体…