将四元数转换为欧拉角。 Y角度范围的问题

问题描述 投票:1回答:2

我正在尝试使用Irrlicht作为图形引擎和物理ODE在C ++中编写3D模拟。然后我使用函数将ODE四元数转换为Irrlicht Euler角度。为了做到这一点,我正在使用此代码。

void QuaternionToEuler(const dQuaternion quaternion, vector3df &euler)
{
    dReal w,x,y,z;

    w = quaternion[0];
    x = quaternion[1];
    y = quaternion[2];
    z = quaternion[3];

    double sqw = w*w;    
    double sqx = x*x;    
    double sqy = y*y;    
    double sqz = z*z; 

    euler.Z = (irr::f32) (atan2(2.0 * (x*y + z*w),(sqx - sqy - sqz + sqw)) * (180.0f/irr::core::PI));
    euler.X = (irr::f32) (atan2(2.0 * (y*z + x*w),(-sqx - sqy + sqz + sqw)) * (180.0f/irr::core::PI));          
    euler.Y = (irr::f32) (asin(-2.0 * (x*z - y*w)) * (180.0f/irr::core::PI));

}

它适用于绘制正确的位置和旋转,但问题来自asin指令。它只返回0..90 - 0..-90范围内的值,我需要得到0..360度数的范围。当我打电话给0..360时,至少我需要在node->getRotation().Y范围内获得一个旋转。

c++ math 3d irrlicht ode-library
2个回答
6
投票

欧拉角(任何类型)都具有奇点。在您正在使用的那些特定欧拉角(看起来像Tait-Bryan角度或其某些变化)的情况下,奇点是正负90度的俯仰(Y)。这是欧拉角的固有限制,也是在任何严重情况下很少使用它们的主要原因之一(飞机动力学除外,因为所有飞机的速度矢量(可能不是水平)的俯仰能力非常有限,所以他们很少靠近那个奇点。)

这也意味着您的计算实际上只是两个等效解决方案之一。对于给定的四元数,有两个欧拉角的解决方案,表示相同的旋转,一个在奇点的一侧,另一个与第一个相反。由于两种解决方案都是等效的,因此您只需在最简单的一侧选择一个,即音高在-90到90度之间。

此外,您的代码需要处理接近奇点以避免获得NaN。换句话说,你必须检查你是否接近(具有小的公差)奇异点(-90和90度),如果是这样,使用替代公式(只能计算一个最接近的角度)旋转)。

如果你有任何方法可以完全避免使用欧拉角,我强烈建议你这样做,几乎任何旋转表示都优于欧拉角。 Irrlicht本身使用矩阵,并且还支持通过axis-angle representation设置/获取旋转,这可以更好地工作(并且更容易从四元数中获得,并且没有奇点)。


1
投票

想想地球的地球。它上的每个点只能用纬度(在[-90, 90]范围内)和经度(在[-180, 180]范围内)定义。因此,可以使用这些角度指定球体上的每个点。现在球体上的一个点指定一个向量,球体上的所有点都指定所有可能的向量。所以就像在this article中指出的那样,你使用的公式将产生所有可能的方向。

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.