欧拉角与四元数 - 由内部存储和向用户呈现之间的紧张关系引起的问题?
四元数可以说是表示内部对象旋转的合适选择。 它们可以简单高效地插值并明确地表示单个方向。
然而,在用户界面中呈现四元数通常是不合适的 - 欧拉角通常对用户来说更熟悉,并且它们的值更直观和可预测。
欧拉角在代码级别上很复杂 - 它们需要存储旋转顺序,并且至少可以说,使用该顺序和相关角度组成实际方向(无论是矩阵还是四元数)是很麻烦的。
使用四元数表示最方便地执行可靠的插值 - 那么这是否意味着我们必须在欧拉表示和四元数表示之间不断转换? 这在性能方面可行吗?
我们可以将方向存储为四元数并将其转换为仅显示给用户吗? 这可能是不可能的,因为对于任何给定的方向,只有一个四元数表示,但有许多欧拉表示。 我们如何“选择”与最初定义该方向的欧拉表示相对应的欧拉表示? 这似乎是一项不可能完成的任务——在转换为四元数时我们实际上丢失了信息。
我们可以存储为欧拉角,然后根据需要转换为四元数吗? 这可能是不可扩展的——从欧拉角到四元数的转换、插值,然后再次转换回来可能是相对昂贵的代码。
我们能否简单地存储这两种表示形式并使用最适合任何给定情况的表示形式? 内存方面的巨大成本(想象一下具有大约六十块骨头的骨架的动画曲线)并且保持这些值同步可能是昂贵的,或者至少是麻烦的。
有没有人见过、使用过或想出任何巧妙的解决方案来解决这个问题? 上面的三个选项肯定不是唯一的吗? 是否还有其他类似的问题领域已得到解决?
Quaternions are arguably an appropriate choice for representing object rotations internally. They are simple and efficient to interpolate and represent a single orientation unambiguously.
However, presenting quaternions in the user interface is generally inappropriate - Euler angles are generally much more familiar to users, and their values are a little more intuitive and predictable.
Euler angles suffer from being complicated at the code level - they require that an order of rotation is stored, and composing a practical orientation (be it matrix or quaternion) using this order and associated angles is cumbersome, to say the least.
Reliable interpolations are most conveniently performed using quaternion representation - so does this mean we must convert constantly between an Euler representation and a quaternion representation? Is this feasible in terms of performance?
Can we store the orientations as quaternions and convert them only for displayed to the user? This may not be possible because for any given orientation there is exactly one quaternion representation but many Euler representations. How do we 'pick' the Euler representation that corresponds to the one that originally defined that orientation? It seems like an impossible task - we've effectively lost information when converting to a quaternion.
Could we store as Euler angles and then convert to quaternions as needed? This probably isn't scalable - conversion from an Euler angle to a quaternion, interpolation, and then conversion back again is likely to be relatively expensive code.
Could we simply store both representations and use the most appropriate for any given situation? A large cost in terms of memory (imagine animation curves for a skeleton with around sixty bones) and keeping these values synchronised could be expensive, or at least cumbersome.
Has anybody seen, used or though up any clever solution to this problem? Surely the three options above aren't out only ones? Are there any other problem domains similar to this that have been solved?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我是一名航空航天工程师; 三十年来我一直在使用四元数进行航天器姿态控制和导航。 以下是对您的情况的一些想法:
我有所有这些操作的算法以及更多:四元数到/从任何旋转序列的欧拉角到/从旋转矩阵(方向余弦矩阵),四元数插值匹配位置,速率等在末端或中间点,刚性和灵活使用四元数的身体动力学和运动学。
如果我可以提供帮助,请联系我
[电子邮件受保护]
I am an aerospace engineer; I have been using quaternions for spacecraft attitude control and navigation for going on three decades. Here are some thoughts on your situation:
I have algorithms for all these operations and many more: quaternions to/from Euler angles of any rotation sequence to/from rotation matrices (direction cosine matrices), quaternion interpolation matching position, rate, etc. at end or intermediate points, rigid and flexible body dynamics and kinematics using quaternions.
Please contact me if I can be of assistance at
[email protected]
你12年前问过这个问题,我告诉你你检查的答案是完全错误的。 那家伙不知道自己在说什么。
如果将欧拉角(让我们使用偏航俯仰滚转)的范围限制为 -180 到 180,则每个四元数至少有两组 YPR(偏航俯仰滚转)来表示它。 如果没有额外的假设,就无法知道哪个 YPR 是正确的。
最好的解决方案是始终在内部存储 YPR,然后当您需要进行计算时,将 YPR 转换为四元数。 这才是正确的答案。
使用四元数进行计算将再次产生多种可能的解决方案,但是因为您仅在内部存储 YPR,您将能够使用原始 YPR 来帮助您找到从四元数派生的正确 YPR。
那些拥有30年经验的人并不意味着杰克。 他很可能正在处理一个受限制的系统。 如果 2 个或更多轴的旋转被限制为只能扫描 180 度(在本例中为 -90 到 90),那么并且只有那么每个四元数才会有一个 YPR 表示。 因为这个人是一名航空航天工程师,所以我很确定这就是他正在处理的问题,因为物理万向节通常具有有限的旋转角度。
You asked this question 12 years ago and I am telling you the answer you checked is completely wrong. That guy doesn't know what he's talking about.
If you restrict the domain of Euler Angles (let's go with yaw pitch roll) to -180 to 180, every single quaternion has at least TWO sets of YPRs (yaw pitch roll) that represents it. There is NO WAY to know which YPR is correct without additional assumptions.
The best solution is to ALWAYS store YPRs internally then when you need to do a computation, convert the YPR to a quaternion. That is the proper answer.
Doing computations with quaternions will again yield multiple possible solutions however because you only stored the YPR internally you will be able to use the original YPR to help you find correct YPR that was derived from the Quaternion.
That guys 3 decades of experience doesn't mean jack. Most likely he's dealing with a restricted system. If 2 axises or more of rotation are restricted to only be able to sweep 180 degrees (-90 to 90 in this case), THEN and only THEN will there be a single YPR represented for every quaternion. Because the guy is an aerospace engineer I am pretty sure that's what he's dealing with since physical gimbals usually have restricted angles of rotation.
我是四元数的粉丝。 为了使它们发挥作用,您可以重新考虑向用户展示的内容吗? 您可以选择一些简单的 3D 对象并将四元数旋转应用于该对象,以直观地显示实际的旋转,而不是将旋转以文本形式的一系列欧拉角呈现给用户。
I am a fan of quaternions. In order to make them work, could you reconsider your presentation to the user? Instead of presenting the rotation to the user as a series of Euler angles in text form, you might instead pick some simple 3D object and apply the quaternion rotation to the object to display visually the rotation in effect.
为什么不在代码中使用四元数并在需要显示时将 Q 转换为角度?
Why not use Quarternions in code and convert the Q to angles when needed for display ?
您可以将旋转表示为轴 + 旋转角度,这与四元数本质上相同(最多一个符号)
You can represent the rotation as axis + rotation angle, which is essentially the same as quaternion (up to a sign)
我认为在内部使用欧拉角是没有意义的 - 您将希望在所有计算中使用四元数,并且通常无法承担到处进行的转换。 至于将其转换回 UI 的欧拉角 - 如果用户仅获得与原始输入相同但表示方式不同的角度,那会那么糟糕吗? 如果转换正确,对于任何给定的四元数,您最终应该得到“最简单”的欧拉角。
I don't think it makes sense to use Euler angles internally - you'll want to use quaternions for all your calculations and usually won't be able to afford the conversions going on everywhere. As for the converting it back to Euler angles for the UI - would it be that bad if the user only gets an angle that is equivalent to the original input but is represented differently? If you do the conversion right, you should end up with the "simplest" Euler angles for any given quaternion.
我们谈论的是多少转换。 看起来您为每次转换支付了大约两次超越操作的费用,在现代硬件上,这些操作的速度约为每秒 1 亿次。 我会存储四元数以提高准确性和美观性,并存储欧拉旋转以保留用户信息。 也许添加一个标志来指示对于任何给定对象来说哪个是首选。 最重要的是,您只需为每个轮换成员执行转换一次。 一旦计算出变换矩阵,它就会进行乘加运算,直到用完顶点。
How many conversions are we talking about. It looks like you're paying for about two transcendental operations per conversion, which on modern hardware is available in the order of 100millions per second. I'd store both, Quaternions for accuracy and aesthetics and euler rotations for preserving user info. Maybe add a flag to indicate which is preferred for any given object. On top of that, you only have to perform the conversion once per rotated member. Once you've computed a transformation matrix, its multiply-adds until you run out of vertexes.