通过四元数旋转坐标系 [英] rotating coordinate system via a quaternion

查看:108
本文介绍了通过四元数旋转坐标系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个表示3d空间中原子的庞大的空间坐标(x,y和z),并且我正在构建一个函数,将这些点转换为新的坐标系.将坐标移动到任意原点很简单,但是我无法绕下下一步:3d点旋转计算.换句话说,我正在尝试将点从(x,y,z)转换为(x',y',z'),其中x',y'和z'分别是i',j'和k',我在 euclid python模块的帮助下制作的新轴矢量.

We have a gazillion spatial coordinates (x, y and z) representing atoms in 3d space, and I'm constructing a function that will translate these points to a new coordinate system. Shifting the coordinates to an arbitrary origin is simple, but I can't wrap my head around the next step: 3d point rotation calculations. In other words, I'm trying to translate the points from (x, y, z) to (x', y', z'), where x', y' and z' are in terms of i', j' and k', the new axis vectors I'm making with the help of the euclid python module.

认为,我要做的只是一个柔和的四元数,即

I think all I need is a euclid quaternion to do this, i.e.

>>> q * Vector3(x, y, z)
Vector3(x', y', z')

但是要做到这一点,我相信我需要一个旋转轴矢量和一个旋转角度.但是我不知道如何从i',j'和k'中计算出这些值.这似乎是一个简单的从头开始编写代码的过程,但是我怀疑这样的事情需要线性代数自行解决.非常感谢您朝着正确的方向前进.

but to make THAT i believe I need a rotation axis vector and an angle of rotation. But I have no idea how to calculate these from i', j' and k'. This seems like a simple procedure to code from scratch, but I suspect something like this requires linear algebra to figure out on my own. Many thanks for a nudge in the right direction.

推荐答案

从代数的角度来看,使用四元数来表示旋转并不困难.就个人而言,我很难用视觉方式推断四元数,但是使用四元数进行旋转所涉及的公式非常简单.我将在此处提供一组基本的引用函数. 1 (另请参见 hosolmaz ,他将它们打包在一起以创建方便的Quaternion类.)

Using quaternions to represent rotation is not difficult from an algebraic point of view. Personally, I find it hard to reason visually about quaternions, but the formulas involved in using them for rotations are quite simple. I'll provide a basic set of reference functions here.1 (See also this lovely answer by hosolmaz, in which he packages these together to create a handy Quaternion class.)

您可以将四元数(出于我们的目的)视为一个标量加上一个3-d向量-抽象为w + xi + yj + zk,这里由一个简单的元组(w, x, y, z)表示. 3-d旋转空间由四元数的子空间( unit 四元数的空间)完全表示,因此您需要确保四元数已标准化.您可以按照将任何4个向量归一化的方式来执行此操作(即,幅度应接近1;如果不是,则按幅度缩小值):

You can think of quaternions (for our purposes) as a scalar plus a 3-d vector -- abstractly, w + xi + yj + zk, here represented by a simple tuple (w, x, y, z). The space of 3-d rotations is represented in full by a sub-space of the quaternions, the space of unit quaternions, so you want to make sure that your quaternions are normalized. You can do so in just the way you would normalize any 4-vector (i.e. magnitude should be close to 1; if it isn't, scale down the values by the magnitude):

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

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

Please note that for simplicity, the following functions assume that quaternion values are already normalized. In practice, you'll need to renormalize them from time to time, but the best way to deal with that will depend on the problem domain. These functions provide just the very basics, for reference purposes only.

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

Every rotation is represented by a unit quaternion, and concatenations of rotations correspond to multiplications of unit quaternions. The formula2 for this is as follows:

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

要旋转四元数的 vector ,您也需要四元数的共轭.很简单:

To rotate a vector by a quaternion, you need the quaternion's conjugate too. That's easy:

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

现在,四元数矢量乘法就像将矢量转换为四元数一样简单(通过设置w = 0并保留xyz相同)然后乘以q * v * q_conjugate(q):

Now quaternion-vector multiplication is as simple as converting a vector into a quaternion (by setting w = 0 and leaving x, y, and z the same) and then multiplying 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在此处清理"输入和输出很有意义.

Finally, you need to know how to convert from axis-angle rotations to quaternions. Also easy! It makes sense to "sanitize" input and output here by calling 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轴上的矢量返回到其原始位置.此代码执行这些轮换:

Here's a quick usage example. A sequence of 90-degree rotations about the x, y, and z axes will return a vector on the y axis to its original position. This code performs those rotations:

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区域.)

Keep in mind that this sequence of rotations won't return all vectors to the same position; for example, for a vector on the x axis, it will correspond to a 90 degree rotation about the y axis. (Keep the right-hand-rule in mind here; a positive rotation about the y axis pushes a vector on the x axis into the negative z region.)

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)

一如既往,如果您在此处发现任何问题,请告诉我.

As always, please let me know if you find any problems here.

1.这些来自OpenGL教程 2.四元数乘法公式看起来像老鼠的巢,但是推导很简单(如果很乏味).首先请注意ii = jj = kk = -1;然后是ij = kjk = iki = j;最后是ji = -kkj = -iik = -j.然后将两个四元数相乘,分配这些项,并根据16个乘法中每一个的结果重新排列它们.这也有助于说明为什么可以使用四元数来表示旋转.最后六个身份遵循右手定则,在从 ij的旋转和围绕 k的旋转之间创建双射,依此类推. sup>

2. The quaternion multiplication formula looks like a rat's nest, but the derivation is simple (if tedious). Just note first that ii = jj = kk = -1; then that ij = k, jk = i, ki = j; and finally that ji = -k, kj = -i, ik = -j. Then multiply the two quaternions, distributing out the terms and rearranging them based on the results of each of the 16 multiplications. This also helps to illustrate why you can use quaternions to represent rotation; the last six identities follow the right-hand rule, creating bijections between rotations from i to j and rotations around k, and so on.

这篇关于通过四元数旋转坐标系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆