如何将欧拉angular转换为方向vector?

我有俯仰,滚转和偏航angular度。 我将如何将这些转换为方向vector?

如果你能告诉我一个四元数和/或matrix表示,这将是特别酷的!

不幸的是,在如何定义这些东西方面存在着不同的约定(滚动,俯仰,偏航与欧拉angular不太一样),所以你必须小心。

如果我们将音高= 0定义为水平(z = 0)并且从x轴逆时针偏转,则方向vector将是

 x = cos(yaw)* cos(pitch)
 y = sin(yaw)* cos(pitch)
 z = sin(pitch)

请注意,我没有使用roll; 这是方向单位vector,它没有指定态度。 编写一个旋转matrix就足够简单了,该旋转matrix将把事物带入飞行物体的框架中(如果你想知道左翼指向的位置),但首先指定惯例是一个好主意。 你能告诉我们更多关于这个问题吗?

编辑:(我一直想回到这个问题两年半)。

对于完整的旋转matrix,如果我们使用上面的惯例,我们希望vector首先偏航,然后俯仰,然后滚动,以获得世界坐标系中的最终坐标,我们必须以相反的顺序应用旋转matrix。

第一卷:

| 1 0 0 | | 0 cos(roll) -sin(roll) | | 0 sin(roll) cos(roll) | 

然后俯仰:

 | cos(pitch) 0 -sin(pitch) | | 0 1 0 | | sin(pitch) 0 cos(pitch) | 

然后偏航:

 | cos(yaw) -sin(yaw) 0 | | sin(yaw) cos(yaw) 0 | | 0 0 1 | 

合并它们,总旋转matrix是:

 | cos(yaw)cos(pitch) -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) -cos(yaw)sin(pitch)cos(roll)+sin(yaw)sin(roll)| | sin(yaw)cos(pitch) -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) -sin(yaw)sin(pitch)cos(roll)-cos(yaw)sin(roll)| | sin(pitch) cos(pitch)sin(roll) cos(pitch)sin(roll)| 

因此,对于从x轴开始的单位vector,最终的坐标将是:

 x = cos(yaw)cos(pitch) y = sin(yaw)cos(pitch) z = sin(pitch) 

对于从y轴(左翼尖)开始的单位vector,最终坐标将为:

 x = -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) y = -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) z = cos(pitch)sin(roll) 

根据所应用的顺序,有三种方法可以将三个欧拉angular转换为matrix:

 typedef float Matrix[3][3]; struct EulerAngle { float X,Y,Z; }; // Euler Order enum. enum EEulerOrder { ORDER_XYZ, ORDER_YZX, ORDER_ZXY, ORDER_ZYX, ORDER_YXZ, ORDER_XZY }; Matrix EulerAnglesToMatrix(const EulerAngle &inEulerAngle,EEulerOrder EulerOrder) { // Convert Euler Angles passed in a vector of Radians // into a rotation matrix. The individual Euler Angles are // processed in the order requested. Matrix Mx; const FLOAT Sx = sinf(inEulerAngle.X); const FLOAT Sy = sinf(inEulerAngle.Y); const FLOAT Sz = sinf(inEulerAngle.Z); const FLOAT Cx = cosf(inEulerAngle.X); const FLOAT Cy = cosf(inEulerAngle.Y); const FLOAT Cz = cosf(inEulerAngle.Z); switch(EulerOrder) { case ORDER_XYZ: Mx.M[0][0]=Cy*Cz; Mx.M[0][1]=-Cy*Sz; Mx.M[0][2]=Sy; Mx.M[1][0]=Cz*Sx*Sy+Cx*Sz; Mx.M[1][1]=Cx*Cz-Sx*Sy*Sz; Mx.M[1][2]=-Cy*Sx; Mx.M[2][0]=-Cx*Cz*Sy+Sx*Sz; Mx.M[2][1]=Cz*Sx+Cx*Sy*Sz; Mx.M[2][2]=Cx*Cy; break; case ORDER_YZX: Mx.M[0][0]=Cy*Cz; Mx.M[0][1]=Sx*Sy-Cx*Cy*Sz; Mx.M[0][2]=Cx*Sy+Cy*Sx*Sz; Mx.M[1][0]=Sz; Mx.M[1][1]=Cx*Cz; Mx.M[1][2]=-Cz*Sx; Mx.M[2][0]=-Cz*Sy; Mx.M[2][1]=Cy*Sx+Cx*Sy*Sz; Mx.M[2][2]=Cx*Cy-Sx*Sy*Sz; break; case ORDER_ZXY: Mx.M[0][0]=Cy*Cz-Sx*Sy*Sz; Mx.M[0][1]=-Cx*Sz; Mx.M[0][2]=Cz*Sy+Cy*Sx*Sz; Mx.M[1][0]=Cz*Sx*Sy+Cy*Sz; Mx.M[1][1]=Cx*Cz; Mx.M[1][2]=-Cy*Cz*Sx+Sy*Sz; Mx.M[2][0]=-Cx*Sy; Mx.M[2][1]=Sx; Mx.M[2][2]=Cx*Cy; break; case ORDER_ZYX: Mx.M[0][0]=Cy*Cz; Mx.M[0][1]=Cz*Sx*Sy-Cx*Sz; Mx.M[0][2]=Cx*Cz*Sy+Sx*Sz; Mx.M[1][0]=Cy*Sz; Mx.M[1][1]=Cx*Cz+Sx*Sy*Sz; Mx.M[1][2]=-Cz*Sx+Cx*Sy*Sz; Mx.M[2][0]=-Sy; Mx.M[2][1]=Cy*Sx; Mx.M[2][2]=Cx*Cy; break; case ORDER_YXZ: Mx.M[0][0]=Cy*Cz+Sx*Sy*Sz; Mx.M[0][1]=Cz*Sx*Sy-Cy*Sz; Mx.M[0][2]=Cx*Sy; Mx.M[1][0]=Cx*Sz; Mx.M[1][1]=Cx*Cz; Mx.M[1][2]=-Sx; Mx.M[2][0]=-Cz*Sy+Cy*Sx*Sz; Mx.M[2][1]=Cy*Cz*Sx+Sy*Sz; Mx.M[2][2]=Cx*Cy; break; case ORDER_XZY: Mx.M[0][0]=Cy*Cz; Mx.M[0][1]=-Sz; Mx.M[0][2]=Cz*Sy; Mx.M[1][0]=Sx*Sy+Cx*Cy*Sz; Mx.M[1][1]=Cx*Cz; Mx.M[1][2]=-Cy*Sx+Cx*Sy*Sz; Mx.M[2][0]=-Cx*Sy+Cy*Sx*Sz; Mx.M[2][1]=Cz*Sx; Mx.M[2][2]=Cx*Cy+Sx*Sy*Sz; break; } return(Mx); } 

FWIW,有些CPU可以同时计算Sin和Cos(例如x86上的fsincos)。 如果你这样做,你可以用三次调用而不是6来计算初始的sin和cos值。

更新:实际上有12种方法,如果你想要右手或左手的结果 – 你可以通过否定angular度来改变“手型”。

Beta保存了我的一天。 然而,我使用的是稍微不同的参考坐标系,而我的音高定义是上下的(点头赞同) 音调导致 y分量。 我的参考vector是OpenGl样式(向下-z轴),所以yaw = 0,pitch = 0,结果单位向量应该等于(0,0,-1)。 如果有人遇到这个post,并且难以将Beta公式转换为这个特定的系统,我使用的公式是:

 vDir->X = sin(yaw); vDir->Y = -(sin(pitch)*cos(yaw)); vDir->Z = -(cos(pitch)*cos(yaw)); 

注意符号变化和偏航< – >音调交换。 希望这能节省一些时间。

你需要清楚你的定义 – 特别是你想要的vector是什么? 如果它是飞机指向的方向,那么滚动甚至不会影响它,而你只是使用球坐标 (可能是轴/扭转的angular度)。

另一方面,如果你想要一个给定的vector,并通过这些angular度来转换它,你正在寻找一个旋转matrix。 关于旋转matrix的wiki文章包含基于xyz旋转matrix的偏航俯仰滚动旋转的公式。 考虑到涉及的希腊字母和matrix,我不打算在这里input。

如果有人在FreeCAD中寻找实现方式,

 import FreeCAD, FreeCADGui from FreeCAD import Vector from math import sin, cos, pi cr = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().toEuler() crx = cr[2] # Roll cry = cr[1] # Pitch crz = cr[0] # Yaw crx = crx * pi / 180.0 cry = cry * pi / 180.0 crz = crz * pi / 180.0 x = sin(crz) y = -(sin(crx) * cos(crz)) z = cos(crx) * cos(cry) view = Vector(x, y, z)