Bonsoir,

Pour un projet, je souhaite faire des rotations en utilisant les quaternions sous Python. Je connais la théorie, je sais a priori l'appliquer, c'est juste un petit problème "d'échelle" lorsque je fais différents tests.

Pour me faire comprendre, voici 2 images :
Une rotation de 45 degrés autour de l'axe ascendant :
Nom : 45.png
Affichages : 1490
Taille : 28,2 Ko
Une autre de 90 degrés autour de ce même axe :
Nom : 90.png
Affichages : 1382
Taille : 25,1 Ko

On voit, avec les graduations sur les axes, qu'il y a un problème d'échelle lorsque je change l'angle.. A priori, le cube est dessiné sur la région de l'espace [-10,10], comme vu ici (rotation réalisée avec les angles d'Euler) :
Nom : phi 25, theta 180, psi 35.png
Affichages : 1354
Taille : 26,8 Ko

Je ne vois pas d'où viens l'erreur..
Je mets ici le code à disposition :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import time
from numpy import sin,cos
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("auto")
ax.set_autoscale_on(True)
 
def q_conj(q):
    ''' Renvoie le conjugué d'un quaternion '''
    w, x, y, z = q
    return (w, -x, -y, -z)
 
def normalise(v, tolerance=0.00001):
    ''' Normalise un quaternion'''
    mag2 = sum(n * n for n in v)
    if abs(mag2 - 1.0) > tolerance:
        mag = np.sqrt(mag2)
        v = tuple(n / mag for n in v)
    return v
 
def axeangle_to_q(v, theta):
    ''' Renvoie le quaternion associé à une rotation d'un angle theta et autour de l'axe v '''
    v = normalise(v)
    x, y, z = v
    theta /= 2
    w = cos(theta)
    x = x * sin(theta)
    y = y * sin(theta)
    z = z * sin(theta)
    return w, x, y, z
 
def q_to_axeangle(q):
    ''' Renvoie l'axe et l'angle de rotation associé à un quaternion '''
    w, v = q[0], q[1:]
    theta = np.arccos(w) * 2.0
    return normalise(v), theta
 
def q_mult(q1, q2):
    ''' Multiplie 2 quaternions ensemble (attention à la non-commutativité) '''
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
    x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
    y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2
    z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2
    return w, x, y, z
 
def qv_mult(q1, v1):
    ''' Applique le procédé de conjugaison pour réaliser une rotation '''
    q2 = (0.0,) + v1
    return q_mult(q_mult(q1, q2), q_conj(q1))[1:]  
 
def dessiner_cube_quaternion(q):
    r = [-10, 10]
    theta=q_to_axeangle(q)[1]
    for s, e in combinations(np.array(list(product(r,r,r))), 2):
            if np.sum(np.abs(s-e)) == r[1]-r[0]:
                a=axeangle_to_q(e,theta)[1:]
                b=axeangle_to_q(s,theta)[1:]
                e_rotated=qv_mult(q,a)
                s_rotated=qv_mult(q,b)
                ax.plot3D(*zip(s_rotated,e_rotated), color="b")
 
 
theta=np.radians(45)
q=axeangle_to_q((0,0,1),theta) #Rotation de theta autour de l'axe ascendant
dessiner_cube_quaternion(q)
 
plt.show()