草庐IT

六轴传感器+卡尔曼滤波+一阶低通滤波

蜡笔小新学电子 2023-08-20 原文

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


角度与角速度测量

1.角度与角速度获取

  直立控制是通过角度与角速度反馈来进行的,所以角度与角速度的测量至关重要。本系统使用 MPU6050 作为姿态传感器,集成一个加速度传感器和一个陀螺仪,可以输出三轴的加速度与角速度。角速度的获取可以通过陀螺仪来直接读取,角度的获取可以有两种方法来测量:一是通过加速度计的加速度分量来计算,二是通过陀螺仪输出的角速度进行积分获得。
  MPU6050 的坐标系定义如图1-1 。
           

图 1-1 MPU6050 坐标系 

  当传感器的正方向Z 轴垂直指向天空时,由于此时受到地球重力的作用,此时加速度计Z 轴的读数应为正,而且理想情况下应为g。注意此时读取加速度计并不是重力加速度,而是物体自身的运动加速度,正因为自身的运动加速度与重力加速度大小相等方向相反,芯片才能保持静止。
  当传感器静止不动时,我们仅绕X 轴旋转一定的角度θ,此时加速度方向一直与X 轴垂直,X 轴并无加速度分量,忽略X 轴,把加速度分解,如图2-2 所示,可以很容易就算出传感器绕X 轴的角度。
           

图 1-2 绕 X 轴加速度计 


  当仅绕Y 轴旋转时也是同样的原理。当绕Z 轴旋转时,因为重力加速度固定为Z 轴方向,故在X 与Y 轴无加速度分量,仅仅通过加速度计无法得出绕Z轴角度,若想得到绕Z 轴角度,只能通过角速度积分获得,但因为有偏差,一段时间后将不再具有参考意义。
  物体的旋转运动就是绕三轴旋转角度的叠加,我们读取加速度计的数据,根据公式进行处理就可以获取相应的姿态角。故小车绕X 轴与Y 轴的角度可用以下公式算出:
        

  在完全静止的情况下确实通过加速度计就可以获取到所需的角度,但是在实际应用中,小车因为车身摆动等情况会产生加速度,它叠加在测量信号上会无法准确地反映出车模的倾角,图1-3 所示。
        

图 1-3 测量倾角与实际倾角对比 
  传感器安装的高度越低越能抑制因运动产生的加速度,但是还是无法切底消除这种影响。

  那么通过陀螺仪的角速度进行积分得到角度呢?如果测量的角速度存在微小的误差或漂移,经过积分运算之后,形成积累误差,随着时间增加,角度信息将不再准确,这一个方法也是不太可行的。
        
  我们可以综合加速度计和陀螺仪的角度,进行滤波和平滑处理得到准确的角度。程序提供了三种得到准确的角度的算法:1.DMP 算法2.互补滤波算法3.卡尔曼滤波算法。
  DMP 算法是MPU6050 自带的一种滤波方法,只要进行一些初始化,使用官方的库函数就可以读取出四元数,根据公式就可以计算出姿态角。

2 互补滤波

  通过加速度计和陀螺仪获取的角度都有一定的缺点,加速度计获取的角度长期来看比较准确,但是波动大,可以认为其掺杂了高频噪声;陀螺仪获取的角度短时间比较准确,但有积分误差,可以认为其掺杂了低频噪声。我们可以分别让他们通过一个低通滤波器和一个高通滤波器然后叠加在一起,这就是互补滤波算法。

图1-5 互补滤波过程 

图1-6 互补滤波系统框图 


图 1-7 系统框图简化


对应我们的代码为:
angle = K1 * angle_m+ (1-K1) * (angle + gyro_m * dt);
可以看出,互补滤波就是通过加速度计获取的角度对陀螺仪积分的角度进行校准,从而积分的角度逐步跟踪到加速度传感器所得到的角度。K1 与1-K1 是对这两个角度取不同的权重,可以表示我们对不同数据的信任程度。

3卡尔曼滤波

  传感器测量的数据总是有很多的不确定性,比如有很多的噪声,而这些噪声大部分都符合高斯分布。对于我们的小车,输入是角速度,输出是角度,这是一个线性的系统。如果一个系统是线性的系统,而且这些不确定性是符合高斯分布的,那么我们就可以使用卡尔曼滤波算法进行最优估计。卡尔曼滤波的思想就是使用系统的状态方程预测当前的值,使用传感器测出来的观测值来修正这个预测值。与互补滤波一样,可以选择不同的权重来实现,但是这个权重是动态变化的。我们知道一个系统的状态方程和传感器的测量方程如下:








4 实现卡尔一阶低通滤波

/****************************** BEFIN ********************************
**
**@Name       : Complementary_Filter_x
**@Brief      : 一阶互补滤波   
**@Param angle_m: 加速度算出的角度 
**		gyro_m: 陀螺仪的角速度
**@Return     : None
**@Author     : @mayuxin
**@Data	      : 2022-06-04
******************************** END *********************************/
float Complementary_Filter_x(float angle_m, float gyro_m)
{
	 static float angle;
	 float K1 =0.02; 
   angle = K1 * angle_m+ (1-K1) * (angle + gyro_m * dt);
	 return angle;
}

5 实现卡尔曼滤波算法

/****************************** BEFIN ********************************
**
**@Name       : Kalman_Filter_x
**@Brief      : 获取x轴角度简易卡尔曼滤波  
**@Param Accel: 加速度算出的角度
**		  Gyro: 陀螺仪的角速度
**@Return     : None
**@Author     : @mayuxin
**@Data	      : 2022-06-04
******************************** END *********************************/
float dt=0.005;		  //每5ms进行一次滤波    
float Kalman_Filter_x(float Accel,float Gyro)		
{
	static float angle_dot;
	static float angle;
	float Q_angle=0.001; // 过程噪声的协方差
	float Q_gyro=0.003;	//0.003 过程噪声的协方差 过程噪声的协方差为一个一行两列矩阵
	float R_angle=0.5;		// 测量噪声的协方差 既测量偏差
	char  C_0 = 1;
	static float Q_bias, Angle_err;
	static float PCt_0, PCt_1, E;
	static float K_0, K_1, t_0, t_1;
	static float Pdot[4] ={0,0,0,0};
	static float PP[2][2] = { { 1, 0 },{ 0, 1 } };
	angle+=(Gyro - Q_bias) * dt; //先验估计
	Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分

	Pdot[1]=-PP[1][1];
	Pdot[2]=-PP[1][1];
	Pdot[3]=Q_gyro;
	PP[0][0] += Pdot[0] * dt;   // Pk-先验估计误差协方差微分的积分
	PP[0][1] += Pdot[1] * dt;   // =先验估计误差协方差
	PP[1][0] += Pdot[2] * dt;
	PP[1][1] += Pdot[3] * dt;
		
	Angle_err = Accel - angle;	//zk-先验估计
	
	PCt_0 = C_0 * PP[0][0];
	PCt_1 = C_0 * PP[1][0];
	
	E = R_angle + C_0 * PCt_0;
	
	K_0 = PCt_0 / E;
	K_1 = PCt_1 / E;
	
	t_0 = PCt_0;
	t_1 = C_0 * PP[0][1];

	PP[0][0] -= K_0 * t_0;		 //后验估计误差协方差
	PP[0][1] -= K_0 * t_1;
	PP[1][0] -= K_1 * t_0;
	PP[1][1] -= K_1 * t_1;
		
	angle	+= K_0 * Angle_err;	 //后验估计
	Q_bias	+= K_1 * Angle_err;	 //后验估计
	angle_dot   = Gyro - Q_bias;	 //输出值(后验估计)的微分=角速度
	return angle;
}

有关六轴传感器+卡尔曼滤波+一阶低通滤波的更多相关文章

  1. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. ruby - Ruby 中的一阶数组差异 - 2

    执行此操作最巧妙、最像Ruby的方法是什么?[1,3,10,5].diff应该产生[2,7,-5]即一阶差分数组。我想出了一个解决方案,我将在下面添加它,但它需要ruby​​1.9并且不是那么圆滑。还有什么可能? 最佳答案 我喜欢这种函数式风格:moduleEnumerabledefdiffeach_cons(2).map{|pair|pair.reverse.reduce:-}endend编辑:我刚刚意识到reverse是完全没有必要的。如果这是一种函数式语言,我会使用模式匹配,但Ruby不支持模式匹配。但是,它确实支持解构绑定(

  4. javascript - CSS 的笛卡尔失真效果 - 2

    我正在尝试重新创建NewYorkTimesFashionWeek中使用的笛卡尔失真效果页。但是,他们使用D3版本3和D3js的鱼眼插件,但不适用于D3版本4。由于我们做的整个元素都在D3V4中,我无法降级到D3Version3。有没有其他方法可以使用CSS和jquery实现这种效果?我已经尝试过这是我到目前为止的位置:previewwindow.onload=run;functionrun(){if($('.overlayDiv').css('display')!='none'){varcontainer=d3.select('.overlayDiv');container.empty

  5. javascript - 如何在JS中将笛卡尔坐标转换为极坐标? - 2

    我需要使用笛卡尔坐标系中的X和Y知道极坐标系中的旋转Angular。在没有大量IF语句的情况下,如何在JS中实现?我知道我可以使用来做到这一点,但我认为这对性能不利,因为它处于动画循环中。 最佳答案 Javascript带有一个内置函数,可以执行图中所示的操作:Math.atan2()Math.atan2()将y,x作为参数并返回以弧度为单位的Angular。例如:x=3y=4Math.atan2(y,x)//Noticethatyisfirst!//returns0.92729521...radians,whichis53.130

  6. javascript - 球体上的纹理未正确对齐?纬度/经度 -> 笛卡尔 xyz - 2

    我想知道我的球体的纹理是否以某种方式没有正确应用,我是否可以以某种方式抵消它?我试图通过提供纬度/经度并转换为笛卡尔xyz坐标来在澳大利亚悉尼放置一个盒子。但是,盒子没有放在正确的位置。我的猜测是因为原始图像是墨卡托map,所以当它应用于球体时,纬度/经度中心点不正确。下面的代码是一个最小的可重现示例。我正在加载地球图像并将其应用于球体(半径=400)。然后我提供澳大利亚悉尼的纬度/经度(33.8688,-151.2093)并转换为弧度。将纬度/经度转换为笛卡尔xyz(取自:https://stackoverflow.com/a/1185413/3723165)翻译一个盒子并将其推到该

  7. 计算机视觉实践之角点检测--Python实现--sobel滤波--Harris矩阵--角点检测器R--非极大值抑制 - 2

    文章目录前言一、方法原理1.Harris角点检测2.Sobel滤波3.角点响应函数R二、代码实现1.**main函数**2.**corner_detect函数**三、结果对比1.不同检测方法(对比一下使用角点检测器R与H矩阵最小特征值)2.不同超参数k(使用角点检测器R,改变k值)3.非最大值抑制(对3x3的邻域范围内非最大值抑制)四、参考资料前言实现对图像的角点检测,编写Python程序能够对输入图像进行角点检测,并返回角点检测的结果,并且在可视化显示输出结果。而具体的文件和代码,在如下链接里:计算机视觉实践之角点检测Python实现使用的是pycharm,提前导入numpy和opencv库

  8. javascript - 如何使用 Dino 和 Sinatra 显示传感器输出? - 2

    我想在我的页面上显示连接到Arduino的传感器(湿度)之一的输出。按照脚本,每隔一秒给我一些值(数字)。require'dino'board=Dino::Board.new(Dino::TxRx.new)sensor=Dino::Components::Sensor.new(pin:'A0',board:board)on_data=Proc.newdo|data|putsdatasleep1endsensor.when_data_received(on_data)sleep我想我可以使用Sinatra作为API和Javascript脚本来显示异步输出。所以应该是这样的%w(sinat

  9. 长时间数据流的信号滤波处理——基于MATLAB的FIR滤波器设计(1) - 2

    背景对于任意一个场景,获取到的信号都是经过噪声污染过的,一些简单的加性噪声可以通过统计的特性进行滤除,而对于一些乘性的噪声,只能通过滤波进行滤除。在信号处理中,信号滤波会广泛使用。在做研究分析信号的特征时,直接读取到数据,然后分析特征;但是,要想解决实际场景中的问题,就需要一些工程化的思想,因为数据是实时产生的数据流,而滤波也需要实时计算。举个栗子:有一个5秒钟的音频信号,采样频率44100hz,需要滤波提取1500-3000hz频带的信号,假设实际中每次发出1秒钟的音频信号,以数据流的形式发送出来,共发送了5秒钟(实际是无限长的时间)。滤波器设计:基于MATLAB的FIR滤波器的设计音频信号

  10. 深入理解梅尔刻度、梅尔滤波器组和梅尔时频谱图 - 2

    前情提要短时傅里叶变换公式S(m,k)=∑n=1N−1x(n+mH)w(n)e−i2πkNnS(m,k)=\sum_{n=1}^{N-1}x(n+mH)w(n)e^{-i2\pi\frac{k}{N}n}S(m,k)=n=1∑N−1​x(n+mH)w(n)e−i2πNk​n其中,m是当前滤波器的序号,表征了当前的时间段,k是当前频率的序号,表征了当前正在对哪一频率的e−i2πkNne^{-i2\pi\frac{k}{N}n}e−i2πNk​n信号,寻找最佳的振幅和初相,w(n)是窗函数。更多关于短时傅里叶变换的知识,请参考深入理解傅里叶变换(四)。本文要讲解的梅尔时频谱图,需要有时频谱图的知识

随机推荐