벡터 시계열에 쿼터니언 회전 적용
다음과 유사한 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
. 내가 발견 한 벡터 이것을 달성하기 위해 사원 수를 사용하고 여기 henneray의 대답.
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의 각 벡터에 동일한 회전을 적용하는 가장 빠른 방법은 무엇입니까?
벡터의 2D 배열이 포함 된 v1
경우 쿼터니언을 만들 수 없으므로 v1
루프를 사용하여 각 배열 요소를 차례로 회전 할 수 있습니다. 그러나 위 링크의 henneray의 답변에서 쿼터니언이 '적절하게 벡터화 된 numpy 배열'에 적용될 수 있다고 언급되어 있습니다. 누구든지 이것이 어떻게 구현 될 수 있는지에 대한 제안이 있습니까?
(부차적 인 질문 : 내 변수 theta
와 axis
변수가 v1과 같은 길이의 배열 인 경우 동일한 방법을 사용하여 v1의 각 벡터를 해당 회전을 통해 회전시킬 수도 있습니까?)
답변
먼저 [x, y, z] 데카르트 벡터를 첫 번째 성분이 0 [0, x, y, z] 인 4 개의 벡터로 변환해야합니다. 그런 다음 이것을 쿼터니언 배열로 캐스트하여 벡터화 된 계산을 수행 할 수 있습니다.
아래의이 함수는 데카르트 벡터 배열을 가져 와서 단일 회전 축을 중심으로 회전합니다. 이 축의 표준이 회전 각도 세타와 같은지 확인해야합니다.
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:]
축 각도와 쿼터니언 표현 간의 변환이 너무 많으면 회전 행렬 대수에 비해 성능이 거의 향상되지 않습니다. 쿼터니언은 많은 순차 회전을 통해 벡터를 회전 할 때만 실제로 도움이되므로 쿼터니언 곱셈을 쌓을 수 있습니다.
회전 계산을 수행하는 "빠른"방법 중 하나는 쿼터니언을 3x3 방향 코사인 행렬로 바꾸고 벡터를 단일 3xN 연속 행렬에 넣은 다음 BLAS 라이브러리 루틴 (예 : dgemm)을 호출하여 표준을 수행하는 것입니다. 행렬 곱하기. N이 큰 좋은 BLAS 라이브러리는이 계산을 다중 스레드로 수행합니다.