当前位置:   article > 正文

卡尔曼滤波在陀螺仪角度获取中的运用(最大可能解决MPU6050零漂问题)_陀螺仪零漂怎么解决

陀螺仪零漂怎么解决

前言:相信使用过MPU6050的人都会发现此陀螺仪(角度传感器)存在零点漂移的现象。我在网上查找了好多解决零点漂移的方法,大多数网友提供的方法都是对陀螺仪采集到的数据进行一些数据的处理,包括一些滤波算法的运用。在经过长时间的尝试后,我觉得使用卡尔曼滤波算法效果比较好,因此我将通过此文来记录卡尔曼滤波算法在解决陀螺仪零漂问题的运用。

同时为了方便读者移植,我会在文章末尾附上工程链接,需要的读者请自取。有关陀螺仪的工作原理驱动代码,读者可以参考这篇文章:STM32MPU6050角度的读取(STM32驱动MPU6050)-CSDN博客

废话不多说,直接对相关代码进行讲解:

filter.c

  1. #include "filter.h"
  2. /**************************************************************************
  3. Function: Simple Kalman filter
  4. Input : acceleration、angular velocity
  5. Output : none
  6. 函数功能:获取x轴角度简易卡尔曼滤波
  7. 入口参数:加速度获取的角度、角速度
  8. 返回 值:x轴角速度
  9. **************************************************************************/
  10. float dt=0.005; //5ms进行一次滤波
  11. float Kalman_Filter_x(float Accel,float Gyro)
  12. {
  13. static float angle_dot;
  14. static float angle;
  15. float Q_angle=0.001; // 过程噪声的协方差
  16. float Q_gyro=0.003; //0.003 过程噪声的协方差 过程噪声的协方差为一个一行两列矩阵
  17. float R_angle=0.5; // 测量噪声的协方差 既测量偏差
  18. char C_0 = 1;
  19. static float Q_bias, Angle_err;
  20. static float PCt_0, PCt_1, E;
  21. static float K_0, K_1, t_0, t_1;
  22. static float Pdot[4] ={0,0,0,0};
  23. static float PP[2][2] = { { 1, 0 },{ 0, 1 } };
  24. angle+=(Gyro - Q_bias) * dt; //先验估计
  25. Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分
  26. Pdot[1]=-PP[1][1];
  27. Pdot[2]=-PP[1][1];
  28. Pdot[3]=Q_gyro;
  29. PP[0][0] += Pdot[0] * dt; // Pk-先验估计误差协方差微分的积分
  30. PP[0][1] += Pdot[1] * dt; // =先验估计误差协方差
  31. PP[1][0] += Pdot[2] * dt;
  32. PP[1][1] += Pdot[3] * dt;
  33. Angle_err = Accel - angle; //zk-先验估计
  34. PCt_0 = C_0 * PP[0][0];
  35. PCt_1 = C_0 * PP[1][0];
  36. E = R_angle + C_0 * PCt_0;
  37. K_0 = PCt_0 / E;
  38. K_1 = PCt_1 / E;
  39. t_0 = PCt_0;
  40. t_1 = C_0 * PP[0][1];
  41. PP[0][0] -= K_0 * t_0; //后验估计误差协方差
  42. PP[0][1] -= K_0 * t_1;
  43. PP[1][0] -= K_1 * t_0;
  44. PP[1][1] -= K_1 * t_1;
  45. angle += K_0 * Angle_err; //后验估计
  46. Q_bias += K_1 * Angle_err; //后验估计
  47. angle_dot = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
  48. return angle;
  49. }
  50. /**************************************************************************
  51. Function: First order complementary filtering
  52. Input : acceleration、angular velocity
  53. Output : none
  54. 函数功能:一阶互补滤波
  55. 入口参数:加速度获取的角度、角速度
  56. 返回 值:x轴角速度
  57. **************************************************************************/
  58. float Complementary_Filter_x(float angle_m, float gyro_m)
  59. {
  60. static float angle;
  61. float K1 =0.02;
  62. angle = K1 * angle_m+ (1-K1) * (angle + gyro_m * dt);
  63. return angle;
  64. }
  65. /**************************************************************************
  66. Function: Simple Kalman filter
  67. Input : acceleration、angular velocity
  68. Output : none
  69. 函数功能:获取y轴角度简易卡尔曼滤波
  70. 入口参数:加速度获取的角度、角速度
  71. 返回 值:y轴角速度
  72. **************************************************************************/
  73. float Kalman_Filter_y(float Accel,float Gyro)
  74. {
  75. static float angle_dot;
  76. static float angle;
  77. float Q_angle=0.001; // 过程噪声的协方差
  78. float Q_gyro=0.003; //0.003 过程噪声的协方差 过程噪声的协方差为一个一行两列矩阵
  79. float R_angle=0.5; // 测量噪声的协方差 既测量偏差
  80. char C_0 = 1;
  81. static float Q_bias, Angle_err;
  82. static float PCt_0, PCt_1, E;
  83. static float K_0, K_1, t_0, t_1;
  84. static float Pdot[4] ={0,0,0,0};
  85. static float PP[2][2] = { { 1, 0 },{ 0, 1 } };
  86. angle+=(Gyro - Q_bias) * dt; //先验估计
  87. Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分
  88. Pdot[1]=-PP[1][1];
  89. Pdot[2]=-PP[1][1];
  90. Pdot[3]=Q_gyro;
  91. PP[0][0] += Pdot[0] * dt; // Pk-先验估计误差协方差微分的积分
  92. PP[0][1] += Pdot[1] * dt; // =先验估计误差协方差
  93. PP[1][0] += Pdot[2] * dt;
  94. PP[1][1] += Pdot[3] * dt;
  95. Angle_err = Accel - angle; //zk-先验估计
  96. PCt_0 = C_0 * PP[0][0];
  97. PCt_1 = C_0 * PP[1][0];
  98. E = R_angle + C_0 * PCt_0;
  99. K_0 = PCt_0 / E;
  100. K_1 = PCt_1 / E;
  101. t_0 = PCt_0;
  102. t_1 = C_0 * PP[0][1];
  103. PP[0][0] -= K_0 * t_0; //后验估计误差协方差
  104. PP[0][1] -= K_0 * t_1;
  105. PP[1][0] -= K_1 * t_0;
  106. PP[1][1] -= K_1 * t_1;
  107. angle += K_0 * Angle_err; //后验估计
  108. Q_bias += K_1 * Angle_err; //后验估计
  109. angle_dot = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
  110. return angle;
  111. }
  112. /**************************************************************************
  113. Function: First order complementary filtering
  114. Input : acceleration、angular velocity
  115. Output : none
  116. 函数功能:一阶互补滤波
  117. 入口参数:加速度获取的角度、角速度
  118. 返回 值:y轴角速度
  119. **************************************************************************/
  120. float Complementary_Filter_y(float angle_m, float gyro_m)
  121. {
  122. static float angle;
  123. float K1 =0.02;
  124. angle = K1 * angle_m+ (1-K1) * (angle + gyro_m * dt);
  125. return angle;
  126. }

filter.h

  1. #ifndef __FILTER_H
  2. #define __FILTER_H
  3. float Kalman_Filter_x(float Accel,float Gyro);
  4. float Complementary_Filter_x(float angle_m, float gyro_m);
  5. float Kalman_Filter_y(float Accel,float Gyro);
  6. float Complementary_Filter_y(float angle_m, float gyro_m);
  7. #endif

以上的卡尔曼滤波算法不仅适用于陀螺仪角度数据的处理,同时对于其他的传感器数据处理也依然适用。

这是此篇的陀螺仪卡尔曼滤波算法移植的完整工程:

链接:https://pan.baidu.com/s/19RWpXG7qykLwCFcjoLgLIQ?pwd=zxf1 
提取码:zxf1 
--来自百度网盘超级会员V3的分享

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/568335
推荐阅读
相关标签
  

闽ICP备14008679号