基于一阶互补滤波的MPU6050姿态解算

2024-01-11 03:20

本文主要是介绍基于一阶互补滤波的MPU6050姿态解算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前报名了第十八届全国大学生智能车竞赛的单车越野组别,但由于种种原因最终未能完赛。所以打算把自己做好的一部分发出来,希望对往后的刚参加竞赛的同学们有所帮助,同时也是对自己过去一个多学期生活的一点总结。由于学疏才浅,如有不准确或者错误的地方,还请不吝赐教。

代码基于逐飞科技的CH32V307开源库。

为什么需要一阶互补滤波

当我们通过MPU6050进行姿态解算时,MPU6050给了我们两组数据:一组来自加速度计,一组来自陀螺仪。两个传感器的数据都可以独自求得小车此时的角度,但它们也各自存在问题:加速度计比较敏感,由振动产生的瞬时误差比较大;陀螺仪积分得到的角度虽然受振动影响比较小,但随着时间的增加,积分误差和温度漂移会逐渐增大。从另一角度加以解释,就是加速度计主要受到高频噪声的影响,而陀螺仪主要受到低频噪声的影响。这两个传感器正好可以弥补相互的缺点。短时间用陀螺仪比较准确,长时间用加速度计比较准确;运动时用陀螺仪比较准确,静止时用加速度计比较准确,也就是互补。通过一阶互补滤波,我们滤除加速度计的高频部分,滤除陀螺仪的低频部分,并将这两个数据以一定权重相加,就能得到比较准确的角度了。

你能在其他资料里面看到二阶互补滤波和卡尔曼滤波。相比于这两种算法,一阶互补滤波的优势在于计算量少、收敛速度较快,对性能薄弱的芯片比较友好。虽然没有二阶互补滤波和卡尔曼滤波那么精确,但是对于我们的用途来说还在能接受的范围以内。

下面我们结合代码来说明基于一阶互补滤波的姿态解算的流程。

自定义结构体

为了让代码看起来更加优雅,我们先定义这样一个结构体,并且声明对应的变量,来储存我们需要的数据。

typedef struct{float Roll;//解算所得角度float Pitch;float Yaw;float Roll_a;//加速度计计算得到的角度float Pitch_a;float Roll_g;//陀螺仪计算得到的角速度float Pitch_g;float lastRoll;//上次的解算角度float lastPitch;int offset_gx;//陀螺仪零漂值int offset_gy;int offset_gz;
}IMU;...IMU IMU_Data;

加速度计与陀螺仪的分别解算

在这里我们以小车的Roll角(翻滚角),也就是单车需要保持平衡的那个角度为例,来解释如何通过加速度计与陀螺仪分别计算出角度。额外注意的是,本文的X轴指向小车前方,如下图所示,但别的资料不一定,在查阅其他资料时请多加留心。

加速度计
IMU_Data.Roll_a=atan2(mpu6050_acc_x,mpu6050_acc_z)/(PI/180);

对数学上的推导过程感兴趣的朋友可以参考这篇博客,在这里不展开说明。总之,mpu6050_acc_x与mpu6050_acc_z是我们通过逐飞库提供的mpu6050_get_acc函数读取到的直接数据,通过上面的数学运算,我们得到的是根据加速度计算得的Roll角Roll_a,单位为度。atan2函数定义在math.h标准库中,使用前要先包含这个库。

如果要计算Pitch角(俯仰角),只需要把x改为y即可。遗憾的是,由于原理上的限制,我们无法用加速度计算出Yaw角(航向角)。

陀螺仪
IMU_Data.Roll_g=-(mpu6050_gyro_y)/14.3;

通过这个运算,我们能把MPU6050提供的陀螺仪数据转换成实际的物理数据,单位是度每秒,也就是角速度。我们只需要对角速度进行积分,就能得到角度了,这个处理我们放在一阶互补滤波的函数中。代码中是否要加负号取决于你的传感器芯片,14.3这个数字由陀螺仪的量程得出,如果用逐飞库的mpu6050_gyro_transition函数来转换的话应该就不用关心这个数字了。

同样的,如果要计算Pitch角,只需要把y改为x即可。你甚至可以用Z轴的数据算出Yaw角,不过,就像我们上面提到的,随着时间的推移,误差将不断增大。要弥补这一误差,你可以结合GNSS(全球卫星导航系统)的数据,但这不在本文的讨论范围之内。

一阶互补滤波过程

#define Ka 0.80  //加速度解算权重
#define dt 0.005 //采样间隔(单位:秒)float FOCF(float acc_m,float gyro_m,float* last_angle){float temp_angle;temp_angle=Ka*acc_m+(1-Ka)*(*last_angle+gyro_m*dt);*last_angle=temp_angle;return temp_angle;
}...IMU_Data.Roll=FOCF(IMU_Data.Roll_a,IMU_Data.Roll_g,&IMU_Data.lastRoll);

在分别处理好加速度计与陀螺仪的数据之后,现在要将两个数据互补在一起。我们定义一个名为FOCF的函数,用于处理这一数学过程。这个函数接受处理好的数据和上次解算结果的储存地址作为参数。

首先,我们将陀螺仪解算出的角速度与采样间隔相乘,得到自上次采样以来的角度变化量。通过将上一次解算结果与这个变化量相加,我们就能得到由陀螺仪计算得到的新的Roll角。

接着,我们将加速度解算所得的角度与陀螺仪解算所得的角度按照权重因子进行加权相加,从而得到最终的解算结果。这个权重因子需要根据实际情况进行调整。

在计算完成后,我们更新*last_angle,以备下一次解算使用。最终,将计算得到的角度作为结果返回,你就能在其他函数中读取IMU_Data.Roll,最终保持你的单车的平衡。

Pitch角也是同理。

在解算之前......

不幸的,你接上陀螺仪后发现,即使你不去触动它,它的数据也不为0,这是工艺上不可避免的误差造成的。幸运的是,这个误差在每一次运行过程中变化不大,让我们可以用简单的方法把它的影响降到最小。

现在我们定义一个去除零漂的函数IMU_offset,并在每次单片机启动时调用它。

#define OFFSET_COUNT 200void IMU_offset(){for(int i=0;i<OFFSET_COUNT;i++){system_delay_ms(5);if(mpu6050_gyro_x==mpu6050_gyro_y){i--;}else{IMU_Data.offset_gx+=mpu6050_gyro_x;IMU_Data.offset_gy+=mpu6050_gyro_y;IMU_Data.offset_gz+=mpu6050_gyro_z;}}IMU_Data.offset_gx/=OFFSET_COUNT;IMU_Data.offset_gy/=OFFSET_COUNT;IMU_Data.offset_gz/=OFFSET_COUNT;
}

既然变化不大,我们只需要求其平均值,然后在每次采样时减去它就好了。这个函数就起求平均值这个作用。OFFSET_COUNT是你要采集的数据量,只要取一个恰当的数值即可。system_delay_ms(5)中的5是你规定的采样间隔。

考虑到实际应用中有时会出现杜邦线接触不良的情况,在代码中做了一个简单的判断。当发生接触不良的时候,X轴数据会与Y轴数据相同(通常均为0,但偶有意外),我们就认为数据是无效的。这是在被杜邦线困扰已久之后摸索出的野路子,权当参考。

综上所述

当我们完成了上面所有的代码之后,是时候调用它们了。去零漂的函数要在启动时调用,也就是main函数的开头部分。为了保证我们的采样间隔恒定不变,我们需要将函数放在定时器的中断处理函数中执行。代码分为两个部分:第一个部分你要从MPU6050中读取原始的数据,并将陀螺仪的原始数据减去你计算出的零漂值;第二个部分你要分别处理加速度计与陀螺仪的数据,然后进行一阶互补滤波。

上面就是基于一阶互补滤波的姿态解算的全部过程,希望能对同学们有所帮助。

(感觉这玩意各种意义上都写得好烂......)

这篇关于基于一阶互补滤波的MPU6050姿态解算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/592983

相关文章

Open3D 基于法线的双边滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数: 输出参数: 参数影响: 2.2完整代码 三、实现效果 3.1原始点云 3.2滤波后点云 Open3D点云算法汇总及实战案例汇总的目录地址: Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客 一、概述         基于法线的双边

6.4双边滤波

目录 实验原理 示例代码1 运行结果1 实验代码2 运行结果2 实验原理 双边滤波(Bilateral Filtering)是一种非线性滤波技术,用于图像处理中去除噪声,同时保留边缘和细节。这种滤波器结合了空间邻近性和像素值相似性的双重加权,从而能够在去噪(平滑图像)的同时保留图像的边缘细节。双边滤波器能够在的同时,保持边缘清晰,因此非常适合用于去除噪声和保持图像特征。在Op

数据集 3DPW-开源户外三维人体建模-姿态估计-人体关键点-人体mesh建模 >> DataBall

3DPW 3DPW-开源户外三维人体建模数据集-姿态估计-人体关键点-人体mesh建模 开源户外三维人体数据集 @inproceedings{vonMarcard2018, title = {Recovering Accurate 3D Human Pose in The Wild Using IMUs and a Moving Camera}, author = {von Marc

6.3中值滤波

目录 实验原理 示例代码1 运行结果1 示例代码2 运行结果2 实验原理 中值滤波(Median Filtering)是一种非线性滤波技术,常用于图像处理中去除噪声,特别是在保留边缘的同时减少椒盐噪声(salt-and-pepper noise)。OpenCV中的cv::medianBlur函数可以实现中值滤波。 函数原型 void medianBlur( InputAr

数据集 Ubody人体smplx三维建模mesh-姿态估计 >> DataBall

Ubody开源人体三维源数据集-smplx-三维建模-姿态估计 UBody:一个连接全身网格恢复和真实生活场景的上半身数据集,旨在拟合全身网格恢复任务与现实场景之间的差距。 UBody包含来自多人的现实场景的1051k张高质量图像,这些图像拥有2D全身关键点、3D SMPLX模型。 UBody由国际数字经济学院(IDEA)提供。 (UBody was used for mesh r

【控制算法 数据处理】一阶滤波算法

简单介绍: 一阶滤波算法是比较常用的滤波算法,它的滤波结果=a*本次采样值+(1-a)*上次滤波结果,其中,a为0~1之间的数。一阶滤波相当于是将新的采样值与上次的滤波结果计算一个加权平均值。a的取值决定了算法的灵敏度,a越大,新采集的值占的权重越大,算法越灵敏,但平顺性差;相反,a越小,新采集的值占的权重越小,灵敏度差,但平顺性好。优点是对周期干扰有良好的抑制作用,适用于波动频率比较高的场合,它

RSSI滤波方法

文章目录 一、均值滤波二、递推平均滤波三、中位值滤波四、狄克逊检验法滤波五、高斯滤波六、速度滤波七、卡尔曼滤波 一、均值滤波 均值滤波是指节点接收到另一节点的多个RSSI值之后,求其算式平均值,作为测试结果 R S S I ‾ = 1 n ∙ ∑ i = 1 n R S S I i \overline{RSSI} = \frac {1}{n} \bullet \sum_{i=1

CUDAPCL ROR点云滤波

文章目录 一、简介二、实现代码三、实现效果参考资料 一、简介 该方法的具体原理为输入的点云中每一个点设定一个范围(半径为r的圆),如果在该范围内没有达到某一个设定的点数值,则该数据点将会被删除,重复上述此过程直到最后一个数据点,即完成该滤波过程。 二、实现代码 ROR.cuh #ifndef ROR_GPU_CUH#define ROR_GPU_CU

matlab频域滤波

步骤: (1)计算原图像f(x,y)的DFT, (2) 讲频谱的零频点移动到频谱图的中心位置; (3)计算滤波器函数H(U,V)与F(U,V)的乘积G(U,V); (4)讲频谱G(U,V)的零频点移回到频谱图的坐上角。 (5)计算(4)的结果的傅立叶反变换g(x,y); (6)取g(x,y)的实部作为最终的滤波后的结果图像。   代码: 大家别激动的啦   代

工控常用滤波方法(限幅+中值+算术平均+滑动平均)

工控常用滤波方法 简介限幅滤波法中值滤波法算术平均滤波法滑动平均滤波 简介 在实际的工程应用中,实际反馈的信号由于是通过电压及电流转换而来的数字量信号,在现场可能会受到比较大的干扰问题,这样的扰动会影响控制系统的输出精度,也会使其产生比较大的偏差。 故在实际应用中,通常不会直接将反馈的信号作为信号输入,会在之前加一个滤波器以使数据更平滑,在此,非常有必要引入数字滤波的概念。