将四元数旋转应用于向量时间序列 [英] Applying quaternion rotation to a vector time series

查看:63
本文介绍了将四元数旋转应用于向量时间序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Python numpy 数组中有一个时间序列的 3D 向量,类似于以下内容:

I have a time series of 3D vectors in a Python numpy array similar to the following:

array([[-0.062, -0.024,  1.   ],
       [-0.071, -0.03 ,  0.98 ],
       [-0.08 , -0.035,  0.991],
       [-0.083, -0.035,  0.98 ],
       [-0.083, -0.035,  0.977],
       [-0.082, -0.035,  0.993],
       [-0.08 , -0.034,  1.006],
       [-0.081, -0.032,  1.008],
       .......

我想通过指定的角度围绕指定的轴旋转每个向量 theta.我一直在使用四元数来为一个向量实现这一点,如 here 在 henneray 的回答中所见.>

I want to rotate each vector around a specified axis through a specified angle theta. I have been using quaternions to achieve this for one vector as found here in henneray's answer.

v1 = np.array ([1, -2, 0])
axis = np.array([-4, -2,  3])
theta = 1.5

rot_axis = np.insert(axis, 0, 0, axis=0)
axis_angle = (theta*0.5) * rot_axis/np.linalg.norm(rot_axis)
vec = quat.quaternion(*v1)
qlog = quat.quaternion(*axis_angle)
q = np.exp(qlog)
v_prime = q * vec * np.conjugate(q)
v_prime_vec = v_prime.imag

我的问题是,对 v1 中的每个向量应用相同旋转的最快方法是什么?

My question is, what is the fastest way to apply the same rotation to each vector in v1?

如果 v1 包含向量的二维数组,则不能从 v1 创建四元数,因此我可以使用循环依次旋转每个数组元素;然而,在上面链接中henneray的回答中,提到四元数可以应用于适当矢量化的numpy数组".有没有人对如何实现这一点有任何建议?

You cannot create a quaternion from v1 if v1 contains a 2D array of vectors, so I could use a loop to rotate each array element in turn; however, in henneray's answer in the link above, it is mentioned that the quaternions could be applied to 'appropriately vectorised numpy arrays'. Does anyone has any suggestions on how this could be implemented?

(一个附带问题:如果我的 thetaaxis 变量是与 v1 等长的数组,是否也可以使用相同的方法将 v1 中的每个向量旋转到相应的旋转?)

(A side question: if my theta and axis variables were arrays of equal length to v1, could the same method also be used to rotate each vector in v1 through a corresponding rotation?)

推荐答案

需要先将 [x,y,z] 笛卡尔向量转换为第一个分量为零的 4-向量 [0,x,y,z].然后您可以将其转换为四元数数组以进行矢量化计算.

It is necessary to first convert the [x,y,z] Cartesian vectors into 4-vectors with the first component equal to zero [0,x,y,z]. Then you can cast this to a quaternion array to do vectorised calculations.

下面的这个函数接受一个笛卡尔向量数组,并围绕单个旋转轴旋转它们.您需要确保该轴的范数等于您的旋转角度 theta.

This function below takes an array of Cartesian vectors and rotates them about a single rotation axis. You will need to make sure the norm of this axis is equal to your rotation angle theta.

def rotate_vectors(vecs, axis):
    """
    Rotate a list of 3D [x,y,z] vectors about corresponding 3D axis
    [x,y,z] with norm equal to the rotation angle in radians

    Parameters
    ----------
    vectors : numpy.ndarray with shape [n,3]
        list of [x,y,z] cartesian vector coordinates
    axis : numpy.ndarray with shape [3]
        [x,y,z] axis to rotate corresponding vectors about
    """
    # Make an 4 x n array of zeros
    vecs4 = np.zeros([vecs.shape[0],vecs.shape[1]+1])
    # Fill the imaginary i, j, k components with x, y, z values, leaving the real part w=0
    vecs4[:,1:] = vecs
    # Convert to quaternion array
    vecsq = quat.as_quat_array(vecs4)

    # Make a rotation quaternion
    qrot = quat.from_rotation_vector(axis)
    # Rotate vectors
    vecsq_rotated = qrot * vecsq * qrot.conjugate()
    # Cast quaternion array to float and return only imaginary components (ignore real part)
    return quat.as_float_array(vecsq_rotated)[:,1:]

作为奖励,该函数采用旋转轴数组来将每个向量旋转相应的轴.

As a bonus, this function takes an array of rotation axes to rotate each vector by the corresponding axes.

def rotate_vectors_each(vecs, axes):
    """
    Rotate a list of 3D [x,y,z] vectors about corresponding 3D axes
    [x,y,z] with norm equal to the rotation angle in radians

    Parameters
    ----------
    vectors : numpy.ndarray with shape [n,3]
        list of [x,y,z] cartesian vector coordinates
    axes : numpy.ndarray with shape [n,3]
        axes to rotate corresponding vectors about
        n = pulse shape time domain
        3 = [x,y,z]
    """
    # Make an 4 x n array of zeros
    vecs4 = np.zeros([vecs.shape[0],vecs.shape[1]+1])
    # Fill the imaginary i, j, k components with x, y, z values, leaving the real part w=0
    vecs4[:,1:] = vecs
    # Convert to quaternion array
    vecsq = quat.as_quat_array(vecs4)

    # Make an 4 x n array of zeros
    rots4 = np.zeros([rots.shape[0],rots.shape[1]+1])
    # Fill the imaginary i, j, k components with x, y, z values, leaving the real part w=0
    rots4[:,1:] = rots
    # Convert to quaternion array and take exponential
    qrots = np.exp(quat.as_quat_array(0.5 * rots4))

    # Rotate vectors
    vecsq_rotated = qrots * vecsq * qrots.conjugate()

    return quat.as_float_array(vecsq_rotated)[:,1:]

请注意,在轴角和四元数表示之间进行了如此多的转换,与旋转矩阵代数相比,这将给您带来很小的性能改进.只有当您通过多次连续旋转来旋转向量时,四元数才真正受益,从而可以堆叠四元数乘法.

Note that with so many conversions between axis angle and quaternion representation, this will give you little performance improvement over rotation matrix algebra. Quaternions really only benefit when you are rotating a vector through many sequential rotations, whereby you can stack the quaternion multiplication.

这篇关于将四元数旋转应用于向量时间序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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