【问题标题】:Incorrect conversion from quaternions to euler angles and back从四元数到欧拉角的不正确转换
【发布时间】:2013-02-24 00:48:44
【问题描述】:

我正在将角度轴表示转换为欧拉角。我决定检查并确保我从转换中得到的欧拉角会回到原来的轴角。我打印出值,但它们不匹配!我已经阅读了http://forum.onlineconversion.com/showthread.php?t=5408http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles 以及该网站上的类似转换问题。

在下面的代码中,我从角度“角度”和轴 (rx,ry,rz) 开始,然后将其转换为四元数 (q0,q1,q2,q3)。我将四元数转换为欧拉角(滚动、俯仰、偏航)。然后为了检查它,我将 (roll,pitch,yaw) 转换回轴角为 cAngle 和 (cRx,cRy,cRz)。然后,我对(滚动、俯仰、偏航)进行一些边界检查,以将数字保持在 -pi 和 pi 之间,然后将它们打印出来。应该是cAngle=angle和(cRx,cRy,cRz)=(rx,ry,rz),但是这两个都是错的。

我相信,旋转的顺序是 Z*Y*X,这很常见。我的数学有问题吗?我计划最终在音高为 0 或 PI 时添加特殊情况,如 http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/ 但现在我认为问题是单独的。

        //input is angle 'angle' and axis '(rx,ry,rz)'

        //convert rx,ry,rz, angle, into roll, pitch, yaw
        double q0 = Math.Cos(angle / 2);
        double q1 = Math.Sin(angle / 2) *Math.Cos(rx);
        double q2 = Math.Sin(angle / 2) * Math.Cos(ry);
        double q3 = Math.Sin(angle / 2) * Math.Cos(rz);
        double roll = Math.Atan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1 * q1 + q2 * q2));
        double pitch = Math.Asin(2 * (q0 * q2 - q3 * q1));
        double yaw = Math.Atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3));

        //convert back to angle axis
        double cAngle = 2 * Math.Cos(Math.Cos(roll / 2) * Math.Cos(pitch / 2) * Math.Cos(yaw / 2) + Math.Sin(roll / 2) * Math.Sin(pitch / 2) * Math.Sin(yaw / 2));
        double cRx = Math.Acos((Math.Sin(roll / 2) * Math.Cos(pitch / 2) * Math.Cos(yaw / 2) - Math.Cos(roll / 2) * Math.Sin(pitch / 2) * Math.Sin(yaw / 2)) / Math.Sin(cAngle / 2));
        double cRy = Math.Acos((Math.Cos(roll / 2) * Math.Sin(pitch / 2) * Math.Cos(yaw / 2) + Math.Sin(roll / 2) * Math.Cos(pitch / 2) * Math.Sin(yaw / 2)) / Math.Sin(cAngle / 2));
        double cRz = Math.Acos((Math.Cos(roll / 2) * Math.Cos(pitch / 2) * Math.Sin(yaw / 2) - Math.Sin(roll / 2) * Math.Sin(pitch / 2) * Math.Cos(yaw / 2)) / Math.Sin(cAngle / 2));

        //stay within +/- PI of 0 to keep the number small
        if (roll > 3.1416) roll = -Math.PI + (roll - Math.PI);
        if (roll < -3.1416) roll = Math.PI + (roll - (-1) * Math.PI);
        if (pitch > 3.1416) pitch = -Math.PI + (pitch - Math.PI);
        if (pitch < -3.1416) pitch = Math.PI + (pitch - (-1) * 3.1416F);
        if (yaw > 3.1416) yaw = -Math.PI + (yaw - Math.PI);
        if (yaw < -3.1416) yaw = Math.PI + (yaw - (-1) * Math.PI);

        Console.WriteLine("original angle, axis " + angle + ": " + rx + ", " + ry + ", " + rz);
        Console.WriteLine("converted angle, axis " + cAngle + ": " + cRx + ", " + cRy + ", " + cRz);
        Console.WriteLine("quats " + q0 + ", " + q1 + ", " + q2 + ", " + q3);
        Console.WriteLine("roll,pitch,yaw:  " + roll + ", " + pitch + ", " + yaw);

【问题讨论】:

  • +1。我终于知道四元数是什么了。一分钟内获得的信息比谷歌的几天还要多。希望你能得到答案。

标签: math rotation angle quaternions


【解决方案1】:

我没有(也不会)检查您的代码。 即使您的代码是正确的,您的测试也会因为至少 2 个原因而失败。

也就是说,即使您的转换是正确的,您也可以获得另一种表示,而不是您开始使用的表示。不管你是从欧拉角还是四元数开始。


如果您想测试您的代码,我建议您检查正交单位基向量的旋转。例如将[1, 0, 0] 适当旋转90 度以获得[0, 1, 0]。检查你是否真的得到了预期的[0, 1, 0]等。 如果你得到了所有 3 个基向量的旋转,那么你的代码很可能是正确的。

这个测试的优点是明确,如果你搞砸了一些东西(例如公式中的一个符号),这个测试可以帮助你找到你的错误。


我不会使用欧拉角作为they screw up the stability of your application。他们也是not very handy

【讨论】:

  • 非常感谢您的完整解释。我想我现在会避免欧拉角,我有一个坏主意,就是用它们作为中介来组成旋转矩阵。如果我将四元数直接转换为旋转矩阵并返回(如在 cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche52.html 中),我会遇到同样的问题,还是能够正确测试除基向量以外的值?另外,如果这种方法遮挡了俯仰角,是否可以编写一个特殊情况来避免云台锁定?
  • 只要来回转换就会遇到同样的问题:四元数具有双重覆盖属性。如果您按照我建议的方式进行测试,那么您不会遇到这个问题。您不必测试单位基向量,这只是一个建议。你可以测试你喜欢的任何向量,只要你能以某种方式计算出预期的结果(你可以很容易地计算出你所拥有的单位向量,这就是我建议它们的原因)。旋转矩阵和四元数都不会受到万向节锁定的影响。所以如果你摆脱了欧拉角,你也摆脱了万向节锁定问题。
  • 好的,我现在知道了。太感谢了。我会确保我更正确地理解双重封面。感谢您的测试建议。
  • 我见过一些问题,即围绕单个轴的旋转看起来不错,但组合的 roll-pitch-yaw 旋转有问题;因此,您不应依赖验证单位向量的旋转。
  • @Dave 是的,我知道,谢谢。这就是为什么我说“可能”。这是一个非常简单的测试,可以尽早发现许多错误,尽管它不会保护您免受所有可能的错误的影响。我的代码中有其他更复杂的测试,我通过分析得出预期结果。
【解决方案2】:

使用四元数是不正确的。

我想补充一下这个答案。即使应用程序不正确,人们也会按照惯例使用四元数,因此这很重要。

如果您的旋转对象无法滚动,那么使用四元数来表示您的旋转是不正确的。四元数将 3 个维度的旋转编码到系统中,如果您的系统只有两个,则表示不匹配且不正确。

四元数是一种过于复杂的旋转表示,用于修复万向节锁定并仅对涉及俯仰、偏航和滚动的旋转提供更好的可组合性。

如果你只有俯仰和偏航。四元数变换可以给你一个涉及滚动的答案,这从根本上是不正确的。将滚动角归零不会阻止您的变换具有滚动值。四元数没有用旋转的概念编码,没有滚动,所以在这里使用它是不正确的。

对于只能俯仰和偏航而不能滚动的物体,请使用不涉及“滚动”概念的实体,例如 3D 笛卡尔坐标或球坐标(不是欧拉角)。这就够了,也更正确了。在这些情况下,您不会受到万向节锁定的影响......为此使用四元数不仅是过度杀戮而且是错误的。

【讨论】:

    猜你喜欢
    • 2012-06-21
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 2014-06-28
    • 2013-01-05
    相关资源
    最近更新 更多