单元测试欧拉到四元数实现失败

Unit testing euler-to-quaternion implementation fails

我目前正在尝试实现一个四元数,我需要在其中进行欧拉到四元数的转换。我当前的实现看起来像这样,我从 here

中截取了它
void Quaternion::FromEuler(double x, double y, double z)
{
    z *= Math::DegToRad;
    y *= Math::DegToRad;
    x *= Math::DegToRad;

    double xCos = Math::Cos(x / 2);
    double xSin = Math::Sin(x / 2);
    double yCos = Math::Cos(y / 2);
    double ySin = Math::Sin(y / 2);
    double zCos = Math::Cos(z / 2);
    double zSin = Math::Sin(z / 2);

    W = zCos * yCos * xCos + zSin * ySin * xSin;
    X = zCos * yCos * xSin - zSin * ySin * xCos;
    Y = zSin * yCos * xSin + zCos * ySin * xCos;
    Z = zSin * yCos * xCos - zCos * ySin * xSin;
}

我正在使用以下单元测试来测试实现

TEST(Quaternions, FromEuler)
{
    Quaternion quaternion(45, 90, 180);


    ExpectNear(quaternion, 0.6532815, -0.2705981, 0.6532815, 0.270598);
}

以下方式失败。

  Expected | Actual     
X  0.6533   -0.6533
Y -0.2706    0.2706
Z  0.6533    0.6533
W  0.2706    0.2706

期望值是从各种网站上获取的,得到的值相同,但符号不同,类似于我当前输出与期望输出的差异。

我也尝试了几种不同的实现,产生了相同类型的失败。

这是因为 several representations 的轮换吗?在这种情况下,我的单元测试失败实际上是假阴性?如果是这样,我该如何实施正确的单元测试?

通过简单的数学可以推断出您对结果的期望是错误的:z_deg == 180,即 z_rad == PI,将给出 zCos 值0.0:PI/2 的余弦为 0.0。知道了这一点,就可以简化 WXYZ 的计算,忽略所有 zCos.

的乘积

由于 x/2 和 y/2 也位于第一象限,因此 xCosxSinyCosySin 的所有值和 zSin 是积极的。因此,X 的结果必须为负(0.0 减去一些正积)。而且,Y 的结果必须是正数:一些正数乘积加上 0.0.

这只是根据您的代码和给定的参数得出的。结论是,要么预期是错误的,要么你在你的算法中发现了一个错误。至少(正如预期的那样)实际结果是合理的:-)

那么,检查您的代码和期望,也许您混合了来自不同来源的实现和期望?或者,如果它们来自同一来源并且您没有复制错误,则原作者计算错误...