当前位置:   article > 正文

esp32 mpu6050 卡尔曼滤波程序_mpu6050 姿态融合 esp32卡尔曼滤波程序

mpu6050 姿态融合 esp32卡尔曼滤波程序
  1. #include <Adafruit_MPU6050.h>
  2. #include <Adafruit_Sensor.h>
  3. #include <Wire.h>
  4. Adafruit_MPU6050 mpu;
  5. /*计算偏移量*/
  6. float i; //计算偏移量时的循环次数
  7. float ax_offset = 0, ay_offset = 0; //x,y轴的加速度偏移量
  8. float gx_offset = 0, gy_offset = 0; //x,y轴的角速度偏移量
  9. /*参数*/
  10. float rad2deg = 57.29578; //弧度到角度的换算系数
  11. float roll_v = 0, pitch_v = 0; //换算到x,y轴上的角速度
  12. /*定义微分时间*/
  13. float now = 0, lasttime = 0, dt = 0; //定义微分时间
  14. /*三个状态,先验状态,观测状态,最优估计状态*/
  15. float gyro_roll = 0, gyro_pitch = 0; //陀螺仪积分计算出的角度,先验状态
  16. float acc_roll = 0, acc_pitch = 0; //加速度计观测出的角度,观测状态
  17. float k_roll = 0, k_pitch = 0; //卡尔曼滤波后估计出最优角度,最优估计状态
  18. /*误差协方差矩阵P*/
  19. float e_P[2][2] ={{1,0},{0,1}}; //误差协方差矩阵,这里的e_P既是先验估计的P,也是最后更新的P
  20. /*卡尔曼增益K*/
  21. float k_k[2][2] ={{0,0},{0,0}}; //这里的卡尔曼增益矩阵K是一个2X2的方阵
  22. void setup(void) {
  23. /*打开串口和实现I2C通信*/
  24. Wire.begin(23, 5);//SDA->23,SCL->5,可以根据情况自行修改
  25. //打开串口
  26. Serial.begin(115200);//串口波特率
  27. delay(100);
  28. /*判断是否连接到MPU6050并且初始化*/
  29. while (!mpu.begin())
  30. {
  31. Serial.println("Failed to find MPU6050 chip");
  32. }
  33. Serial.println("MPU6050 Found!");
  34. mpu.setAccelerometerRange(MPU6050_RANGE_2_G);//加速度量程±2G
  35. mpu.setGyroRange(MPU6050_RANGE_250_DEG);//角速度量程±250°/s
  36. mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);//采样频率21Hz
  37. //计算偏移量
  38. for (i = 1; i <= 2000; i++) {
  39. sensors_event_t a, g, temp;
  40. mpu.getEvent(&a, &g, &temp);//获取加速度、角速度、温度
  41. ax_offset = ax_offset + a.acceleration.x;//计算x轴加速度的偏移总量
  42. ay_offset = ay_offset + a.acceleration.y;//计算y轴加速度的偏移总量
  43. gx_offset = gx_offset + g.gyro.x;
  44. gy_offset = gy_offset + g.gyro.y;
  45. }
  46. ax_offset = ax_offset / 2000; //计算x轴加速度的偏移量
  47. ay_offset = ay_offset / 2000; //计算y轴加速度的偏移量
  48. gx_offset = gx_offset / 2000; //计算x轴角速度的偏移量
  49. gy_offset = gy_offset / 2000; //计算y轴角速度的偏移量
  50. delay(100);
  51. }
  52. void loop() {
  53. /*计算微分时间*/
  54. now = millis(); //当前时间(ms)
  55. dt = (now - lasttime) / 1000.0; //微分时间(s)
  56. lasttime = now; //上一次采样时间(ms)
  57. /*获取角速度和加速度 */
  58. sensors_event_t a, g, temp;
  59. mpu.getEvent(&a, &g, &temp);//获取加速度、角速度、温度
  60. /*step1:计算先验状态*/
  61. /*计算x,y轴上的角速度*/
  62. roll_v = (g.gyro.x-gx_offset) + ((sin(k_pitch)*sin(k_roll))/cos(k_pitch))*(g.gyro.y-gy_offset) + ((sin(k_pitch)*cos(k_roll))/cos(k_pitch))*g.gyro.z;//roll轴的角速度
  63. pitch_v = cos(k_roll)*(g.gyro.y-gy_offset) - sin(k_roll)*g.gyro.z;//pitch轴的角速度
  64. gyro_roll = k_roll + dt*roll_v;//先验roll角度
  65. gyro_pitch = k_pitch + dt*pitch_v;//先验pitch角度
  66. /*step2:计算先验误差协方差矩阵P*/
  67. e_P[0][0] = e_P[0][0] + 0.0025;//这里的Q矩阵是一个对角阵且对角元均为0.0025
  68. e_P[0][1] = e_P[0][1] + 0;
  69. e_P[1][0] = e_P[1][0] + 0;
  70. e_P[1][1] = e_P[1][1] + 0.0025;
  71. /*step3:更新卡尔曼增益K*/
  72. k_k[0][0] = e_P[0][0]/(e_P[0][0]+0.3);
  73. k_k[0][1] = 0;
  74. k_k[1][0] = 0;
  75. k_k[1][1] = e_P[1][1]/(e_P[1][1]+0.3);
  76. /*step4:计算最优估计状态*/
  77. /*观测状态*/
  78. //roll角度
  79. acc_roll = atan((a.acceleration.y - ay_offset) / (a.acceleration.z))*rad2deg;
  80. //pitch角度
  81. acc_pitch = -1*atan((a.acceleration.x - ax_offset) / sqrt(sq(a.acceleration.y - ay_offset) + sq(a.acceleration.z)))*rad2deg;
  82. /*最优估计状态*/
  83. k_roll = gyro_roll + k_k[0][0]*(acc_roll - gyro_roll);
  84. k_pitch = gyro_pitch + k_k[1][1]*(acc_pitch - gyro_pitch);
  85. /*step5:更新协方差矩阵P*/
  86. e_P[0][0] = (1 - k_k[0][0])*e_P[0][0];
  87. e_P[0][1] = 0;
  88. e_P[1][0] = 0;
  89. e_P[1][1] = (1 - k_k[1][1])*e_P[1][1];
  90. //打印角度
  91. Serial.print("roll: ");
  92. Serial.print(k_roll);
  93. Serial.print(",");
  94. Serial.print("pitch: ");
  95. Serial.println(k_pitch);
  96. //姿态可视化 使用Processing展示姿态
  97. // Serial.print(k_roll);
  98. // Serial.print("/");
  99. // Serial.println(k_pitch);
  100. }

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

闽ICP备14008679号