欧拉角与四元数 - 内部存储和呈现给用户之间的紧张关系引起的问题?

Posted

技术标签:

【中文标题】欧拉角与四元数 - 内部存储和呈现给用户之间的紧张关系引起的问题?【英文标题】:Euler angles vs. Quaternions - problems caused by the tension between internal storage and presentation to the user? 【发布时间】:2010-10-24 09:15:13 【问题描述】:

四元数可以说是在内部表示对象旋转的合适选择。它们可以简单高效地插值并明确表示单个方向。

但是,在用户界面中呈现四元数通常是不合适的 - 欧拉角通常对用户来说更熟悉,并且它们的值更直观和可预测。

欧拉角在代码级别受到复杂影响 - 它们需要存储旋转顺序,并且使用此顺序和相关角度组成实际方向(无论是矩阵还是四元数)至少可以说很麻烦。

使用四元数表示最方便地执行可靠插值 - 那么这是否意味着我们必须在欧拉表示和四元数表示之间不断转换?这在性能方面是否可行?

我们可以将方向存储为四元数并将它们转换为仅显示给用户吗?这可能是不可能的,因为对于任何给定的方向,只有一个四元数表示,但有许多欧拉表示。我们如何“挑选”对应于最初定义该方向的欧拉表示?这似乎是一项不可能完成的任务 - 我们在转换为四元数时实际上丢失了信息。

我们可以存储为欧拉角,然后根据需要转换为四元数吗?这可能是不可扩展的 - 从欧拉角到四元数的转换、插值,然后再转换回来可能是相对昂贵的代码。

我们是否可以简单地存储这两种表示并使用最适合任何给定情况的表示?内存方面的大量成本(想象一下具有大约 60 根骨骼的骨骼的动画曲线)并保持这些值同步可能会很昂贵,或者至少很麻烦。

有没有人看到、使用或提出过任何聪明的解决方案来解决这个问题?上面的三个选项肯定不是唯一的吗?还有其他类似的问题域已经解决了吗?

【问题讨论】:

【参考方案1】:

我是一名航空工程师;三年来,我一直在使用四元数进行航天器姿态控制和导航。以下是对您的情况的一些想法:

    执行任何改变欧拉角方向的过程几乎是不可能的。欧拉角受到奇点的影响——当其他角度通过奇点时,角度会瞬间变化多达 180 度;欧拉角几乎不可能用于连续旋转。四元数不会遇到这些问题 有 12 种不同的可能的欧拉角旋转序列 - XYZ、XYX、XZY 等。没有一组“最简单”或“正确”的欧拉角。要导出一组欧拉角,您必须知道您使用的是哪种旋转序列并坚持下去。 我建议您使用四元数执行所有存储和旋转操作,并且仅在需要输出时将四元数转换为欧拉角。执行此操作时,您必须定义所使用的欧拉旋转序列。

我有所有这些操作的算法以及更多:四元数到/从任何旋转序列的欧拉角到/从旋转矩阵(方向余弦矩阵),四元数插值匹配位置,速率等在端点或中间点,使用四元数的刚体和柔体动力学和运动学。

如果我能提供帮助,请与我联系 nhughes1ster@gmail.com

【讨论】:

接受这个答案,因为它似乎拥有最多的选票。然而,1)是的,不幸的是我在动画领域工作,艺术家希望有欧拉角 2)是的,动画师希望能够任意设置他们骨骼的旋转顺序,所以我必须支持所有排列 3 ) 这或多或少是我最终所做的。【参考方案2】:

你在 12 年前问过这个问题,我告诉你你检查的答案是完全错误的。那家伙不知道他在说什么。

如果将欧拉角的域(让我们使用偏航俯仰滚动)限制为 -180 到 180,则每个四元数至少有两组 YPR(偏航俯仰滚动)来表示它。如果没有额外的假设,就无法知道哪个 YPR 是正确的。

最好的解决方案是始终在内部存储 YPR,然后当您需要进行计算时,将 YPR 转换为四元数。这是正确的答案。

使用四元数进行计算将再次产生多种可能的解决方案,但是因为您只在内部存储了 YPR,您将能够使用原始 YPR 来帮助您找到从四元数派生的正确 YPR。

这家伙 3 年的经验并不意味着杰克。很可能他正在处理一个受限系统。如果 2 个或更多轴的旋转被限制为只能扫过 180 度(在这种情况下为 -90 到 90),那么只有 THEN 才会为每个四元数表示一个 YPR。因为这家伙是一名航空工程师,所以我很确定这就是他正在处理的问题,因为物理云台通常具有有限的旋转角度。

【讨论】:

假设您不需要确切的 YPR 值,而只需要生成的旋转:除了更大的计算量之外,您为什么还要在系统中引入歧义/复杂性(假设 YPR/在每一步都指定 YPR)加载?在大多数应用程序中,您需要最终的方向,因此确切的 YPR 值无关紧要。此外,根据机器人技术的要求将欧拉角转换为不同的坐标系听起来并不有趣。 @baumflaum 四元数是一个幻想值,就像虚数一样。如果我想向物理云台呈现真正的旋转,我必须给那个云台一个 YPR。云台上的每个电机都需要知道转动多少弧度。四元数在物理世界中是无用的。所有轴上限制为 -180 到 180 的物理云台对于每个四元数有两个 YPR。这不是数学技巧。 @baumflaum 物理云台本身对于每个方向的电机总共有 2 组或 YPR 旋转,可以在空间中实现相同的方向。这很重要,因为无论万向节处于何种旋转配置,其最大运动范围的相对阈值都是不同的。四元数掩盖了物理万向节中的这种二元性。如果您将 ypr 的音高限制在 -90 到 90 之间,则这种二元性不再存在。 @baumflaum 您处理过的机器人系统可能已经这样做了……如果这样做了,那么是的……从正单位四元数到受限 YPR 和库之间存在一对一的映射可以抽象出触摸 YPR 的需要(尽管 ypr 仍然是发送到电机的命令) 检查您的机器人云台。一个轴必须特别限制为 180 度扫掠,而其他轴则开放为 360 度扫掠。【参考方案3】:

我是四元数的粉丝。为了让它们发挥作用,你能重新考虑你向用户展示的内容吗?您可以选择一些简单的 3D 对象并将四元数旋转应用于对象,以直观地显示旋转的效果,而不是以文本形式将旋转呈现给用户。

【讨论】:

如果只是 :) 但如果你能在实践中侥幸成功,我会感到惊讶。据我所知,3D 艺术家的正常工作流程几乎总是涉及了解实际数字 - 所以虽然您可能会为他们提供 Max/Maya 风格的旋转小工具,但在某些时候他们会希望旋转是 正好 30度,或者至少看看那个旋转是什么。【参考方案4】:

为什么不在代码中使用 Quarternions 并在需要显示时将 Q 转换为角度?

【讨论】:

您的意思是存储为四元数并根据需要转换为欧拉角?由于我上面概述的原因 - 单一方向有许多欧拉表示......你向用户展示哪一个? 你为什么不选择一个约定?假设在实验室框架中旋转两次,在身体框架中旋转一次。这需要您为每个对象保留身体坐标,但艺术家可能会喜欢这样。【参考方案5】:

您可以将旋转表示为轴+旋转角度,这与四元数基本相同(最多一个符号)

【讨论】:

【参考方案6】:

我认为在内部使用欧拉角是没有意义的 - 您会希望在所有计算中都使用四元数,而且通常无法承受到处进行的转换。至于将其转换回 UI 的欧拉角 - 如果用户只获得与原始输入等效但表示方式不同的角度,那会不会很糟糕?如果你正确地转换,你应该得到任何给定四元数的“最简单”的欧拉角。

【讨论】:

我很想摆脱这个问题,但我怀疑在实践中“最简单的”欧拉角对于艺术家来说几乎和四元数一样难以处理(因为它们并不总是直观的) )。我认为以曲线形式呈现的动画数据会带来特别的挑战,因为它可能看起来与艺术家所期望的完全不同。【参考方案7】:

我们谈论的是多少次转化。看起来您为每次转换支付了大约两个先验操作,在现代硬件上,这些操作以每秒 1 亿次的数量级可用。我会同时存储四元数以确保准确性和美观,并存储欧拉旋转以保留用户信息。也许添加一个标志来指示任何给定对象的首选。最重要的是,您只需为每个轮换成员执行一次转换。一旦你计算了一个变换矩阵,它的乘法-加法直到你用完顶点。

【讨论】:

如果我担心每个顶点的成本或执行转换以进行渲染,这将是正确的 - 我主要关心将多个动画混合在一起以获得骨架。所以我们谈论的是大约 50 根骨头,可能同时有 5 到 10 个动画处于活动状态。在这个阶段,我希望将动画数据存储为四元数,但我还需要将动画曲线以欧拉角的形式呈现给用户。 10 个 body 有 50 个成员,每个是 500 个成员,乘以 72 fps 是 36000 次转换。不是很多。你可以做 1000 次,但仍然使用很少的 CPU 这很好。也许在将其作为解决方案注销之前确实需要对其进行分析。但是,必须不断转换似乎太不雅了!顺便说一句,它不是 10 个单独的角色和 50 根骨头,它是一个单独的角色,有 10 个同时活动的动画并在它们之间混合(即快走和上半身转身的行走)。但我怀疑计算是一样的。

以上是关于欧拉角与四元数 - 内部存储和呈现给用户之间的紧张关系引起的问题?的主要内容,如果未能解决你的问题,请参考以下文章

欧拉角与四元数互转,及四元数slerp球面线性插值算法

欧拉角与四元数(计算,编程)

欧拉角与四元数转换——编程

3D图形:矩阵、欧拉角、四元数与方位的故事

轴角与四元数的利弊

Unity编程四元数(Quaternion)与欧拉角