Come posso confrontare due quaternioni per l'uguaglianza logica?


9

Sto provando a scrivere alcuni test unitari e mi rendo conto che non so come confrontare i quaternioni. Devo sapere se due quaternioni rappresentano lo stesso orientamento (l'oggetto sarebbe rivolto allo stesso modo). Con una posizione simile a un vettore confronterei semplicemente le parti e verificherei che siano abbastanza vicine, ma per i quaternioni i valori possono essere molto diversi.

Come posso confrontare due quaternioni?


Non sono sicuro che si tratti di una pratica standard, ma ad esempio in Java e Unity i quaternioni sono memorizzati come quattro valori float. Basta confrontare questi a vicenda come delineato in questi post: answers.unity3d.com/questions/288338/... stackoverflow.com/questions/5803627/quaternion-comparision
Tholle

1
@Tholle l'utente si preoccupa anche dell'impatto dell'applicazione del quaternione per trasformare / ruotare un'entità 3D (vale a dire in posa). Due quaternioni diverse possono ottenere la stessa rotazione (ad es. qE -q). Il modo ingenuo (dal punto di vista computazionale) sarebbe applicare entrambi i quaternioni allo stesso vettore e vedere se i loro risultati vettoriali sono diversi ..
teodron,

Risposte:


7

Se i tuoi due quaternioni sono q1e q2, rappresentano la stessa rotazione se si verifica una di queste due condizioni:

  1. q1il componente è approssimativamente uguale a q2OR
  2. q1 il componente è approssimativamente uguale a -q2

Sapendo questo, puoi scrivere un tester di uguaglianza abbastanza semplice che si adatta al tuo obiettivo.


9
+1, un nitpick però, qe -qrappresentano lo stesso orientamento (che veniva richiesto), ma non la stessa rotazione. Questo è cruciale quando si interpola.
falstro,

@falstro, penso di aver capito cosa intendi: gli assi di rotazione sono invertiti, ma anche l'angolo argomento viene negato tra qe -qquando rappresentato come operatore di rotazione dell'asse angolare. Quindi, in effetti, tecnicamente l'effetto di queste rotazioni è lo stesso, anche se gli operatori non lo sono. E, sì, quando SLERPING, uno deve assicurarsi q1e q2mentire sullo stesso emisfero dell'ipersfera S3 in modo che lo slerp prenda il percorso più breve.
teodron,

1
Esattamente, quando esegui una delle due rotazioni, finirai con lo stesso orientamento, ma la interpoli (sia che tu lerp o slerp o qualche altra interpolazione di fantasia), vedrai che sta girando in modi diversi. E sì, l'argomento dell'angolo è negato, ma è lo stesso di 2pi-angle, quindi sta girando la strada intorno agli assi negati. A volte questo è quello che vuoi però; è solo qualcosa di cui essere consapevoli, si q1 dot q2 > 0traduce nella svolta breve, q1 dot q2 < 0prende la svolta lunga.
falstro,

12

Solo perché non è stato menzionato. Poiché i quaternioni utilizzati per l'orientamento spaziale sono sempre di lunghezza unitaria (o dovrebbero essere), funzionerà anche quanto segue.

abs(q1.dot(q2)) > 1-EPS

dove l'EPS è un fattore di sfumatura che consente piccoli errori dovuti alla precisione limitata in virgola mobile. Se (e solo se) entrambi i quaternioni rappresentano lo stesso orientamento allora q1 = +- q2, e quindi q1.dot(q2) = +- 1. Se vuoi assicurarti che abbiano la stessa rotazione (piuttosto che solo l'orientamento), quindi rimuovi abs.


@bogglez true. Era nascosto nel testo del dott. :)
falstro,

+1, piuttosto elegante e forse anche numericamente più efficiente della mia risposta (purché vengano utilizzate le operazioni SIMD :)).
teodron,

Qual è la giustificazione matematica per questo?
fabian789,

Giustificazione "matematica" (tra virgolette non sono un matematico :)): due vettori di lunghezza unitaria hanno un punto (noto anche come prodotto interno) che è 0 se sono verticali l'uno rispetto all'altro, 1 * 1 = 1 se indicano esattamente il stessa direzione e 1 * 1 * cos (phi) nel caso generale, con phi il loro angolo ...
ntg

2

I quaternioni sono memorizzati come 4 float o doppi, spesso chiamati x, y, z ew, dove i primi tre rappresentano un asse e il grado di rotazione attorno a quell'asse.

Un approccio ingenuo sarebbe quello di confrontare quei numeri di due quaternioni per l'uguaglianza. Tuttavia, poiché i calcoli in virgola mobile comportano un errore, dovresti almeno utilizzare un errore, spesso chiamato eps (per epsilon) e confrontare ogni componente come

    double const eps = 1e-12; // some error threshold
    abs(quat1_x - quat2_x) < eps // similar enough?
    // repeat for other values..

Un test migliore sarebbe quello di calcolare il punto prodotto dei due quaternioni e verificare se è vicino a 1.0. Dovresti cercare l'equazione dei quaternioni con peccato e cos e punteggiare solo due quaternioni, quindi dovresti vedere prontamente perché questo funziona.


0

Sulla base di tutti i suggerimenti per usare Dot ed eps ho scoperto che usando (in unità):

Mathf.Approximately(Mathf.Abs(Quaternion.Dot(transform.rotation, to)), 1.0f)

ha funzionato bene senza che dovessi prendere una decisione per le dimensioni di eps.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.