【问题标题】:What is the difference between a "unit" quaternion and an "identity" quaternion?“单位”四元数和“身份”四元数有什么区别?
【发布时间】:2020-03-05 22:27:43
【问题描述】:

我一直在使用 www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ 上的指南来学习 OpenGL。本指南说...

glm::quat q;

...创建一个身份四元数(无旋转)。

实验表明q = [0, 0, 0, 0]。使用它作为根骨骼的父方向会导致根本不旋转任何骨骼。他们失去了所有的轮换。

指南说...

四元数是 4 个数字的集合,[x y z w],表示旋转如下:

// RotationAngle 以弧度为单位

x = RotationAxis.x * sin(RotationAngle / 2)

y = RotationAxis.y * sin(RotationAngle / 2)

z = RotationAxis.z * sin(RotationAngle / 2)

w = cos(RotationAngle / 2)

...和...

[0 0 0 1] (w=1) 表示角度 = 2*acos(1) = 0,所以这是一个单位四元数,完全不旋转。

我一直在试验一个骨架系统,其中每个骨骼在应用自己的旋转之前继承其父级的方向。

如果我使用“身份”四元数作为根骨骼的“父”方向,则根本不会旋转任何骨骼。如果我使用“单位”旋转,一切都很好。

当我将骨骼的初始方向设置为“身份”或“单位”四元数时,它会按我的意愿显示。但是,当我将用户输入的欧拉角转换为一个方向时,我会旋转 180 度。我所做的转换是:

        glm::vec3 eulers(glm::radians(pose.lng_rotate),
                         glm::radians(pose.lat_rotate),
                         glm::radians(pose.att_rotate));

        pose.orientation = glm::quat(eulers);

注意:我在这里使用“lng”、“lat”和“att”旋转,因为当骨骼继承父旋转时,“x”轴可能不再是“x”轴了。

我注意到的最后一件奇怪的事情是我在每种类型的四元数上使用了glm::mat4_cast,然后乘以一个标识glm::vec4。 “恒等”四元数使向量保持不变,但“单位”四元数使向量反转(乘以 -1)向量的 x 和 y 分量。

我想更好地理解四元数,尤其是关于它们在代码中的使用。

从概念上讲,“单位”四元数与“身份”四元数有何不同?

我应该在哪里使用“单位”四元数,我应该在哪里使用“身份”四元数?

我只是被写得不好的指南弄糊涂了吗?

【问题讨论】:

  • "实验表明 q = [0, 0, 0, 0]。" 证明它。全零的四元数不是“身份四元数”。我不认为 GLM 有这么糟糕的编码会有这样的错误。
  • @Nicol 我只是做了glm::quat q; printf("%s, %s, %s, %s\n", std::to_string(q.x).c_str(), std::to_string(q.y).c_str(), std::to_string(q.z).c_str(), std::to_string(q.w).c_str()); 我使用字符串转换的原因是因为底层类型有些奇怪,使用 %f 或 %lf 会导致显示奇怪的值。我懒得弄清楚为什么。
  • 我做了更多的实验,发现glm::quat(1.0, 0.0, 0.0, 0.0) 工作得很好。我没有注意到,尽管指南将四元数表示为 [x, y, z, w],但它声明您将其显式初始化为 glm::quat(w,x,y,z)
  • 这个问题的标题是理想的标题。无需进一步阅读即可理解。它应该仅针对该属性进行投票。

标签: 3d rotation


【解决方案1】:

单位四元数与恒等四元数不同。四元数是“四元数空间”中的任意数字,例如 3 + 2i - 7j + 6k

当我们使用四元数来计算旋转时,我们总是在谈论单位四元数,并且总是长度为 1,就像单位向量一样。乘以单位四元数是计算旋转的一种非常有效的方法,但长度必须保持不变,即 1。

恒等四元数是不会改变任何与之相乘的四元数的四元数,因此是1 + 0i + 0j + 0k1。因此,恒等四元数是无的旋转。

【讨论】:

  • * i、j 和 k 是 glm 中的 x、y 和 z。 w 是“实数”。
  • 根据问题,在线指南说“......所以这是一个单位四元数,根本不旋转”。我认为您的回答很有意义,并且根据我接受的回答,该指南显然是错误的,因此我无法对您的回答提出异议,但是如果您可以包含对您的定义的权威参考,那就太好了。
  • 我的教科书已经没有了,但是 3Blue1Brown 的视频可以更好地解释它。 https://www.youtube.com/watch?v=d4EgbgTm0Bg 以及单位四元数的 [en.wikipedia.org/wiki/Quaternion#Unit_quaternion](wiki) 上的定义。
  • Joan Solà 的文档“用于错误状态卡尔曼滤波器的四元数运动学”对四元数的所有风格都有完整而出色的解释:iri.upc.edu/people/jsola/JoanSola/objectes/notes/kinematics.pdf
  • 重新审视这个问题,我已经接受了这个答案而不是我的答案。但是请注意,官方 OpenGL 指南声明“......所以这是一个单位四元数,根本不旋转”,因此根据指南,它们是相同的。该指南确实需要重写。
【解决方案2】:

单位和身份四元数是一回事。该指南写得不好且令人困惑。

glm::quat q; 确实 NOT 创建身份四元数。它创建了一个无效的四元数。创建身份四元数的最佳方法是通过glm::quat q(glm::vec3(0.0, 0.0, 0.0));glm::quat q(1.0, 0.0, 0.0, 0.0);。第一个基于全零欧拉旋转的向量生成四元数。第二个将其显式初始化为身份四元数。

请注意,虽然四元数通常被描述为[x y z w],但它们被存储和初始化为(w, x, y, z)

【讨论】:

  • 它们存储为 x,y,z,w
  • @Krum,没有 glm::quat 将值存储为 w,x,y,z
  • @ravenisadesk 不适用于最近的 glm 版本:“默认情况下,GLM 以 x、y、z、w 顺序存储四元数组件。GLM_FORCE_QUAT_DATA_WXYZ 允许将四元数数据存储切换到 w、x、y、 z 顺序。” (GLM manual)
  • 请注意,您还可以使用glm::identity<glm::quat>() 来实例化一个身份四元数。
  • 我对 OpenGL 不是很有经验,但是单位和身份四元数绝对不一样。正如@JustNewHere 回应的那样,单位四元数的范数等于1,而恒等四元数是1+0i+0j+0k。您可以将身份四元数视为单位四元数的子集,但并不相同。
猜你喜欢
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 2011-04-30
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 2019-05-30
  • 1970-01-01
相关资源
最近更新 更多