【发布时间】:2019-10-27 19:21:03
【问题描述】:
我正在模拟平面运动。目前,我使用欧拉角将“身体框架”转换为“世界框架”,效果很好。
最近我了解了四元数及其相对于旋转矩阵(万向节锁定)的优势,并尝试使用模拟器中的偏航/俯仰/滚动角度来实现它。
四元数
如果我理解正确,四元数代表两件事。它有一个 x, y, 和 z 组件,它们表示将发生旋转的轴。它还有一个 w 组件,它表示将围绕该轴发生的旋转量。简而言之,一个向量和一个浮点数。四元数可以表示为 4 元素向量:
q=[w,x,y,z]
计算结果(完全旋转后)方程使用:
p'=qpq'
地点:
p=[0,x,y,z]-方向向量
q=[w,x,y,z]-旋转
q'=[w,-x,-y,-z]
算法
- 创建四元数:
使用wikipedia 我通过围绕 3 个轴 (q) 旋转来创建四元数:
Quaterniond toQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
{
//Degree to radius:
yaw = yaw * M_PI / 180;
pitch = pitch * M_PI / 180;
roll = roll * M_PI / 180;
// Abbreviations for the various angular functions
double cy = cos(yaw * 0.5);
double sy = sin(yaw * 0.5);
double cp = cos(pitch * 0.5);
double sp = sin(pitch * 0.5);
double cr = cos(roll * 0.5);
double sr = sin(roll * 0.5);
Quaterniond q;
q.w = cy * cp * cr + sy * sp * sr;
q.x = cy * cp * sr - sy * sp * cr;
q.y = sy * cp * sr + cy * sp * cr;
q.z = sy * cp * cr - cy * sp * sr;
return q;
}
-
定义平面方向(航向)向量:
p = [0,1,0,0]
-
p'=qpq'
q'= [w, -qx, -qy, -qz]
p' = (H(H(q, p), q')
Quaterniond HamiltonProduct(Quaterniond u, Quaterniond v)
{
Quaterniond result;
result.w = u.w*v.w - u.x*v.x - u.y*v.y - u.z*v.z;
result.x = u.w*v.x + u.x*v.w + u.y*v.z - u.z*v.y;
result.y = u.w*v.y - u.x*v.z + u.y*v.w + u.z*v.x;
result.z = u.w*v.z + u.x*v.y - u.y*v.x + u.z*v.w;
return result;
}
结果
我的结果将是一个向量:
v=[p'x,p'y,p'z]
它工作正常,但与欧拉角旋转(万向锁)相同。是因为我在这里也使用欧拉角吗?如果不围绕 3 个轴旋转,我真的不知道它应该如何工作。我应该分别绕每个轴旋转吗?
对于理解这个问题的任何建议和帮助,我将不胜感激。
编辑(应用程序如何工作)
1.我的应用程序基于数据流,这意味着每 1ms 它检查是否有新数据(平面的新方向)。
例子:
在请求 pitch/roll/yaw = 0 后,1ms 偏航角改变 10 度,因此应用程序读取 pitch=0, roll=0,偏航 = 10。在接下来的 1ms 之后,偏航角再次改变 20 度。因此输入数据将如下所示:pitch=0, roll=0, yaw = 30。
2。创建方向四元数 - p
在乞求时,我定义我的飞机的方向(头部)在 X 轴上。所以我的本地方向是 v=[1,0,0] 在四元数中 (my p) 是 p=[0,1,0,0]
Vector3 LocalDirection, GlobalDirection; //head
Quaterniond p,P,q, Q, pq; //P = p', Q=q'
LocalDirection.x = 1;
LocalDirection.y = 0;
LocalDirection.z = 0;
p.w = 0;
p.x = direction.x;
p.y = direction.y;
p.z = direction.z;
3.创建旋转
在每 1ms 之后,我从数据流中检查旋转角度(欧拉)并使用 toQuaternion
计算 qq = toQuaternion(yaw, pitch, roll); // create quaternion after rotation
Q.w = q.w;
Q.x = -q.x;
Q.y = -q.y;
Q.z = -q.z;
4.计算“世界方向”
使用 Hamilton 积我计算旋转后的四元数,这是我的全局方向:
pq = HamiltonProduct(q, p);
P = HamiltonProduct(pq, Q);
GlobalDirection.x = P.x;
GlobalDirection.y = P.y;
GlobalDirection.z = P.z;
5.每1ms
重复3-4【问题讨论】:
-
即使是 [90, -90] 也应该像这样将音高转换为半径吗?
标签: c++ quaternions euler-angles