一维向量转换为n维向量_如何在N维上固定万向节锁

一维向量转换为n维向量

Gimbal lock is a common issue that arises in 3D rotation systems. Conventional wisdom says that you should represent your rotations as quaternions to avoid this problem (as stated in many popular game engine docs and countless YouTube videos). But I couldn’t find any good explanations of exactly how quaternions solve it.

云台锁定是3D旋转系统中常见的问题。 传统观点认为,应将旋转表示为四元数,以避免出现此问题(如许多流行的游戏引擎文档和无数的YouTube视频所述 )。 但是我找不到关于四元数如何解决它的任何很好的解释。

This was important for me because I was implementing a 4D geometry viewer and spent a lot of time trying to figure out how to generalize quaternions to higher dimensions, only to discover that you can still get gimbal lock with quaternions!

这对我很重要,因为我正在实现4D几何查看器,并花了很多时间试图弄清楚如何将四元数泛化为更高的维度,却发现您仍然可以使用四元数来获得万向节锁定!

The answer is it’s not about what you use to represent your rotations (quaternions, matrices, or rotors), it’s about how you apply those rotations.

答案不在于您用来表示旋转(四元数,矩阵或转子)的意义,而是与如何应用这些旋转有关。

是什么导致云台锁定? (What causes gimbal lock?)

Gimbal lock is the loss of a degree of freedom in a rotation system. It will always happen in any system that uses Euler angles, where you rotate your object by applying a fixed set of successive rotations.

云台锁定是旋转系统中自由度的损失。 在使用Euler角的任何系统中,它都将始终发生,在该系统中,您将通过应用一组固定的连续旋转来旋转对象。

In 3D, this happens when one of the 3 axes of rotation becomes parallel to any other one (or in other words, when the “gimbals” line up). This is shown in the animation below. It starts with the +Z side facing the camera. The first 90 degree rotation places the top cube in a gimbal locked state: rotating by the blue and red gimbals now produce the same rotation. It is not possible in this state to rotate around the cube’s local X axis (pointing towards the camera). This is the degree of freedom we’ve lost and is represented by the red gimbal in the bottom view.

在3D中,当三个旋转轴之一平行于任何另一个旋转轴时(或换句话说,当“万向节”对齐时),就会发生这种情况。 这在下面的动画中显示。 它从面向相机的+ Z面开始。 第一个90度旋转将顶部多维数据集置于万向节锁定状态:通过蓝色和红色万向节旋转现在会产生相同的旋转。 在这种状态下,无法绕立方体的局部X轴旋转(指向摄像机)。 这是我们失去的自由度,在底部视图中用红色的云台表示。

It’s easier to see this by trying it yourself in this demo (requires a keyboard):

通过在本演示中自己尝试(需要键盘),可以更轻松地看到它:

  • Rotate the cubes with W,A,S,D and Q, E

    用W,A,S,D和Q,E旋转立方体
  • R to reset

    R重置

https://gimbal-lock-quaternions.glitch.me/

https://gimbal-lock-quaternions.glitch.me/

The top two cubes use Euler angles, so there will always be a way to get into this gimbal locked state. All you have to do is line up the blue and red gimbals. Then compare the behavior with the bottom two cubes, which show what the correct rotation should be.

最上面的两个立方体使用欧拉角,因此总会有一种进入该云台锁定状态的方法。 您所要做的就是将蓝色和红色的云台对齐。 然后将其行为与最下面的两个立方体进行比较,以显示正确的旋转角度。

Here is pseudocode for how the rotation for the top left cube is implemented:

这是有关如何实现左上方立方体旋转的伪代码:

rotationAroundX = Matrix3.fromAxisAngle(angle1, Xaxis);
rotationAroundY = Matrix3.fromAxisAngle(angle2, Yaxis);
rotationAroundZ = Matrix3.fromAxisAngle(angle3, Zaxis);cubeRotation = rotationAroundX * rotationAroundY * rotationAroundZ;

This is an Euler angle system that uses rotation matrices to represent and apply the rotations. We will get exactly the same behavior if we swap out the matrices for quaternions.

这是一个使用旋转矩阵表示和应用旋转的欧拉角系统。 如果我们将矩阵换成四元数,我们将得到完全相同的行为。

Here is how the top right cube is implemented:

这是实现右上角多维数据集的方式:

rotationAroundX = Quaternion.fromAxisAngle(angle1, Xaxis);
rotationAroundY = Quaternion.fromAxisAngle(angle2, Yaxis);
rotationAroundZ = Quaternion.fromAxisAngle(angle3, Zaxis);cubeRotation = rotationAroundX * rotationAroundY * rotationAroundZ;

This is an Euler angle system that uses quaternions to represent and apply the rotations, and thus also suffers from gimbal lock.

这是一个使用四元数表示和应用旋转的欧拉角系统,因此也遭受了万向节锁定的困扰。

如何固定云台锁? (How do you fix gimbal lock?)

To fix gimbal lock, we must avoid modelling this physical gimbal system.

要修复万向节锁定,我们必须避免对此物理万向节系统建模。

In 3D, instead of using 3 fixed angles that we multiply together to get the final rotation, we will:

在3D中,我们将使用:

  1. Construct a quaternion that describes a rotation around whatever axis we want, and the angle to rotate by.

    构造一个四元数,该四元数描述围绕所需轴旋转的角度以及旋转角度。
  2. Multiply that by the object’s current rotation as represented by a quaternion.

    将其乘以四元数表示的对象的当前旋转。
  3. Take the result and overwrite it back into the object’s current stored rotation.

    获取结果并将其覆盖回该对象的当前存储的旋转。

This is how the bottom right cube in the demo above is implemented. The pseudocode looks like this:

这就是上面演示中右下角的多维数据集的实现方式。 伪代码如下所示:

// We want to rotate by 0.05 radians in this frame.
rotationThisFrame = Quaternion.fromAxisAngle(0.05, arbitraryAxis);cubeRotation = cubeRotation * rotationThisFrame;

Nothing about this technique is unique to quaternions. Here is how the bottom left cube implements this with matrices:

四元数没有什么是这种技术独有的。 这是左下方的多维数据集如何使用矩阵实现此目标的方法:

rotationThisFrame = Matrix3.fromAxisAngle(0.05, arbitraryAxis);cubeRotation = cubeRotation * rotationThisFrame;

The “arbitrary axis” is the cube’s local X/Y/Z axes, depending on what key is pressed. It can instead be the global X/Y/Z axes if we wanted to rotate relative to a fixed global frame.

“任意轴”是立方体的局部X / Y / Z轴,具体取决于所按的键。 如果要相对于固定的全局框架旋转,则可以改为全局X / Y / Z轴。

You can see the full JavaScript code for all 4 rotating cubes here: https://glitch.com/edit/#!/gimbal-lock-quaternions?path=index.html%3A51%3A37

您可以在此处查看所有4个旋转多维数据集的完整JavaScript代码: https : //glitch.com/edit/#!/ gimbal-lock-quaternions ?path= index.html%3A51% 3A37

推广到N维 (Generalizing to N-dimensions)

To generalize this solution to higher dimensions we need two things:

为了将此解决方案推广到更高的维度,我们需要两件事:

  • A way to represent rotations. So far in 3D we’ve used 3x3 matrices and quaternions.

    一种表示旋转的方式。 到目前为止,在3D中,我们已使用3x3矩阵和四元数。
  • A way to describe a rotation around an arbitrary axis.

    描述绕任意轴旋转的一种方法。

Side note: it’s more generalizable to talk about “rotating within a plane” instead of “rotating around an axis”. In 2D there is only one plane of rotation, the XY plane. In 3D there are 3 planes of rotation. In 4D there are 6 planes. In N-D there are (N choose 2) planes.

旁注:谈论“在平面内旋转”而不是“绕轴旋转”更为笼统。 在2D模式下,只有一个旋转平面,即XY平面。 在3D中,有3个旋转平面。 在4D中,有6个平面。 在ND中有(N选择2)个平面。

I ended up choosing 4x4 matrices to represent my rotations, because 4x4 matrix operations are supported on the GPU and so I could rotate the geometry in my vertex shader, in the same way I would in 3D.

我最终选择了4x4矩阵来表示旋转,因为GPU支持4x4矩阵运算,因此可以像在3D中一样旋转顶点着色器中的几何。

So the proposed solution is:

因此,建议的解决方案是:

rotationThisFrame = Matrix4.fromAxisAngle(0.05, arbitraryAxis);cubeRotation = cubeRotation * rotationThisFrame;

Now the tricky part is implementing a Matrix4.fromAxisAngle function. It’s much easier to create a 4x4 rotation matrix for each of the 6 planes of rotations and compose them. So this can be broken down into:

现在,棘手的部分是实现Matrix4.fromAxisAngle函数。 为6个旋转平面中的每一个创建4x4旋转矩阵并进行组合要容易得多。 因此,可以将其分解为:

// Check which key(s) were pressed. In this frame, only the key for rotating in the XZ plane was pressed, so the rXZ 4x4 matrix gets a non-zero angle. rXY = Matrix4.fromXYRotation(0);
rXZ = Matrix4.fromXZRotation(0.05);
rYZ = Matrix4.fromYZRotation(0);
rXW = Matrix4.fromXWRotation(0);
rYW = Matrix4.fromYWRotation(0);
rZW = Matrix4.fromZWRotation(0);rotationThisFrame = rXY * rXZ * rYZ * XW * rYW * rZW;cubeRotation = cubeRotation * rotationThisFrame;

This looks suspiciously like Euler angles, but it’s not. This will never gimbal lock. No matter what orientation the cube ends up in, we can always rotate it by 0.05 radians in any of the 6 planes.

这看起来像可疑的欧拉角,但事实并非如此。 这将永远不会万向节锁定。 无论多维数据集的最终方位如何,我们始终可以在6个平面中的任何一个平面中将其旋转0.05弧度。

To illustrate the difference, here’s a version that will gimbal lock:

为了说明不同之处,下面是一个可以万向锁定的版本:

// Check which key(s) were pressed. In this frame, only the key for the rotating in the XZ plane was pressed, so we add 0.05 to angle2.angle2 += 0.05;rXY = Matrix4.fromXYRotation(angle1);
rXZ = Matrix4.fromXZRotation(angle2);
rYZ = Matrix4.fromYZRotation(angle3);
rXW = Matrix4.fromXWRotation(angle4);
rYW = Matrix4.fromYWRotation(angle5);
rZW = Matrix4.fromZWRotation(angle6);cubeRotation = rXY * rXZ * rYZ * XW * rYW * rZW;

Beyond 4D, you could continue using NxN rotation matrices, but since GPUs don’t support that, I’d use rotors from Geometric Algebra to simplify implementation, which is how you generalize quaternions to higher dimensions.

除了4D,您可以继续使用NxN旋转矩阵,但是由于GPU不支持该矩阵,我将使用Geometric Algebra的转子来简化实现,这是将四元数泛化为更高维度的方式。

I hope you’ve found this post useful in illustrating how to avoid gimbal lock, regardless of how you choose to represent your rotations.

我希望您发现这篇文章对说明如何避免万向节锁定很有用,无论您选择如何表示旋转角度。

If you want to learn more about my 4D geometry work, check out my talk at !!Con. If you’ve found an error in my explanation or something is unclear, you can find me on Twitter (https://twitter.com/omar4ur).

如果您想了解有关我的4D几何工作的更多信息, 请在!! Con上查看我的演讲 。 如果您发现我的解释有误或不清楚,可以在Twitter ( https://twitter.com/omar4ur )上找到我

翻译自: https://medium.com/swlh/how-to-fix-gimbal-lock-in-n-dimensions-f2f7baec2b5e

一维向量转换为n维向量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值