我有俯仰角,俯仰角和偏航角。我如何将这些转换为方向向量?
如果您能向我展示四元数和/或矩阵表示,那就特别酷!
答案 0 :(得分:70)
不幸的是,关于如何定义这些东西有不同的约定(滚动,俯仰,偏航与欧拉角度不完全相同),所以你必须要小心。
如果我们将pitch = 0定义为水平(z = 0)并将yaw定义为从x轴逆时针,那么方向矢量将
x = cos(yaw)*cos(pitch) y = sin(yaw)*cos(pitch) z = sin(pitch)
请注意,我没有使用过roll;这是方向单位向量,它没有指定态度。编写一个旋转矩阵很容易,它将物体带入飞行物体的框架中(如果你想知道,比如左翼尖指向的位置),但最好先指定惯例。你能告诉我们更多关于这个问题的信息吗?
修改强> (我一直想回到这个问题两年半。)
对于完整旋转矩阵,如果我们使用上面的约定并且我们希望矢量首先偏转,然后俯仰,然后滚动,以便在世界坐标系中获得最终坐标,我们必须应用旋转矩阵。逆序。
第一次滚动:
| 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 |
将它们组合起来,总旋转矩阵为:
| 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轴开始的单位矢量,最终坐标为:
x = cos(yaw)cos(pitch)
y = sin(yaw)cos(pitch)
z = sin(pitch)
对于从y轴(左翼尖)开始的单位矢量,最终坐标为:
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)
答案 1 :(得分:19)
有三种不同的方法可以将三个欧拉角转换为一个矩阵,具体取决于它们所应用的顺序:
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种方法可以取决于您 - 可以通过否定角度来改变“手性”。
答案 2 :(得分:8)
Beta节省了我的一天。但是我使用的是一个稍微不同的参考坐标系,我对音高的定义是向上\向下(点头同意),其中正音高导致负 y -零件。我的参考向量是OpenGl样式(向下-z轴),因此当yaw = 0,pitch = 0时,得到的单位向量应该等于(0,0,-1)。 如果有人遇到这篇文章并且难以将Beta的公式转换为这个特定的系统,我使用的公式是:
vDir->X = sin(yaw);
vDir->Y = -(sin(pitch)*cos(yaw));
vDir->Z = -(cos(pitch)*cos(yaw));
注意符号变化和偏航< - >音调交换。希望这能节省一些时间。
答案 3 :(得分:1)
你需要在这里明确你的定义 - 特别是你想要的矢量是什么?如果它是飞机指向的方向,则滚动甚至不会影响它,并且您只是使用spherical coordinates(可能是轴/角度置换)。
另一方面,如果您想要获取给定的矢量并按这些角度进行变换,则需要寻找旋转矩阵。旋转矩阵上的wiki article包含基于xyz旋转矩阵的偏航 - 俯仰 - 滚动旋转的公式。考虑到所涉及的希腊字母和矩阵,我不打算在这里输入它。
答案 4 :(得分:0)
如果有人偶然发现在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)