发新帖我要提问
12
返回列表
打印
[其他ST产品]

MPU6050姿态解算2-欧拉角&旋转矩阵

[复制链接]
楼主: 狗啃模拟
手机看帖
扫描二维码
随时随地手机跟帖
21
狗啃模拟|  楼主 | 2022-9-27 23:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
姿态融合

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

实际上,加速度仅在静止时刻可以得到较准确的姿态,而陀螺仪仅对转动时的姿态变化敏感,且陀螺仪若本身存在误差,则经过连续的时间积分,误差会不断增大。因此,需要结合两者计算的姿态,进行互补融合。当然,这里只能对roll和pitch融合,因为加速度计没有得到yaw。

使用特权

评论回复
22
狗啃模拟|  楼主 | 2022-9-27 23:30 | 只看该作者
K为比例系数,需要根据实际来调整,如选用0.4。

使用特权

评论回复
23
狗啃模拟|  楼主 | 2022-9-27 23:33 | 只看该作者
MATLAB公式推导

上面的一些推导计算过程,可用MATLAB来辅助计算,防止手工计算出错:

使用特权

评论回复
24
狗啃模拟|  楼主 | 2022-9-27 23:34 | 只看该作者
先定义3个旋转矩阵Y
% 旋转顺序:Z,Y,X(从大地坐标系到IMU坐标系)

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

% 3个旋转矩阵(坐标系旋转,注意负号的位置!)
M_x = [  1,       0,      0;
         0,  cos(r), sin(r);
         0, -sin(r), cos(r)];
  
M_y = [cos(p),   0, -sin(p);
            0,   1,       0;
       sin(p),   0,  cos(p)];

M_z = [ cos(y),  sin(y),  0;
       -sin(y),  cos(y),  0;
            0,       0,   1];

使用特权

评论回复
25
狗啃模拟|  楼主 | 2022-9-27 23:35 | 只看该作者
推导陀螺仪的变换矩阵
%% 推导陀螺仪的变换矩阵

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

% 绕x轴转动 row 的角速度
dr_t = [drdt;
           0;
           0];
      
% 绕y轴转动 pitch 的角速度
dp_t = [   0;
        dpdt;
           0];
      
% 绕z轴转动 yaw 的角速度
dy_t = [   0;
           0;
        dydt];

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

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

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

% matlab求解的逆矩阵需要在再手工化简
M_gyro_inv_ =[ 1, (sin(p)*sin(r))/cos(p), (cos(r)*sin(p))/cos(p);
               0,                 cos(r),                -sin(r);
               0,          sin(r)/cos(p),          cos(r)/cos(p)];
% 验证一下,M_gyro_inv_ * M_gyro_inv应该是单位矩阵
fprintf('M_gyro_inv_ * M_gyro=\r\n')
disp(M_gyro_inv_ * M_gyro)
fprintf('M_gyro_inv_ =\r\n')
disp(M_gyro_inv_)

使用特权

评论回复
26
狗啃模拟|  楼主 | 2022-9-27 23:35 | 只看该作者
运行后的输出结果:
M_x*M_y*dy_t + M_x*dp_t + dr_t=

               drdt - dydt*sin(p)
dpdt*cos(r) + dydt*cos(p)*sin(r)
dydt*cos(p)*cos(r) - dpdt*sin(r)

M_gyro is true

M_gyro=

[ 1,       0,       -sin(p)]
[ 0,  cos(r), cos(p)*sin(r)]
[ 0, -sin(r), cos(p)*cos(r)]

M_gyro_inv=

[ 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)]
[ 0,                        cos(r)/(cos(r)^2 + sin(r)^2),                       -sin(r)/(cos(r)^2 + sin(r)^2)]
[ 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)]

M_gyro_inv_ * M_gyro=

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

M_gyro_inv_ =

[ 1, (sin(p)*sin(r))/cos(p), (cos(r)*sin(p))/cos(p)]
[ 0,                 cos(r),                -sin(r)]
[ 0,          sin(r)/cos(p),          cos(r)/cos(p)]

使用特权

评论回复
27
狗啃模拟|  楼主 | 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坐标系的陀螺仪角速度值转换到大地坐标系的旋转矩阵

使用特权

评论回复
28
狗啃模拟|  楼主 | 2022-9-27 23:43 | 只看该作者
推导加速度计的变换矩阵
%% 推导加速度计的变换矩阵

M_acc=M_x*M_y*M_z;
fprintf('M_acc=\r\n')
disp(M_acc)

%重力向量
syms g
acc = [0;
       0;
       g];
IMU_acc=M_acc*acc;
fprintf('IMU_acc=\r\n')
disp(IMU_acc)

使用特权

评论回复
29
狗啃模拟|  楼主 | 2022-9-27 23:48 | 只看该作者
运行后的输出结果:
M_acc=

[                        cos(p)*cos(y),                        cos(p)*sin(y),       -sin(p)]
[ cos(y)*sin(p)*sin(r) - cos(r)*sin(y), cos(r)*cos(y) + sin(p)*sin(r)*sin(y), cos(p)*sin(r)]
[ sin(r)*sin(y) + cos(r)*cos(y)*sin(p), cos(r)*sin(p)*sin(y) - cos(y)*sin(r), cos(p)*cos(r)]

IMU_acc=

       -g*sin(p)
g*cos(p)*sin(r)
g*cos(p)*cos(r)
[em:24:]

使用特权

评论回复
30
狗啃模拟|  楼主 | 2022-9-27 23:48 | 只看该作者
计算得到的IMU_acc即是加速度计感受到的重力加速度向量在IMU最终姿态所在坐标系中的坐标。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则