Вот элегантный метод, использующий кватернионы, которые являются невероятно быстрыми; Я могу рассчитать 10 миллионов оборотов в секунду с соответствующим векторным массивом. Он основан на расширении кватерниона для найденной numy здесь .
Теория кватернионов:
Кватернион - это число с одним действительным и 3 мнимыми измерениями, обычно записываемое как q = w + xi + yj + zk
, где «i», «j», «k» - мнимые измерения. Подобно тому, как единичное комплексное число «c» может представлять все 2d вращения на c=exp(i * theta)
, так и единичный кватернион «q» может представлять все 3d вращения на q=exp(p)
, где «p» представляет собой чисто воображаемый кватернион, заданный вашей осью и углом .
Мы начнем с преобразования вашей оси и угла в кватернион, мнимые размеры которого определяются вашей осью вращения, а величина равна половине угла поворота в радианах. Векторы из 4 элементов (w, x, y, z)
строятся следующим образом:
import numpy as np
import quaternion as quat
v = [3,5,0]
axis = [4,4,1]
theta = 1.2 #radian
vector = np.array([0.] + v)
rot_axis = np.array([0.] + axis)
axis_angle = (theta*0.5) * rot_axis/np.linalg.norm(rot_axis)
Сначала строится массив из 4 элементов с вещественной составляющей w = 0 как для вектора, который должен вращаться vector
, так и для оси вращения rot_axis
. Представление угла оси затем строится путем нормализации и умножения на половину желаемого угла theta
. См. здесь , почему требуется половина угла.
Теперь создайте кватернионы v
и qlog
, используя библиотеку, и получите кватернион вращения единицы q
, взяв экспоненту.
vec = quat.quaternion(*v)
qlog = quat.quaternion(*axis_angle)
q = np.exp(qlog)
Наконец, вращение вектора вычисляется с помощью следующей операции.
v_prime = q * vec * np.conjugate(q)
print(v_prime) # quaternion(0.0, 2.7491163, 4.7718093, 1.9162971)
Теперь просто отбросьте реальный элемент, и у вас есть повернутый вектор!
v_prime_vec = v_prime.imag # [2.74911638 4.77180932 1.91629719] as a numpy array
Обратите внимание, что этот метод особенно эффективен, если вам нужно повернуть вектор на множество последовательных вращений, поскольку произведение кватернионов можно просто вычислить как q = q1 * q2 * q3 * q4 * ... * qn, а затем вектор вращается только на 'q' в самом конце, используя v '= q * v * con (q).
Этот метод обеспечивает плавное преобразование между оператором трехмерного поворота оси <---> просто с помощью функций exp
и log
(да log(q)
просто возвращает представление угла оси!). Подробнее о том, как работает умножение кватернионов и т. Д., См. здесь