从代数的角度来看,使用四元数来表示旋转并不困难。就个人而言,我发现很难从 视觉上
对四元数进行推理,但是使用四元数进行旋转所涉及的公式非常简单。我将在此处提供一组基本的参考功能。
您可以将四元数(出于我们的目的)视为一个标量加上一个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,依此类推。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)