旋转矩阵 欧拉角 四元数
来源:互联网 发布:linux 登录mysql 编辑:程序博客网 时间:2024/05/01 23:39
如何描述三维空间中刚体的旋转,是个有趣的问题。具体地说,就是刚体上的任意一个点P(x, y, z)围绕过原点的轴(i, j, k)旋转θ,求旋转后的点P\'(x\', y\', z\')。
旋转矩阵
旋转矩阵乘以点P的齐次坐标,得到旋转后的点P',因此旋转矩阵可以描述旋转,
绕x,y,或z轴旋转θ的矩阵为:
所以,绕任意轴旋转的矩阵为
这表示:
1. 绕x轴旋转角度p使指定的旋转轴在xz平面上
2. 绕y轴旋转角度q使指定的旋转轴与z轴重合
3. 绕z轴旋转角度θ
4. 绕y轴旋转角度-q
5. 绕x轴旋转角度-p
其中,p和q的值需要用i,j,k计算出来。
欧拉角
欧拉角也可以描述三维刚体旋转,它将刚体绕过原点的轴(i,j,k)旋转θ,分解成三步(蓝色是起始坐标系,而红色的是旋转之后的坐标系。)。
1. 绕z轴旋转α,使x轴与N轴重合,N轴是旋转前后两个坐标系x-y平面的交线
2. 绕x轴(也就是N轴)旋转β,使z轴与旋转后的z轴重合
3. 绕z轴旋转γ,使坐标系与旋转后的完全重合
按照旋转轴的顺序,该组欧拉角被称为是“zxz顺规”的。对于顺规的次序,学术界没有明确的约定。
欧拉角的旋转矩阵为:
在旋转矩阵一节中,最先进行的旋转其矩阵在最右侧,说明该矩阵最先与点的齐次坐标相乘,旋转矩阵按照旋转的次序从右向左排列。而在欧拉角中,最先进行的旋转其旋转矩阵在最左边。这是因为,**对于前者(旋转矩阵),我们始终是以绝对参考系为参照来的,对于后者(欧拉角),我们每一次旋转的刻画都是基于刚体的坐标系。**比如,在欧拉角中的第2步,绕x轴旋转β,这里的x轴实际上是N轴了(而不是蓝色的x轴)。
为什么旋转参考系的不同会导致旋转矩阵次序的差异呢?细想一下便知,旋转矩阵左乘叠加用以描述三维变换效果的叠加,这本身就是基于绝对坐标系的,所以旋转矩阵一节没有疑问;而对于欧拉角一节的这种旋转方式,这样考虑:
1. 如果有一个“影子坐标系3”与原坐标系重合,然后首先进行了第3步(绕z轴旋转γ);
2. 然后有一个“影子坐标系2”也与原坐标系重合,然后与“影子坐标系3”一起(视作同一个刚体)进行了第二步;
3. 最后一个“影子坐标系1”,与前两个坐标系一起进行了第一步。
此时,考察“影子坐标系”1和2,他们就分别落在了欧拉角旋转的两个“快照”上,而“影子坐标系3”就落在旋转后的位置上(红色的)。而在上述过程中,“影子坐标系3”就是相对于绝对坐标系依次进行了第三步,第二步,和第一步。所以欧拉角的旋转矩阵写成那样,也是行得通的。
这个想法,我猜在很多第一人称游戏中,已经得到了广泛应用了。这样,玩家对人物的控制就可以绕开人物的实时状态(位置,角度等)直接对人物的模型矩阵产生影响。
万向节死锁是欧拉角的一个弊端,这是一个直观的例子。
四元数
四元数是今天的主角,它能够很方便的刻画刚体绕任意轴的旋转。四元数是一种高阶复数,四元数q表示为:
其中,i,j,k满足:
由于i,j,k的性质和笛卡尔坐标系三个轴叉乘的性质很像,所以可以将四元数写成一个向量和一个实数组合的形式:
可以推导出四元数的一些运算性质,包括:
* 四元数乘法
* 共轭四元数
* 四元数的平方模
* 四元数的逆
四元数可以看做是向量和实数的一种更加一般的形式,向量可以视作为实部为0的四元数,而实数可以是作为虚部为0的四元数。上述四元数的运算性质也是实数或向量的运算性质的更一般的形式。
四元数可用来刻画三维空间中的旋转,绕单位向量(x,y,z)表示的轴旋转θ,可令:
刚体坐标系中的点p(P,0)(写成四元数的形式),旋转后的坐标p'为:
接下来我们来证明这一点。
首先,我们证明
其中s为实数。显然
此时,我们可以将q看做是单位矩阵,因为如果q不是单位矩阵,我们就可以乘以一个常数s将其化为单位矩阵。
然后,我们证明qpq^{-1}和p的模长相等
下面将q视为单位四元数:
四元数q的标量:
那么:
最后,我们证明
如图所示,u为旋转轴,旋转角度为σ,向量v旋转到w处。旋转到σ/2处为k(图中未标出)。
下面也用相同的字母指代四元数,如u就表示向量u的四元数形式((ux,uy,uz),0)。
首先,令u方向上的单位向量为u(为了方便,命名不变,后面的u都是指旋转轴方向的单位四元数),那么根据q的定义,参见四元数乘法法则:
现在令
如果能证明w与v的夹角是σ,那么就说明w确实是v旋转σ得到的,整个命题就得证了。
注意v,k和w都是实部为0的单位四元数,表示单位向量,我们有:
所以
上面的式子拆分成实部和虚部,虚部表明w与-k的平面和k与-v的平面重合,实部表明w和-k之间的夹角与k和-v之间的夹角相等,都是π-σ/2。这就说明了w与v的夹角是σ,原命题就得证了。
作者:一叶斋主人
出处:www.cnblogs.com/yiyezhai
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
欧拉角-旋转矩阵-四元数转换的一个例子
欧拉角转四元数与旋转矩阵再转回欧拉角
本次测试C代码出处:
http://bbs.ednchina.com/BLOG_ARTICLE_ 1616965.HTM{{Name→Visual Studio, Compiler→CCompilerDriver`VisualStudioCompiler`VisualStudioCompiler, CompilerInstallation→E:\\Program Files (x86)\\Microsoft Visual Studio 10.0, CompilerName→Automatic}}
(*ResetDirectory[] *)
mainFile = Imp
ort[sourceDirectory<>"\\EulerAngle.txt", CharacterEncoding->"CP936"] /* 输入欧拉角,能看到四元数,以及再转换回去成欧拉角
Yaw范围(-180~180)
Pitch范围(-90~90)
Roll范围(-180~180)
*/
#include \"stdio.h\"
#include \"math.h\"
main()
{
float theta_z , theta_y ,theta_x ;
float cos_z_2;
float cos_y_2;
float cos_x_2;
float sin_z_2;
float sin_y_2;
float sin_x_2;
float Pitch;
float Roll;
float Yaw;
float Q[4];
float T[3][3];
do{
printf(\"\
Yaw = \");
scanf(\"%f\",&theta_z);
printf(\"\
Pitch = \");
scanf(\"%f\",&theta_y);
printf(\"\
Roll = \");
scanf(\"%f\",&theta_x);
theta_z = theta_z*3.1416/180;
theta_y = theta_y*3.1416/180;
theta_x = theta_x*3.1416/180;
cos_z_2 = cos(0.5*theta_z);
cos_y_2 = cos(0.5*theta_y);
cos_x_2 = cos(0.5*theta_x);
sin_z_2 = sin(0.5*theta_z);
sin_y_2 = sin(0.5*theta_y);
sin_x_2 = sin(0.5*theta_x);
Q[0] = cos_z_2*cos_y_2*cos_x_2 + sin_z_2*sin_y_2*sin_x_2;
Q[1] = cos_z_2*cos_y_2*sin_x_2 - sin_z_2*sin_y_2*cos_x_2;
Q[2] = cos_z_2*sin_y_2*cos_x_2 + sin_z_2*cos_y_2*sin_x_2;
Q[3] = sin_z_2*cos_y_2*cos_x_2 - cos_z_2*sin_y_2*sin_x_2;
printf(\"\
Q=[ %f %f %f %f]\
\
\",Q[0],Q[1],Q[2],Q[3]) ;
printf(\"alpha = %f\
\
\",acos(Q[0])*2*180/3.1416) ;
T[0][0] = Q[0]*Q[0]+Q[1]*Q[1]-Q[2]*Q[2]-Q[3]*Q[3] ;
T[0][1] = 2*(Q[1]*Q[2]-Q[0]*Q[3]);
T[0][2] = 2*(Q[1]*Q[3]+Q[0]*Q[2]);
T[1][0] = 2*(Q[1]*Q[2]+Q[0]*Q[3]);
T[1][1] = Q[0]*Q[0]-Q[1]*Q[1]+Q[2]*Q[2]-Q[3]*Q[3] ;
T[1][2] = 2*(Q[2]*Q[3]-Q[0]*Q[1]);
T[2][0] = 2*(Q[1]*Q[3]-Q[0]*Q[2]);
T[2][1] = 2*(Q[2]*Q[3]+Q[0]*Q[1]);
T[2][2] = Q[0]*Q[0]-Q[1]*Q[1]-Q[2]*Q[2]+Q[3]*Q[3] ;
printf(\"T[0][0] = %9f,T[0][1] = %9f,T[0][2] = %9f\
\",T[0][0],T[0][1],T[0][2]);
printf(\"T[1][0] = %9f,T[1][1] = %9f,T[1][2] = %9f\
\",T[1][0],T[1][1],T[1][2]);
printf(\"T[2][0] = %9f,T[2][1] = %9f,T[2][2] = %9f\
\
\",T[2][0],T[2][1],T[2][2]);
Pitch = asin(-T[2][0]);
Roll = atan( T[2][1]/T[2][2]);
Yaw = atan( T[1][0]/T[0][0]);
if(T[2][2]<0)
{
if(Roll < 0)
{
Roll = Roll+3.1416;
}
else
{
Roll = Roll-3.1416;
}
}
if(T[0][0]<0)
{
if(T[1][0]>0)
{
Yaw = Yaw + 3.1416;
}
else
{
Yaw = Yaw - 3.1416;
}
}
printf(\"Yaw = %f\
Pitch = %f\
Roll = %f\
\",Yaw*180/3.1416,Pitch*180/3.1416,Roll*180/3.1416) ;
}while(1);
printf(\"Hello, world\
\");
getch();
}temp = CreateExecutable[mainFile, "EulerAngle", "Language"→"C", "Debug"→True, "TargetDirectory"→targetDirectory]
E:\\Users\\Quaternions\\Documents\\C Programming\\Working-euclid-13500-13148-1>call \"E:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\vcvarsall.bat\" amd64
Setting environment for using Microsoft Visual Studio 2010 x64 tools.
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.30319.01 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
EulerAngle.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:EulerAngle.exe
/debug
user32.lib
kernel32.lib
gdi32.lib
\"/LIBPATH:E:\\Program Files\\Wolfram Research\\Mathematica\\9.0\\SystemFiles\\Links\\MathLink\\DeveloperKit\\Windows-x86-64\\CompilerAdditions\\mldev64\\lib\"
\"/LIBPATH:E:\\Program Files\\Wolfram Research\\Mathematica\\9.0\\SystemFiles\\Libraries\\Windows-x86-64\"
\"/out:E:\\Users\\Quaternions\\Documents\\C Programming\\Working-euclid-13500-13148-1\\EulerAngle.exe\"
EulerAngle.objE:\\Users\\Quaternions\\Documents\\C Programming\\EulerAngle.exe
一个可能的问题
输入的欧拉角和反求的欧拉角存在数值上的不一致性,这个问题有的时候会有问题,特别是90度角等及一些奇点的情况。
可能会导致运动中的不连续性问题。
转自:http://quaternions.blog.163.com/blog/static/20608214720134184924552/
- 旋转矩阵 欧拉角 四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 四元数 旋转 旋转矩阵 欧拉角互相转换
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 三维旋转:旋转矩阵,欧拉角,四元数
- 旋转矩阵、欧拉角、四元数比较
- 旋转矩阵、欧拉角、四元数比较
- 欧拉角、四元数和旋转矩阵
- 四元数、欧拉角和旋转矩阵
- 旋转矩阵、欧拉角、四元数比较
- 三维空间 旋转矩阵 四元数 欧拉角 相互转换 组合旋转
- 旋转矩阵、DCM、旋转向量、四元数、欧拉角相关
- 旋转矩阵,欧拉角,四元数,旋转向量(轴-角)
- LightSwitch新theme的创建
- 如何判断mysql某个数据库某张表是否存在
- java基础---IO流
- MyEclipse使用教程之自定义和更新MyEclipse
- Linus Torvalds 如何修正影响《猎魔人2》的内核 bug
- 旋转矩阵 欧拉角 四元数
- 代写程序
- Google Chrome浏览器经常崩溃怎么处理?
- android应用开发学习纪实(2)
- Java内存分配全面浅析
- 读取excel为CSV文件件
- ubuntu server 14.04 启动 gnome(桌面) fail(失败)
- java的Object类
- 宏定义放在结构体里