[其他ST产品] MPU6050姿态解算2-欧拉角&旋转矩阵

[复制链接]
2160|29
 楼主| 狗啃模拟 发表于 2022-9-27 23:29 | 显示全部楼层
姿态融合

由上面的分析可知,加速度计在静止时刻,根据感受到的重力加速度,可以计算出roll和pitch角,并且角度计算只与当前姿态有关。而陀螺仪是对时间间隔内的角速度积分,得到每一次的角度变换量,累加到上一次的姿态角上,得到新的姿态角,陀螺仪可以计算roll、pitch、yaw三个角。

实际上,加速度仅在静止时刻可以得到较准确的姿态,而陀螺仪仅对转动时的姿态变化敏感,且陀螺仪若本身存在误差,则经过连续的时间积分,误差会不断增大。因此,需要结合两者计算的姿态,进行互补融合。当然,这里只能对roll和pitch融合,因为加速度计没有得到yaw。
75395633316a9796eb.png
 楼主| 狗啃模拟 发表于 2022-9-27 23:30 | 显示全部楼层
K为比例系数,需要根据实际来调整,如选用0.4。
 楼主| 狗啃模拟 发表于 2022-9-27 23:33 | 显示全部楼层
MATLAB公式推导

上面的一些推导计算过程,可用MATLAB来辅助计算,防止手工计算出错:
 楼主| 狗啃模拟 发表于 2022-9-27 23:34 | 显示全部楼层
先定义3个旋转矩阵Y
  1. % 旋转顺序:Z,Y,X(从大地坐标系到IMU坐标系)

  2. % 定义一些符号 r=row p=pitch y=yaw
  3. syms r p y

  4. % 3个旋转矩阵(坐标系旋转,注意负号的位置!)
  5. M_x = [  1,       0,      0;
  6.          0,  cos(r), sin(r);
  7.          0, -sin(r), cos(r)];
  8.   
  9. M_y = [cos(p),   0, -sin(p);
  10.             0,   1,       0;
  11.        sin(p),   0,  cos(p)];

  12. M_z = [ cos(y),  sin(y),  0;
  13.        -sin(y),  cos(y),  0;
  14.             0,       0,   1];
 楼主| 狗啃模拟 发表于 2022-9-27 23:35 | 显示全部楼层
推导陀螺仪的变换矩阵
  1. %% 推导陀螺仪的变换矩阵

  2. %定义一些符号 drdt dpdt dydt 指的是分别对 roll pitch yaw求导,也就是角速度
  3. syms drdt dpdt dydt

  4. % 绕x轴转动 row 的角速度
  5. dr_t = [drdt;
  6.            0;
  7.            0];
  8.       
  9. % 绕y轴转动 pitch 的角速度
  10. dp_t = [   0;
  11.         dpdt;
  12.            0];
  13.       
  14. % 绕z轴转动 yaw 的角速度
  15. dy_t = [   0;
  16.            0;
  17.         dydt];

  18. % [矩阵X*矩阵Y*yaw角速度(绕Z)] + [矩阵X*pitch角速度(绕Y)] + [roll角速度(绕X)]
  19. % IMU_gyro实际就是IMU测得的3个陀螺仪数据
  20. IMU_gyro = M_x*M_y*dy_t + M_x*dp_t + dr_t;
  21. fprintf('M_x*M_y*dy_t + M_x*dp_t + dr_t=\r\n')
  22. disp(IMU_gyro)
  23. % roll pitch yaw角速度组成的列向量,这个实际是要求的大地坐标系的3个角速度
  24. rpy_t = [drdt;
  25.          dpdt;
  26.          dydt];

  27. %手动分解IMU_gyro为矩阵M_gyro与列向量rpy_t相乘的形式
  28. %根据IMU_gyro写出M_gyro,该矩阵将大地坐标系的角速度转换为IMU坐标系
  29. M_gyro = [ 1,     0,       -sin(p);
  30.            0, cos(r),cos(p)*sin(r);
  31.            0,-sin(r),cos(p)*cos(r)];
  32. %验证一下
  33. if M_gyro * rpy_t==IMU_gyro
  34.     fprintf('M_gyro is true\r\n');
  35. else
  36.     fprintf('M_gyro is false\r\n');
  37. end
  38. fprintf('M_gyro=\r\n')
  39. disp(M_gyro)

  40. % 对M_gyro求逆矩阵,用于将IMU坐标系的陀螺仪角速度值转换到大地坐标系
  41. M_gyro_inv = inv(M_gyro);
  42. fprintf('M_gyro_inv=\r\n')
  43. disp(M_gyro_inv)

  44. % matlab求解的逆矩阵需要在再手工化简
  45. M_gyro_inv_ =[ 1, (sin(p)*sin(r))/cos(p), (cos(r)*sin(p))/cos(p);
  46.                0,                 cos(r),                -sin(r);
  47.                0,          sin(r)/cos(p),          cos(r)/cos(p)];
  48. % 验证一下,M_gyro_inv_ * M_gyro_inv应该是单位矩阵
  49. fprintf('M_gyro_inv_ * M_gyro=\r\n')
  50. disp(M_gyro_inv_ * M_gyro)
  51. fprintf('M_gyro_inv_ =\r\n')
  52. disp(M_gyro_inv_)
 楼主| 狗啃模拟 发表于 2022-9-27 23:35 | 显示全部楼层
运行后的输出结果:
  1. M_x*M_y*dy_t + M_x*dp_t + dr_t=

  2.                drdt - dydt*sin(p)
  3. dpdt*cos(r) + dydt*cos(p)*sin(r)
  4. dydt*cos(p)*cos(r) - dpdt*sin(r)

  5. M_gyro is true

  6. M_gyro=

  7. [ 1,       0,       -sin(p)]
  8. [ 0,  cos(r), cos(p)*sin(r)]
  9. [ 0, -sin(r), cos(p)*cos(r)]

  10. M_gyro_inv=

  11. [ 1, (sin(p)*sin(r))/(cos(p)*cos(r)^2 + cos(p)*sin(r)^2), (cos(r)*sin(p))/(cos(p)*cos(r)^2 + cos(p)*sin(r)^2)]
  12. [ 0,                        cos(r)/(cos(r)^2 + sin(r)^2),                       -sin(r)/(cos(r)^2 + sin(r)^2)]
  13. [ 0,          sin(r)/(cos(p)*cos(r)^2 + cos(p)*sin(r)^2),          cos(r)/(cos(p)*cos(r)^2 + cos(p)*sin(r)^2)]

  14. M_gyro_inv_ * M_gyro=

  15. [ 1,                   0, cos(r)^2*sin(p) - sin(p) + sin(p)*sin(r)^2]
  16. [ 0, cos(r)^2 + sin(r)^2,                                          0]
  17. [ 0,                   0,                        cos(r)^2 + sin(r)^2]

  18. M_gyro_inv_ =

  19. [ 1, (sin(p)*sin(r))/cos(p), (cos(r)*sin(p))/cos(p)]
  20. [ 0,                 cos(r),                -sin(r)]
  21. [ 0,          sin(r)/cos(p),          cos(r)/cos(p)]
 楼主| 狗啃模拟 发表于 2022-9-27 23:36 | 显示全部楼层
程序先计算出了M_x*M_y*dy_t + M_x*dp_t + dr_t,然后手工分解为M_gyro与rpy_t相乘的形式,最后求得M_gyro的逆矩阵M_gyro_inv_,即得到用于将IMU坐标系的陀螺仪角速度值转换到大地坐标系的旋转矩阵
 楼主| 狗啃模拟 发表于 2022-9-27 23:43 | 显示全部楼层
推导加速度计的变换矩阵
  1. %% 推导加速度计的变换矩阵

  2. M_acc=M_x*M_y*M_z;
  3. fprintf('M_acc=\r\n')
  4. disp(M_acc)

  5. %重力向量
  6. syms g
  7. acc = [0;
  8.        0;
  9.        g];
  10. IMU_acc=M_acc*acc;
  11. fprintf('IMU_acc=\r\n')
  12. disp(IMU_acc)

 楼主| 狗啃模拟 发表于 2022-9-27 23:48 | 显示全部楼层
运行后的输出结果:
  1. M_acc=

  2. [                        cos(p)*cos(y),                        cos(p)*sin(y),       -sin(p)]
  3. [ cos(y)*sin(p)*sin(r) - cos(r)*sin(y), cos(r)*cos(y) + sin(p)*sin(r)*sin(y), cos(p)*sin(r)]
  4. [ sin(r)*sin(y) + cos(r)*cos(y)*sin(p), cos(r)*sin(p)*sin(y) - cos(y)*sin(r), cos(p)*cos(r)]

  5. IMU_acc=

  6.        -g*sin(p)
  7. g*cos(p)*sin(r)
  8. g*cos(p)*cos(r)
  9. [em:24:]
 楼主| 狗啃模拟 发表于 2022-9-27 23:48 | 显示全部楼层
计算得到的IMU_acc即是加速度计感受到的重力加速度向量在IMU最终姿态所在坐标系中的坐标。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部