其他分享
首页 > 其他分享> > 欧拉角表示旋转会出现的问题——万向锁(Gimbal Lock)

欧拉角表示旋转会出现的问题——万向锁(Gimbal Lock)

作者:互联网

本文用来总结万向锁问题。尽量写得非常简单,方便自己复习和后人理解。

一、旋转的表示

二、万向锁的定义

下面是我个人的定义:

  1. 绕Z轴旋转90°(右旋90)
  2. 绕Y轴旋转90度(抬头90)
  3. 绕X轴旋转90度;
    物体最终呈现的空间状态 和 物体直接 绕Y轴旋转90度是一样的。

三、万向锁带来的问题

3D动画中的插帧问题

当然上述的最终情况是用比较特殊的方式表示的,如果表示为0 90 0就不会出现为这个问题;
但是当设置为其他情况时候:
初始:Z(30) Y(10) X(15)
最终:Z(120) Y(90) X(45)
在这里插入图片描述

初始:Z(350) Y(0) X(0)
最终:Z(90) Y(90) X(0)
在这里插入图片描述

总结一下可以发现:只有初始状态是在XZ平面YZ平面内的向量在用欧拉角插值的时候才不会出现插值出异常的运动轨迹。其他的轨迹均是运动异常的。所以一般3D动画采用的是四元数插值方法。

高机动飞行器的姿态问题

这方面没有想通到底问题何在,普通飞控一般采用欧拉角进行控制,一般普通飞机的俯仰角不会达到90°,或许是类似于火箭/导弹一类飞行器,有垂直飞行转化为水平飞行的过程有涉及到万向锁的问题。若有懂哥请指教。

四、数学上的解释

另 θ = 90 \theta=90 θ=90
变换矩阵可化为
[ 0 sin ⁡ ( ϕ − ψ ) cos ⁡ ( ϕ − ψ ) 0 cos ⁡ ( ϕ − ψ ) − sin ⁡ ( ϕ − ψ ) 1 0 0 ] \begin{bmatrix} 0 & \sin(\phi-\psi)& \cos(\phi-\psi) \\ 0 & \cos(\phi-\psi) & -\sin(\phi-\psi) \\ 1 & 0 & 0 \end{bmatrix} ⎣⎡​001​sin(ϕ−ψ)cos(ϕ−ψ)0​cos(ϕ−ψ)−sin(ϕ−ψ)0​⎦⎤​
对于所有状态的初始向量 [ 1 0 0 ] \begin{bmatrix}1\\0\\0\end{bmatrix} ⎣⎡​100​⎦⎤​,无论滚转航向角度取何值,最终都是 [ 0 0 1 ] \begin{bmatrix}0\\0\\1\end{bmatrix} ⎣⎡​001​⎦⎤​;

五、总结

  1. 首先是用坐标变换矩阵表示旋转,旋转总是从列向量 [ 1 0 0 ] \begin{bmatrix}1\\0\\0\end{bmatrix} ⎣⎡​100​⎦⎤​开始的;
  2. 第三部分的例子的初始状态也是通过旋转矩阵从 [ 1 0 0 ] \begin{bmatrix}1\\0\\0\end{bmatrix} ⎣⎡​100​⎦⎤​旋转到例子中的初始状态下的(详见程序);
  3. 注意坐标变换时的输入和输出向量是在什么坐标系下的;
  4. 万向锁是用欧拉角表示旋转过程中的一种状态;

参考

https://zhuanlan.zhihu.com/p/73406793
https://zhuanlan.zhihu.com/p/74040465
https://www.bilibili.com/video/BV1WK4y187A3?from=search&seid=14517252516529200541

附:matlab程序

clc;
clear;
axis on;
set(gca,'ZDir','reverse')%对Z方向反转
set(gca,'XDir','reverse')%对X方向反转
PI=3.1415926;
DEG2RAD=PI/180;
%初始
phi_init = 30*DEG2RAD;%X
tha_init = 10*DEG2RAD;%Y
psi_init = 15*DEG2RAD;%Z
%最终
phi_fin = 120*DEG2RAD;
tha_fin = 90*DEG2RAD;
psi_fin = 45*DEG2RAD;

inter_cnt=50;%插帧数量
PHI=[phi_init];
THA=[tha_init];
PSI=[psi_init];
%生成帧序列 各个中间状态
for i=1:inter_cnt
    PHI=[PHI PHI(i)+(phi_fin-phi_init)/inter_cnt];
    THA=[THA THA(i)+(tha_fin-tha_init)/inter_cnt];
    PSI=[PSI PSI(i)+(psi_fin-psi_init)/inter_cnt];
end

vecx=[];
vecy=[];
vecz=[];
hold on;
for i=1:inter_cnt
    phi=PHI(i);
    tha=THA(i);
    psi=PSI(i);
    RX=[1 0 0;
        0 cos(phi) -sin(phi);
        0 sin(phi) cos(phi)];
    RY=[cos(tha) 0 sin(tha);
        0 1 0;
        -sin(tha) 0 cos(tha)];
    RZ=[cos(psi) -sin(psi) 0;
        sin(psi) cos(psi) 0;
        0 0 1];
    
    vec=RZ*RY*RX*[1;0;0];%都是从[1;0;0]开始旋转来表示每帧状态,而非相对上一帧的增量
    vecx=[vecx vec(1)];
    vecy=[vecy vec(2)];
    vecz=[vecz vec(3)];
    line([0 vec(1)],[0 vec(2)],[0 vec(3)]);
    
end
%正方向指示
line([0 1],[0 0],[0 0],'color','r');%X
line([0 0],[0 1],[0 0],'color','g');%Y
line([0 0],[0 0],[0 1],'color','b');%Z
%划出的轨迹
plot3(vecx,vecy,vecz);

标签:phi,psi,Gimbal,欧拉角,Lock,cos,bmatrix,90,sin
来源: https://blog.csdn.net/seraph0321/article/details/111640415