web-dev-qa-db-fra.com

Quaternion et normalisation

Je sais que les quaternions doivent être normalisés si je veux faire pivoter un vecteur. 

Mais y a-t-il des raisons de ne pas normaliser automatiquement un quaternion? Et s’il en existe, quelles opérations sur les quaternions produisent des quaternions non normalisés? 

  • Multiplier deux quaternions?
  • Produit scalaire?

Désolé, si cette question est un peu floue. J'essaie encore de m'entourer des quaternions.

16

Toute opération produisant un quaternion devra être normalisée, car des erreurs de précession en virgule flottante l'empêcheront d'être de la longueur.

Je déconseillerais les routines standard effectuant automatiquement la normalisation pour des raisons de performances. Tout programmeur compétent doit être conscient des problèmes de précision et pouvoir normaliser les quantités si nécessaire - et il n’est pas toujours nécessaire d’avoir un quaternion de longueur unitaire.

Il en va de même pour les opérations vectorielles.

8
user1157123

Réponse tardive; cette réponse est destinée aux personnes qui rencontrent cette question dans le futur plutôt que pour le questionneur.

Je ne suis pas d'accord avec les deux autres réponses concernant la normalisation occasionnelle d'un quaternion. Les formules standard pour utiliser un quaternion pour faire pivoter/transformer un vecteur ou pour générer une matrice de rotation/transformation supposent implicitement que le quaternion est normalisé. Les erreurs résultant de l'utilisation d'un quaternion non normalisé sont proportionnelles au carré de la magnitude du quaternion. La croissance d'erreur quadratique est quelque chose de mieux à éviter.

Si vous normalisez fréquemment, vous n’avez pas besoin de la racine carrée. Une approximation au premier ordre fonctionne assez bien. Voici ce que j'utilise pour les quaternions en double IEEE, un peu stylisé:

double qmagsq = quat.square_magnitude();
if (std::abs(1.0 - qmagsq) < 2.107342e-08) {
    quat.scale (2.0 / (1.0 + qmagsq));
}
else {
    quat.scale (1.0 / std::sqrt(qmagsq));
}

Notez que j'utilise le padé de premier ordre approximant 2.0/(1.0+qmagsq) plutôt que le développement de Taylor de premier ordre 0.5*(3.0-qmagsq) pour estimer 1.0/std::sqrt(qmagsq). Cette approximation, si elle est valide, remplace l’appel de racine carrée par une simple division. La clé est de déterminer quand cette approximation est valide, c'est là que ce nombre magique 2.107342e-08 entre en jeu.

Pourquoi un approximé Padé? Deux raisons. La première est que pour les valeurs de qmagsq proches de un, 1+qmagsq perd moins de précision que 3-qmagsq. L'autre est que l'approximant Padé réduit l'erreur d'un facteur de trois par rapport à l'expansion de Taylor. Pour les valeurs de qmagsq comprises entre 0 et 2, l'erreur dans cette approximation est inférieure à (1-qmagsq)^2 / 8. Le nombre magique 2.107342e-08 représente l'endroit où cette erreur est supérieure à la moitié d'une ULP pour les doublons IEEE. Si vous faites des petits pas raisonnables, le carré de la magnitude du quaternion sera toujours dans cette limite. Vous n'appellerez jamais sqrt.

La seule exception à ce paradigme "normaliser toujours" pourrait être si vous utilisez une technique d'intégration de groupe de Lie pour propager des quaternions. Si vous ne savez pas ce que cela signifie, vous utilisez probablement l'équivalent de q(t+Δt) = q(t) + dq(t)/dt*Δt pour propager un quaternion. Vous utilisez toujours cette étape d'Euler quelque part, même si vous utilisez une technique d'intégration d'ordre supérieur qui n'est pas un intégrateur de groupe de Lie.

27
David Hammen

Curieusement, la construction de matrices de rotation est une opération pour laquelle la normalisation des quaternions n’est PAS nécessaire, ce qui vous permet d’économiser une sqrt:

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z);
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z);
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z] / (w*w+x*x+y*y+z*z)

(en notation MATLAB-ish) pour le quaternion w+x*i+y*j+z*k.

De plus, si vous travaillez avec des coordonnées homogènes et des matrices de transformation 4x4, vous pouvez également sauvegarder certaines opérations de division: créez simplement une partie de rotation 3x3 comme si le quaternion était normalisé, puis placez sa longueur au carré dans l'élément (4,4) :

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z),     0;
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z),    0;
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z, 0;
     0,               0,               0,               w*w+x*x+y*y+z*z].

Multipliez par une matrice de traduction, etc., comme d'habitude pour une transformation complète. De cette façon, vous pouvez faire, par exemple,

[xh yh zh wh]' = ... * OtherM * M * [xold yold zold 1]';
[xnew ynew znew] = [xh yh zh] / wh.

Naturellement, la normalisation au moins occasionnelle des quaternions est toujours recommandée (elle peut également être requise pour d’autres opérations).

5
vpozdyayev

Si une unité quaternion est obtenue en intégrant numériquement sa première dérivée, l'intégrateur peut la normaliser automatiquement à l'aide d'un simple retour d'erreur.

Soit q représente une matrice de quaternions sur 4 colonnes et dq sa dérivée temporelle. Ensuite, envoyer dq + 0.5 (1-qq) q/tau à l'intégrateur à la place de dq et utiliser une constante de temps appropriée tau normalisera en permanence q . q.q représente le produit intérieur.

J'ai simulé un mécanisme de Bricard articulé et conservateur flottant dans un espace sans gravité pendant 3,6 millions de secondes, soit près de 42 jours. Les quaternions représentaient l'orientation du corps de base flottant. L'énergie totale est restée constante à environ une partie par million en utilisant une constante de temps tau de 0,5 seconde. Une tolérance d'erreur absolue de 10 ^ -12 et une tolérance d'erreur relative de zéro ont été utilisées dans l'intégrateur numérique DE.

http://www.Amazon.com/Computer-Solution-Ordinary-Differential-Equations/dp/0716704617/

Les quaternions sont souvent obtenus par intégration numérique. S'ils ne sont pas normalisés dans l'intégrateur, les erreurs de magnitude et de phase s'accumulent. Un quaternion normalisé se déplace le long d'une sphère unitaire et sa première dérivée est tangente à cette sphère. Si le quaternion s'éloigne de la sphère de l'unité, il commencera à accumuler des erreurs de phase qu'une normalisation en dehors de l'intégrateur ne pourra pas corriger. Le quaternion doit donc être normalisé en permanence au sein de l'intégrateur numérique afin de minimiser les erreurs de phase.

2
Roger Wehage

votre question est ambigüe mais si vous devez normaliser un quaternion, c'est simple

q_normalized = q/square (norme (q))

avec, q = q1 + q2i + q3 j + q4 k norm (q) = (q1) ^ 2 + (q2) ^ 2 + (q3) ^ 2) + (q4) ^ 4

sinon, expliquez-moi votre question

0