从右手坐标系翻转四元数到左手坐标系

11

我需要将一个四元数从右手坐标系转换为左手坐标系:

x = 从左到右
y = 从前到后
z = 从上到下

转换后的左手坐标系为:

x = 从左到右
y = 从上到下
z = 从前到后

应该如何进行此操作?


1
请解释一下你实际想要做什么。就目前而言,你的问题没有意义。不理解如何做某事是可以的,但你必须提供完整的故事。我的猜测是,你的问题应该像这样:“我有一个四元数,表示三维旋转,但因为我使用的坐标系与预期的坐标系在这个特定的方面不同,所以四元数并不能表示我想要的旋转。我该如何将其转换为能够实现我想要的旋转的四元数?”这几乎是https://dev59.com/R3M_5IYBdhLWcg3wt1g0的重复。 - Anton Geraschenko
2
我原本认为不需要提供更多信息,但是这个表示一个旋转或者方向在三维空间中,其中z轴朝上。 现在我需要交换z和y轴,使得y轴朝上。是的,这与我的另一个问题类似,因为我试图实现相同的目标,但它们是两个不同的问题。 - cmann
6个回答

11

我不认为这些答案中有任何一个是正确的。

安德烈斯是正确的,四元数没有手性(*)。手性(或者我所说的“轴约定”)是人类应用的一种属性;它是我们将“前进,向右,向上”的概念映射到X、Y、Z轴的方式。

这些事情是真的:

  • 纯旋转矩阵(正交、行列式为1等)可以转换为单位四元数并返回,恢复原始矩阵。
  • 不是纯旋转的矩阵(行列式为-1的矩阵,例如翻转单个轴的矩阵)也称为“不适当的旋转”,不能转换为单位四元数并返回。您的mat_to_quat()例程可能不会崩溃,但它不会给出正确答案(在这样的意义下,quat_to_mat(mat_to_quat(M)) == M不成立)。
  • 交换手性的基变换行列式为-1。它是一个不适当的旋转:等价于绕原点旋转(可能是身份)与关于原点的镜像组合。

要更改四元数的基,比如从ROS(右手)到Unity(左手),我们可以使用.的方法。

mat3x3 ros_to_unity = /* construct this by hand */;
mat3x3 unity_to_ros = ros_to_unity.inverse();
quat q_ros = ...;
mat3x3 m_unity = ros_to_unity * mat3x3(q_ros) * unity_to_ros ;
quat q_unity = mat_to_quat(m_unity);

第1至4行只是https://dev59.com/R3M_5IYBdhLWcg3wt1g0#39519079中的方法:“如何对矩阵执行基变换?”

第5行很有趣。我们知道mat_to_quat()仅适用于纯旋转矩阵。我们怎么知道m_unity是一个纯旋转矩阵?它很可能不是,因为unity_to_rosros_to_unity都具有行列式-1(这是由于左右手性切换的结果)。

模糊的答案是手性会切换两次,因此结果没有手性切换。更深入的答案与相似变换保留运算符的某些方面有关,但我没有足够的数学来证明。

请注意,这将给出一个正确的结果,但如果unity_to_ros是一个简单的矩阵(例如,只有轴交换),那么您可能可以更快地完成它。但是,您应该通过扩展此处所做的数学来导出更快的方法。

(*) 实际上,存在Hamilton和JPL四元数之间的区别;但是每个人都使用Hamilton,所以没有必要用它来混淆问题。


7

我认为解决方案是:

Given:    Right Hand: {w,x,y,z}
Convert:  Left Hand: {-w,z,y,x}

在Unity中:
 new Quaternion(rhQz,rhQy,rhQx,-rhQw)

这是实际起作用的内容;唯一需要的是我们需要 {y,z,-w,x}(所以'y'需要否定)。不过这可能是因为我做错了什么;这是在一个OpenGL应用程序中,我计算了一个modelView矩阵,然后将其作为四元数发送到Unity,并尝试在那里设置相机。 - Ruud van Gaal
除非您使用非常奇怪的四元数数据结构,否则这不应该起作用。 w值通常是元组中的第一个或最后一个值,并且与任何空间方向都没有直接关联,因此它永远不应该出现在第三个位置。 - Sty
我试图将一个骨骼的旋转从一个手性不同的骨架调整到另一个骨架,我认为这个方法优雅地解决了我的问题!谢谢! - Logic1
也许我在翻译中搞错了什么,但由于某种原因,选项1与选项2不等同。我尝试将它们设置到Unity3D编辑器中的相机中。对我来说,选项2可行。 - Sepehr
1
好奇,你如何在数学上证明它们相等?是基于它们的点积吗? - Sepehr

6
好的,为了明确起见,四元数实际上没有“左右手定则”(请参见维基百科关于四元数的文章)。然而,从四元数到矩阵的转换确实与“左右手定则”有关。请参见http://osdir.com/ml/games.devel.algorithms/2002-11/msg00318.html。如果您的代码执行此转换,您可能需要有两个不同的函数来将其转换为左手坐标系或右手坐标系的矩阵。
希望能够帮助到您。

4
我认为用户真正想问的是“更改基的左右手性如何影响我的旋转四元数?”这是一个合理的问题。方向是与向量空间相关的数据,而不是其变换(包括四元数和矩阵表示)。 - rschwieb
那个osdir线程是不正确的。从四元数到3x3矩阵的转换不涉及任何手性。它纯粹是“解出矩阵M,使得Mv = qv”(假设你正在使用列向量)。请参见http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/以获取推导过程。 - Paul Du Bois

2

一旦你这样做了,你就不再有一个四元数了,即通常的乘法规则将不起作用。如果你交换j和k(在右手坐标系中是y和z),那么等式i^2 = j^2 = k^2 = ijk = -1将不再成立。


1
那么你的意思是你不能改变四元数吗? - cmann
@cmann 如果你想保留通常的属性,就不能这样做。我想可以派生出一个全新的LH四元数规则集......但为什么呢?你试图达到什么目的?也许有更简单的方法;可能是将LH转换为RH坐标,执行旋转或其他操作,然后再转换回LH系统? - Jim Lewis
2
我正在尝试将数据从Blender导出到OpenGL。 - cmann

0

1
你引用的帖子实际上回答了一个不同的问题 - 原帖作者似乎使用“左手”来表示“相反方向旋转”。这与cmann想要做的交换Y和Z轴非常不同。 - Jim Lewis

0

我知道这个问题很老了,但下面的方法经过测试可行。 我使用pyquaternion来操作四元数。

从右手坐标系转换到左手坐标系。 找到右手四元数的轴和角度。 然后将轴转换为左手坐标系。 取负右手角度以获得左手角度。 使用左手坐标系和左手角度构造四元数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接