c++ - 单元测试欧拉到四元数的实现失败
问题描述
我目前正在尝试实现一个四元数,其中我需要欧拉到四元数的转换。我当前的实现看起来像这样,我从这里删减了
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
预期值是从各种网站获得的,它们产生相同的值,但符号不同,类似于我当前的输出与预期输出的差异。
我还尝试了几种不同的实现,产生了相同类型的失败。
这是由于轮换有几种表示,在这种情况下,我的单元测试失败实际上是假阴性吗?如果是这样,我该如何实施适当的单元测试?
解决方案
通过简单的数学可以推断出您对结果的期望是错误的:z_deg == 180,即 z_rad == PI,将给出zCos
0.0 的值:PI/2 的 cos 为 0.0。知道了这一点,您可以简化, , ,的计算W
,忽略所有带有 的产品。X
Y
Z
zCos
由于 x/2 和 y/2 也位于第一象限,所有xCos
、xSin
、yCos
和ySin
的值zSin
都是正的。因此, 的结果X
必须是负数(0.0 减去一些正数)。而且,结果Y
必须是正数:一些正数乘积加上 0.0。
这仅来自您的代码和给定的参数。结论是,要么期望是错误的,要么您在算法中发现了错误。至少(正如预期的那样)实际结果是合理的:-)
所以,检查你的代码和期望,也许你有来自不同来源的混合实现和期望?或者,如果它们来自同一来源并且您没有犯任何复制错误,则原作者计算错误......
推荐阅读
- apache - 有什么方法可以简化对 apache httpd.conf 文件中特定源 IP 的访问限制
- bash - Bash 处理具有相同变量的多个用户菜单选项
- typescript - 在 Iphone 中使用时需要有关 Dhtmlx 和 wijmo 网格上下文菜单和触摸事件的帮助 - safari
- html - 如何在html中制作这个符号?
- apache-felix - LinkageError:加载程序约束违规 - BundleClassLoader - docx4j
- sql-server - 不允许插入触发器同时执行
- excel - 为多个 Excel UDF 创建帮助文档
- java - 如何将两个数组中的常用词保存到第三个数组中?
- linux - 不使用通配符的预期工具不匹配换行符
- sql-server - ReadUnCommitted 隔离级别不适用于 EF Core