当前位置:   article > 正文

mpu6050和mpu9250姿态解算_mpu9250 mpu6050

mpu9250 mpu6050

在正确读出陀螺仪,加速度计和磁力计原始数据的基础上,使用如下的代码可以实现姿态解算

如果使用的是mpu6050的话,将磁力计的传入参数置为0即可,在姿态解算函数内部会自动忽略,不会加入对磁力计的处理

首先定义一个结构体用于存储读取出的陀螺仪,加速度计和磁力计值

  1. typedef struct
  2. {
  3. float x;
  4. float y;
  5. float z;
  6. }Axis3f

 下面是姿态解算的核心代码:

  1. #define DEG2RAD 0.017453293f /* 度转弧度 π/180 */
  2. #define RAD2DEG 57.29578f /* 弧度转度 180/π */
  3. //数值越大越相信加速度计
  4. float A_Kp = 0.4f; /*比例增益*/
  5. float A_Ki = 0.001f; /*积分增益*/
  6. float A_exInt = 0.0f;
  7. float A_eyInt = 0.0f;
  8. float A_ezInt = 0.0f; /*积分误差累计*/
  9. //数值越大越相信磁力计
  10. float M_Kp = 1.0f; /*比例增益*/
  11. float M_Ki = 0.001f; /*积分增益*/
  12. float M_exInt = 0.0f;
  13. float M_eyInt = 0.0f;
  14. float M_ezInt = 0.0f; /*积分误差累计*/
  15. static float q0 = 1.0f; /*四元数*/
  16. static float q1 = 0.0f;
  17. static float q2 = 0.0f;
  18. static float q3 = 0.0f;
  19. static float rMat[3][3];/*旋转矩阵*/
  20. /*快速开平方求倒*/
  21. float invSqrt(float x)
  22. {
  23. float halfx = 0.5f * x;
  24. float y = x;
  25. long i = *(long*)&y;
  26. i = 0x5f3759df - (i>>1);
  27. y = *(float*)&i;
  28. y = y * (1.5f - (halfx * y * y));
  29. return y;
  30. }
  31. /*计算旋转矩阵*/
  32. void imuComputeRotationMatrix(void)
  33. {
  34. float q1q1 = q1 * q1;
  35. float q2q2 = q2 * q2;
  36. float q3q3 = q3 * q3;
  37. float q0q1 = q0 * q1;
  38. float q0q2 = q0 * q2;
  39. float q0q3 = q0 * q3;
  40. float q1q2 = q1 * q2;
  41. float q1q3 = q1 * q3;
  42. float q2q3 = q2 * q3;
  43. rMat[0][0] = 1.0f - 2.0f * q2q2 - 2.0f * q3q3;
  44. rMat[0][1] = 2.0f * (q1q2 + -q0q3);
  45. rMat[0][2] = 2.0f * (q1q3 - -q0q2);
  46. rMat[1][0] = 2.0f * (q1q2 - -q0q3);
  47. rMat[1][1] = 1.0f - 2.0f * q1q1 - 2.0f * q3q3;
  48. rMat[1][2] = 2.0f * (q2q3 + -q0q1);
  49. rMat[2][0] = 2.0f * (q1q3 + -q0q2);
  50. rMat[2][1] = 2.0f * (q2q3 - -q0q1);
  51. rMat[2][2] = 1.0f - 2.0f * q1q1 - 2.0f * q2q2;
  52. }
  53. //传入参数分别为加速度计,陀螺仪和磁力计值,Angle用于存放解算后的角度值,dt为调用此函数的时间间隔
  54. void imuUpdate(Axis3f acc, Axis3f gyro, Axis3f mag, Axis3f *Angle , float dt) /*数据融合 互补滤波*/
  55. {
  56. float normalise;
  57. float ex, ey, ez;
  58. float halfT = 0.5f * dt;
  59. float accBuf[3] = {0.f};
  60. Axis3f tempacc = acc;
  61. Axis3f tempmag = {0};
  62. Axis3f tempmag_2 = {0};
  63. gyro.x = gyro.x * DEG2RAD; /* 度转弧度 */
  64. gyro.y = gyro.y * DEG2RAD;
  65. gyro.z = gyro.z * DEG2RAD;
  66. /* 加速度计输出有效时,利用加速度计补偿陀螺仪*/
  67. if((acc.x != 0.0f) || (acc.y != 0.0f) || (acc.z != 0.0f))
  68. {
  69. /*单位化加速计测量值*/
  70. normalise = invSqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z);
  71. acc.x *= normalise;
  72. acc.y *= normalise;
  73. acc.z *= normalise;
  74. /*加速计读取的方向与重力加速计方向的差值,用向量叉乘计算*/
  75. ex = (acc.y * rMat[2][2] - acc.z * rMat[2][1]);
  76. ey = (acc.z * rMat[2][0] - acc.x * rMat[2][2]);
  77. ez = (acc.x * rMat[2][1] - acc.y * rMat[2][0]);
  78. /*误差累计,与积分常数相乘*/
  79. A_exInt += A_Ki * ex * dt ;
  80. A_eyInt += A_Ki * ey * dt ;
  81. A_ezInt += A_Ki * ez * dt ;
  82. /*用叉积误差来做PI修正陀螺零偏,即抵消陀螺读数中的偏移量*/
  83. gyro.x += A_Kp * ex + A_exInt;
  84. gyro.y += A_Kp * ey + A_eyInt;
  85. gyro.z += A_Kp * ez + A_ezInt;
  86. }
  87. /* 磁力计输出有效时,利用磁力计补偿陀螺仪*/
  88. if((mag.x != 0.0f) || (mag.y != 0.0f) || (mag.z != 0.0f))
  89. {
  90. /*单位化磁力计测量值*/
  91. normalise = invSqrt(mag.x * mag.x + mag.y * mag.y + mag.z * mag.z);
  92. mag.x *= normalise;
  93. mag.y *= normalise;
  94. mag.z *= normalise;
  95. /*磁力计从机体到地球*/
  96. tempmag.x = rMat[0][0] * mag.x + rMat[0][1] * mag.y + rMat[0][2] * mag.z;
  97. tempmag.y = rMat[1][0] * mag.x + rMat[1][1] * mag.y + rMat[1][2] * mag.z;
  98. tempmag.z = rMat[2][0] * mag.x + rMat[2][1] * mag.y + rMat[2][2] * mag.z;
  99. /*让导航坐标系中X轴指向正北方*/
  100. tempmag.x = sqrt(tempmag.x * tempmag.x + tempmag.y * tempmag.y);
  101. tempmag.y = 0;
  102. /*磁力计从地球到机体*/
  103. tempmag_2.x = rMat[0][0] * tempmag.x + rMat[1][0] * tempmag.y + rMat[2][0] * tempmag.z;
  104. tempmag_2.y = rMat[0][1] * tempmag.x + rMat[1][1] * tempmag.y + rMat[2][1] * tempmag.z;
  105. tempmag_2.z = rMat[0][2] * tempmag.x + rMat[1][2] * tempmag.y + rMat[2][2] * tempmag.z;
  106. /*磁力计转换后的方向与磁力计方向的差值,用向量叉乘计算*/
  107. ex = (mag.y * tempmag_2.z - mag.z * tempmag_2.y);
  108. ey = (mag.z * tempmag_2.x - mag.x * tempmag_2.z);
  109. ez = (mag.x * tempmag_2.y - mag.y * tempmag_2.x);
  110. /*误差累计,与积分常数相乘*/
  111. M_exInt += M_Ki * ex * dt ;
  112. M_eyInt += M_Ki * ey * dt ;
  113. M_ezInt += M_Ki * ez * dt ;
  114. /*用叉积误差来做PI修正陀螺零偏,即抵消陀螺读数中的偏移量*/
  115. gyro.x += M_Kp * ex + M_exInt;
  116. gyro.y += M_Kp * ey + M_eyInt;
  117. gyro.z += M_Kp * ez + M_ezInt;
  118. }
  119. /* 一阶近似算法,四元数运动学方程的离散化形式和积分 */
  120. float q0Last = q0;
  121. float q1Last = q1;
  122. float q2Last = q2;
  123. float q3Last = q3;
  124. q0 += (-q1Last * gyro.x - q2Last * gyro.y - q3Last * gyro.z) * halfT;
  125. q1 += ( q0Last * gyro.x + q2Last * gyro.z - q3Last * gyro.y) * halfT;
  126. q2 += ( q0Last * gyro.y - q1Last * gyro.z + q3Last * gyro.x) * halfT;
  127. q3 += ( q0Last * gyro.z + q1Last * gyro.y - q2Last * gyro.x) * halfT;
  128. /*单位化四元数*/
  129. normalise = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
  130. q0 *= normalise;
  131. q1 *= normalise;
  132. q2 *= normalise;
  133. q3 *= normalise;
  134. imuComputeRotationMatrix(); /*计算旋转矩阵*/
  135. /*计算roll pitch yaw 欧拉角*/
  136. Angle->x = -asinf(rMat[2][0]) * RAD2DEG;
  137. Angle->y = atan2f(rMat[2][1], rMat[2][2]) * RAD2DEG;
  138. Angle->z = atan2f(rMat[1][0], rMat[0][0]) * RAD2DEG;
  139. }

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

闽ICP备14008679号