通过四元数旋转坐标系

通过四元数旋转坐标系,第1张

通过四元数旋转坐标系

从代数的角度来看,使用四元数来表示旋转并不困难。就个人而言,我发现很难从 视觉上
对四元数进行推理,但是使用四元数进行旋转所涉及的公式非常简单。我将在此处提供一组基本的参考功能。

您可以将四元数(出于我们的目的)视为一个标量加上一个3-d向量-抽象地

w + xi + yj + zk
表示为此处的一个简单元组
(w, x, y,z)
。3-d旋转空间完全由四元数的子空间( 单位
四元数的空间)表示,因此您需要确保四元数被标准化。您可以按照将任何4个向量归一化的方式进行 *** 作(即,幅度应接近1;否则,将值按幅度缩减):

def normalize(v, tolerance=0.00001):    mag2 = sum(n * n for n in v)    if abs(mag2 - 1.0) > tolerance:        mag = sqrt(mag2)        v = tuple(n / mag for n in v)    return v

请注意,为简单起见,以下函数假定四元数值 已标准化
。在实践中,您将需要不时地对它们进行规范化,但是最好的解决方法将取决于问题域。这些功能仅提供基本信息,仅供参考。

每次旋转都用一个单位四元数表示,旋转的级联对应于单位四元数的 乘法 。公式2如下:

def q_mult(q1, q2):    w1, x1, y1, z1 = q1    w2, x2, y2, z2 = q2    w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2    x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2    y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2    z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2    return w, x, y, z

要通过四元数旋转 向量 ,还需要四元数的共轭。这很容易:

def q_conjugate(q):    w, x, y, z = q    return (w, -x, -y, -z)

现在四元数-向量乘法很简单,只要矢量变换成四元数(通过设置

w = 0
和离开
x
y
以及
z
相同的),然后乘以
q * v *q_conjugate(q)

def qv_mult(q1, v1):    q2 = (0.0,) + v1    return q_mult(q_mult(q1, q2), q_conjugate(q1))[1:]

最后,您需要知道如何将轴角旋转转换为四元数。还容易!在这里通过调用“清理”输入和输出是有意义的

normalize

def axisangle_to_q(v, theta):    v = normalize(v)    x, y, z = v    theta /= 2    w = cos(theta)    x = x * sin(theta)    y = y * sin(theta)    z = z * sin(theta)    return w, x, y, z

然后回来:

def q_to_axisangle(q):    w, v = q[0], q[1:]    theta = acos(w) * 2.0    return normalize(v), theta

这是一个快速使用示例。绕x,y和z轴旋转90度的序列会将y轴上的向量返回到其原始位置。此代码执行这些旋转:

x_axis_unit = (1, 0, 0)y_axis_unit = (0, 1, 0)z_axis_unit = (0, 0, 1)r1 = axisangle_to_q(x_axis_unit, numpy.pi / 2)r2 = axisangle_to_q(y_axis_unit, numpy.pi / 2)r3 = axisangle_to_q(z_axis_unit, numpy.pi / 2)v = qv_mult(r1, y_axis_unit)v = qv_mult(r2, v)v = qv_mult(r3, v)print v# output: (0.0, 1.0, 2.220446049250313e-16)

请记住,这种旋转顺序不会将 所有
矢量返回到相同位置。例如,对于x轴上的矢量,它将对应于围绕y轴旋转90度。(此处请牢记右手法则;围绕y轴的正向旋转会将x轴上的矢量推入z 负向 区域。)

v = qv_mult(r1, x_axis_unit)v = qv_mult(r2, v)v = qv_mult(r3, v)print v# output: (4.930380657631324e-32, 2.220446049250313e-16, -1.0)

与往常一样,如果您在此处发现任何问题,请告诉我。


1.这些改编自此处存档的OpenGL教程。

2.四元数乘法公式看起来像老鼠的巢,但是推导很简单(如果很乏味)。首先请注意

ii = jj = kk = -1
; 那么
ij = k
jk =i
ki = j
; 最后是
ji = -k
kj = -i
ik =-j
。然后将两个四元数相乘,分配这些项并根据16个乘法中每一个的结果重新排列它们。这也有助于说明 为什么
可以使用四元数来表示旋转。最后六个恒等式遵循右手定则,在
i
到的
j
旋转与 围绕的 旋转之间创建双射
k
,依此类推。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5647750.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存