看了网上好多的讲解,讲的都不是特别清晰,让人有一种很懵懵的感觉,感觉懂了,又貌似没懂的奇怪感觉,读了那么多的水文,大多都是内容差不多,好多文章之中错误百出,都是稍微提了一点,没有详细对比二者的区别,很难让人从心里真正明白其中含义.由于项目需要,这里对于动态欧拉角和静态欧拉角的区别进行一个整理.
针对于欧拉角的概念,一个点围绕一个轴进行旋转,进而得到另一个点,可以将其视为一维旋转过程.欧拉角就是将这一个点围绕一个轴进行旋转分为围绕三个轴旋转的过程,将原来的一维旋转变换为围绕三个轴三维旋转的过程.
这里采用的右手坐标系进行讲解,就是拿出右爪子,从大拇指开始的三个手指摆出三脚架的样子,如下坐标系为一个右手坐标系.当然方向是可以进行改变的.这里只是举一个例子。
这里取固定的坐标系为oxyz,由于旋转的过程原点o是固定的,其变换过程的坐标系为.(学会一项新技能,CSDN之中插入公式终于不用截图了,使用下面的这个链接Online Equation Editor - standaloneLaTeX equation editor that creates lightweight graphical equations (gif, png, swf, pdf, emf) and produces code to quickly and directly embedding equations into HTML websites, forums or blogs.https://codecogs.com/latex/eqneditor.php转换成LaTeX,进行黏贴就可以转换成为CSDN公式.)
静态/外旋欧拉角
静态欧拉角(又称为外旋欧拉角),就是其旋转轴使用的是静止不动的参考系,比如说世界坐标系,物体在旋转的过程中,坐标轴始终是保持静止,所以称为静态欧拉角,这种欧拉角一般是在地图的构建过程以及地图的导航过程之中使用,因为我们要统一坐标系,统一旋转角度,不可能是拿着相对的坐标系去表征当前的角度.
以旋转过程中,以轴序:x-y-z;,角序: (α,β,γ)为例.其每个旋转的过程是按照固定的坐标轴,x,y,z轴进行一个旋转的过程.
设一点p在原来的坐标系之中的向量为,旋转矩阵的计算方法如下:r = rz * ry *rx,乘法顺序:从右向左,依次旋转X轴Y轴Z轴.将其旋转过程分为如下几个过程.
- 第一次旋转:围绕x轴逆时针旋转α度.
设旋转矩阵为r(x,α),可知p点原始的向量为,经过旋转之后所得到的旋转向量为 - 第二次旋转:围绕y轴逆时针旋转β度.
设旋转矩阵为r(y,β),可知旋转向量经过旋转之后所得到的旋转向量为. - 第三次旋转:围绕z轴逆时针旋转γ度.
设旋转矩阵为r(z,γ),可知旋转向量经过旋转之后所得到的旋转向量为.
综上所述,三次旋转之后,所对应的原始向量变成了,旋转过程,总而言之,可以表述为,记这里的为旋转矩阵.
这就是所谓的静态欧拉角的表述过程.
为了更好的理解,建立如下固定坐标系:
这里我们定义旋转量如下所示:
其旋转矩阵可以表示为:
通过如上所示,就可以将围绕每个坐标轴旋转的角度进行求取.
动态/内旋欧拉角
动态欧拉角(又称为内旋欧拉角),就是其旋转轴使用的是活动的参考系,绕物体坐标系三个轴的旋转,由于物体旋转过程中坐标轴随着旋转变换运动,所以称为动态欧拉角。这种欧拉角在航空领域中,滚转、俯仰、偏航角有明确的物理意义。
以旋转过程中,初始坐标系与定义的固定oxyz坐标系相同,旋转每次的坐标系分别为.以轴序:,角序: (α,β,γ)为例.其每个旋转的过程是按照活动的坐标轴进行旋转.
由于直接进行得到旋转矩阵R的过程是非常难以理解的,所以这里是需要使用一个逆向思维进行求解旋转矩阵R,使用的是一个反向求解的过程,分为如下步骤进行:
设原始点为p,经过旋转之后得到向量为,在原始的坐标系之中.经过坐标系变换,其向量变换为.也就是说要求向量
-
第一次旋转的过程:围绕原来的oxyz轴中的z轴逆向旋转γ,进而得到坐标系.
-
第二次旋转的过程:围绕坐标系中的y轴旋转β,进而得到坐标系.
- 第三次旋转的过程:围绕坐标系中的x轴旋转α,进而得到坐标系.
上述的三次旋转过程之后得到的旋转矩阵与静态欧拉角表述得到的旋转矩阵是相同的.也就是,只不过这里是使用R进行表示的。
二者之间的区别
静态欧拉角是进行一个左乘的过程,动态欧拉角是进行一个右乘的过程,由上面描述的过程可以知道,静态欧拉角的旋转顺序是x-y-z,动态欧拉角的旋转顺序是z-y-x,每个轴旋转角度是相同的,得到的结果却也是相同的。
动态欧拉角的万向节死锁问题
两种表述方式:
①语言描述:在进行动态欧拉角的旋转的过程,首先围绕一个轴1旋转,旋转过后再围绕轴2旋转90度,会导致两个轴平行的过程。
②公式描述:如下所示:
可见,原来的三个自由度,现在变成了两个自由度,直接失去了一个自由度的过程,我们称之为万向节死锁问题。
旋转矩阵与欧拉角之间的相互转换
旋转矩阵转欧拉角(这里是不需要配置什么什么库的方法,具体的计算过程在前面的静态欧拉角已经写得很明白了)
// Checks if a matrix is a valid rotation matrix.
bool isRotationMatrix(Mat &R)
{Mat Rt;transpose(R, Rt);Mat shouldBeIdentity = Rt * R;Mat I = Mat::eye(3,3, shouldBeIdentity.type());return norm(I, shouldBeIdentity) < 1e-6;
}// Calculates rotation matrix to euler angles
// The result is the same as MATLAB except the order
// of the euler angles ( x and z are swapped ).
Vec3f rotationMatrixToEulerAngles(Mat &R)
{assert(isRotationMatrix(R));float sy = sqrt(R.at<double>(0,0) * R.at<double>(0,0) + R.at<double>(1,0) * R.at<double>(1,0) );bool singular = sy < 1e-6; // Iffloat x, y, z;if (!singular){x = atan2(R.at<double>(2,1) , R.at<double>(2,2));y = atan2(-R.at<double>(2,0), sy);z = atan2(R.at<double>(1,0), R.at<double>(0,0));}else//由于欧拉角存在奇异性,当pitch为90°时会出现解不稳定的情况因此需要进行特殊处理{x = atan2(-R.at<double>(1,2), R.at<double>(1,1));y = atan2(-R.at<double>(2,0), sy);z = 0;}return Vec3f(x, y, z);}
欧拉角转换为旋转矩阵(就是进行一个直接相乘的过程,简单的很)
// Calculates rotation matrix given euler angles.
Mat eulerAnglesToRotationMatrix(Vec3f &theta)
{// Calculate rotation about x axisMat R_x = (Mat_<double>(3,3) <<1, 0, 0,0, cos(theta[0]), -sin(theta[0]),0, sin(theta[0]), cos(theta[0]));// Calculate rotation about y axisMat R_y = (Mat_<double>(3,3) <<cos(theta[1]), 0, sin(theta[1]),0, 1, 0,-sin(theta[1]), 0, cos(theta[1]));// Calculate rotation about z axisMat R_z = (Mat_<double>(3,3) <<cos(theta[2]), -sin(theta[2]), 0,sin(theta[2]), cos(theta[2]), 0,0, 0, 1);// Combined rotation matrixMat R = R_z * R_y * R_x;return R;
}
欧拉角的缺点
欧拉角的表示方式不唯一。给定某个起始朝向和目标朝向,通过相同的旋转但是不同的旋转顺序得到的终值可能相同。
欧拉角的插值比较难。
计算旋转变换时,一般需要转换成旋转矩阵,这时候需要计算很多sin, cos,计算量较大。
补充---正方向的判断
方式①:如果是右手系,旋转轴正方向面对观察者时,逆时针方向的旋转是正、顺时针方向的旋转是负。
方式②:亦可这样描述:使用右手的大拇指指向旋转轴正方向,其他4个手指在握拳过程中的指向便是正方向