Voici une méthode élégante utilisant des quaternions qui sont extrêmement rapides ; je peux calculer 10 millions de rotations par seconde avec des tableaux numpy vectorisés de manière appropriée. Elle s'appuie sur l'extension quaternion de numpy que l'on a trouvée aquí .
Théorie des quaternions : Un quaternion est un nombre à une dimension réelle et trois dimensions imaginaires qui s'écrit généralement comme suit q = w + xi + yj + zk
où "i", "j", "k" sont des dimensions imaginaires. De même qu'un nombre complexe unitaire "c" peut représenter toutes les rotations 2d par c=exp(i * theta)
un quaternion unitaire "q" peut représenter toutes les rotations 3D par q=exp(p)
où "p" est un quaternion imaginaire pur défini par votre axe et votre angle.
Nous commençons par convertir votre axe et votre angle en un quaternion dont les dimensions imaginaires sont données par votre axe de rotation, et dont la magnitude est donnée par la moitié de l'angle de rotation en radians. Les vecteurs à 4 éléments (w, x, y, z)
sont construits comme suit :
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)
Tout d'abord, un tableau numpy de 4 éléments est construit avec la composante réelle w=0 pour le vecteur à faire tourner vector
et l'axe de rotation rot_axis
. La représentation de l'angle de l'axe est ensuite construite en normalisant puis en multipliant par la moitié l'angle souhaité theta
. Voir aquí pour expliquer pourquoi la moitié de l'angle est nécessaire.
Créez maintenant les quaternions v
y qlog
en utilisant la bibliothèque, et obtenir le quaternion de rotation unitaire q
en prenant l'exponentielle.
vec = quat.quaternion(*v)
qlog = quat.quaternion(*axis_angle)
q = np.exp(qlog)
Enfin, la rotation du vecteur est calculée par l'opération suivante.
v_prime = q * vec * np.conjugate(q)
print(v_prime) # quaternion(0.0, 2.7491163, 4.7718093, 1.9162971)
Il suffit maintenant d'écarter l'élément réel pour obtenir un vecteur rotatif !
v_prime_vec = v_prime.imag # [2.74911638 4.77180932 1.91629719] as a numpy array
Notez que cette méthode est particulièrement efficace si vous devez faire pivoter un vecteur par de nombreuses rotations séquentielles, car le produit quaternaire peut simplement être calculé comme q = q1 * q2 * q3 * q4 * ... * qn, puis le vecteur n'est tourné que de 'q' à la toute fin en utilisant v' = q * v * conj(q).
Cette méthode permet une transformation transparente entre l'angle de l'axe <---> l'opérateur de rotation 3D simplement par exp
y log
fonctions (oui log(q)
ne renvoie que la représentation de l'angle de l'axe !) Pour plus de précisions sur le fonctionnement de la multiplication des quaternions, etc. aquí
14 votes
Je trouve très surprenant qu'il n'y ait pas de fonctionnalité pour cela dans SciPy (ou un paquetage similaire facilement accessible) ; la rotation de vecteurs n'est pas si exotique.
3 votes
Aujourd'hui, c'est le cas : scipy.spatial.transform.Rotation.from_rotvec