四元数< - >欧拉

时间:2013-03-03 15:38:25

标签: quaternions

我正在使用C#,在我的程序中,我在Quaternions中收到一个ridigbody的四元数,但轴与我使用的轴的方向不对应,所以我想旋转四元数。为了做到这一点,我将四元数转换为欧拉角,切换音高,偏航和滚动,使其与我的坐标系相对应,将其转换回四元数,然后生成一个旋转矩阵来转换位置。

然而出现问题,当我只是将相同的输入从四元数转换为euler并返回时我得到另一个四元数...所以其中一个函数出错了我不知道在哪里......

Quaternion q = new Quaternion(-0.4, -0.7, -0.8, 0.5);

double yaw = 0, pitch = 0, roll = 0;
toEuler(q, ref yaw, ref pitch, ref roll);

Quaternion quat = ToQ((float)(yaw), (float)(pitch), (float)(roll));





private void toEuler(Quaternion q, ref double x, ref double y, ref double z)
        {
            double test = q.X * q.Y + q.Z * q.W;
            if (test > 0.499)                            // singularity at north pole
            {
                y = 2.0F * System.Math.Atan2(q.X, q.W);
                z = Math.PI / 2.0F;
                x = 0.0F;
                return;
            }

            if (test < -0.499)                           // singularity at south pole
            {
                y = -2.0F * System.Math.Atan2(q.X, q.W);
                z = -Math.PI / 2.0F;
                x = 0.0F;
                return;
            }

            double sqx = q.X * q.X;
            double sqy = q.Y * q.Y;
            double sqz = q.Z * q.Z;
            y = System.Math.Atan2(2.0F * q.Y * q.W - 2.0 * q.X * q.Z, 1.0F - 2.0 * sqy - 2.0 * sqz);
            z = System.Math.Asin(2.0F * test);
            x = System.Math.Atan2(2.0 * q.X * q.W - 2.0 * q.Y * q.Z, 1.0F - 2.0 * sqx - 2.0 * sqz);
        }

 public Quaternion ToQ(float yaw, float pitch, float roll)
        {
            float rollOver2 = roll * 0.5f;
            float sinRollOver2 = (float)Math.Sin((double)rollOver2);
            float cosRollOver2 = (float)Math.Cos((double)rollOver2);
            float pitchOver2 = pitch * 0.5f;
            float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
            float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
            float yawOver2 = yaw * 0.5f;
            float sinYawOver2 = (float)Math.Sin((double)yawOver2);
            float cosYawOver2 = (float)Math.Cos((double)yawOver2);
            Quaternion result = new Quaternion();
            result.W = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2;
            result.X = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2;
            result.Y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2;
            result.Z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2;

            return result;
        }

3 个答案:

答案 0 :(得分:2)

您的四元数似乎没有标准化。表示旋转的四元数应该具有范数1.

答案 1 :(得分:1)

要扩展Ben的答案,请通过除以平方和的平方根来规范化四元数。

如果需要旋转四元数并保持其长度,我建议使用四元数进行旋转。维基百科有一个很棒的页面: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

答案 2 :(得分:0)

请确保您使用相同的Euler Angels转换为“to”和“from”。

您可以从Ken Shoemake找到很好的参考代码 http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/

文章“欧拉角转换”Ken Shoemake来自“图形宝石”系列