python - 将四元数旋转应用于向量时间序列

标签 python numpy vector vectorization quaternions

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

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在亨内雷的回答中。

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 中的每个向量应用相同旋转的最快方法是什么?

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

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

最佳答案

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

下面的这个函数采用笛卡尔向量数组并围绕单个旋转轴旋转它们。您需要确保该轴的范数等于您的旋转角度 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:]

作为奖励,此函数采用旋转轴数组来按相应的轴旋转每个向量。

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:]

请注意,轴角度和四元数表示之间有如此多的转换,与旋转矩阵代数相比,这几乎不会带来性能改进。四元数实际上只有在通过多次连续旋转来旋转向量时才会受益,从而可以堆叠四元数乘法。

关于python - 将四元数旋转应用于向量时间序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64988678/

相关文章:

loops - 展开向量中的(开始,结束)对

python - 快速重新排列文本文件

python - vmprof : Example config. ini 文件 : configparser. MissingSectionHeaderError

python - django local_settings导入错误

python - 如何修复签名中 Tensorflow 1.14.0rc 中的 'strided slice assignment are not compatible with expected types'?

python - 如何在损失函数中的 keras 张量上使用 numpy 函数?

python - 如何从多个相同长度的列表中获取 numpy 数组并沿轴排序?

python - 寻找良好的索引和稀疏矩阵方法以从现有矩阵创建矩阵

java - 执行哈希表的包含操作

c++ - 在 C++ 中初始化 vector 时获取错误消息