将四元数从右手坐标系转换为左手坐标系

Convert quaternion from right-handed to left-handed coordinate system

我的 3d 程序,对象的旋转由四元数表示,如 [0.130526, 0.0, 0.0, 0.991445]。该程序使用 Z 轴朝上的右手坐标系(类似于 3ds max):

另一方面,我的应用程序使用左手坐标系并且Y轴向上:

如何将我的四元数从一个坐标系转换到另一个坐标系,同时考虑哪个轴在上?

角度 x 绕轴 (u,v,w) 的旋转可以用实部 cos(x/2) 虚部 sin(x/2)*(u, v,w).

如果轴坐标在原始三面体中为 (u,v,w),则它们在您的三面体中为 (u,w,v)。

因此,如果原始四元数是 (a,b,c,d) - a+ib+jc+kd - 四元数必须在你的三面体中转换为 (a,b,d,c)。

编辑

但是因为你的三面体是左手的,所以角度也要倒转,所以同样的旋转最终可以用你的三面体中的四元数(a,-b,-d,-c)表示。

这是 an answer 的浓缩版,问题略有不同。

即使两个坐标系同轴,也会出现你问的问题;事实证明,惯用手翻转不会使问题变得更加困难。这是一般的做法。要更改四元数的基础,例如从 ROS(右手,Z 向上)到 Unity(左手,Y 向上):

mat3x3 ros_to_unity = /* construct this by hand by mapping input axes to output axes */;
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行就是的方法:"How do you perform a change-of-basis on a matrix?"

第 5 行很有趣;并非所有矩阵都转换为 quats,但如果 ros_to_unity 正确,则此转换将成功。

请注意,这将为您提供 正确的 结果,但它需要进行大量工作 —— 与矩阵的转换、一些乘法和求逆。但是您可以检查其结果,然后编写一个重新排列或翻转轴的特殊版本,例如 aka.nice derived.

几何代数解法,纯属娱乐。

我会写 uv 来表示向量 u 和 [=] 的 几何乘积 31=]v.
它对于并行向量是可交换的:uv = vuuv,
正交向量的反交换:uv = −vu when uv,
和联想:(uv)w = u(vw) = uvw.
此外,uu = |u|²(长度的平方)。

让 (x, y, z) 成为旧的右手基础。
基中的向量是正交的,所以 xy = −yx, yz = −zy, zx = −xz,
并且长度为 1,所以 xx = yy = zz = 1.

四元数基(1,i,j,k)对应多向量基础 (1, zy, xz, yx).
您可以检查所有四元数身份是否有效。例如:

  • ij = zyxz = −zyzx = zzyx = yx = k,
  • k² = yxyx = −yyxx = −xx = −1,
  • ijk = k² = −1.

旧基础中的四元数可以写为 s + b⋅zy + c⋅xz + d⋅yx.
新基中的四元数可以写为 S + B⋅yz + C⋅xy + D⋅zx。 (我们交换了 yz。)

求解新系数,我们得到S=s,B=−b,C=−d和D=−c。

四元数系数的书写有两种约定:[s, b,c,d][b,c,d, s]

  • [s=0.130526, b=0, c=0, d=0.991445] 转换为 [S=0.130526, B=0, C=-0.991445, D=0].
  • [b=0.130526, c=0, d=0, s=0.991445] 转换为 [B=-0.130526, C=0, D=0, S=0.991445].