Sto lavorando su simulatore di movimento con 2 DOF (rullo &). Sto leggendo la matrice di trasformazione dal gioco e ho bisogno di ottenere gli angoli e inviare all'hardware per guidare i motori. Poiché gli angoli di Eulero hanno singolarità, non posso davvero usarli. Si comporta in questo modo:Ottieni intonazione e rotazione da matrice senza singolarità
quando dovrebbe in questo modo:
ho preparato esempio online per mostrare meglio la questione:
// Get euler angles from model matrix
var mat = model.matrix;
mat.transpose();
var e = new THREE.Euler();
e.setFromRotationMatrix(mat, 'XZY');
var v = e.toVector3();
var pitch = -v.z;
var roll = -v.x;
http://jsfiddle.net/qajro0ny/3/
Per quanto ho capito, ci sono due problemi qui.
- Non esiste alcun asse di imbardata sul simulatore.
- Anche se ci fosse l'asse di imbardata, i motori semplicemente non si comportano come computer grafica, cioè hanno bisogno di tempo per raggiungere la posizione di destinazione.
Ho letto di gimbal lock e anche implementato il filtro euler, ma non ha funzionato come previsto. La maggior parte dei consigli sul blocco del giunto cardanico consisteva nell'utilizzare i quaternioni, ma non posso guidare il motore fisico con il quaternione (o posso?).
L'ordine degli assi non ha molta importanza qui, perché cambiando si sposta solo la singolarità da un asse all'altro.
Ho bisogno di gestirlo in un altro modo.
Ho provato a moltiplicare i vettori di assi per matrice e quindi utilizzando prodotti a croce e punto per ottenere angoli, ma anche quello non è riuscito. Penso che dovrebbe esserci anche una riprogettazione degli assi per farlo correttamente, ma non riuscivo a capirlo. Ma qualcosa mi dice che questo è il modo giusto per farlo. Era qualcosa del genere: http://jsfiddle.net/qajro0ny/53/
Poi ho avuto un'idea diversa. So posizione precedente, quindi forse effettuare le seguenti operazioni: a matrice
- Converti in quaternione
- differenza Compute tra il quaternione corrente e precedente
- Converti risultante quaternione di angoli di Eulero
- Aggiungi quegli angoli di campo statico, variabili roll and yaw.
Quindi l'ho provato e ... ha funzionato! Nessuna singolarità in nessuna delle direzioni, perfetta rotazione di 360 gradi in pitch, roll e imbardata. La soluzione perfetta! Tranne ... non lo è. I frame non si sincronizzarono, quindi dopo un po 'gli angoli erano lontani da quello che dovrebbero essere. Ho pensato a una sorta di meccanismo di sincronizzazione, ma ho pensato che non fosse la strada giusta.
Si presentava così: http://jsfiddle.net/qajro0ny/52/
E la stessa logica, ma direttamente con le matrici: http://jsfiddle.net/qajro0ny/54/
Ho cercato web ad alta e bassa, ho letto decine di documenti e altre domande/messaggi e non riesco a credere che nulla funzioni davvero per il mio caso.
potrei non capire o manca qualcosa, ecco tutto quello che ho trovato e provato:
vicini: http://pastebin.com/3G0dYLvu
Codice: http://pastebin.com/PiZKwE2t (ho messo tutto insieme in modo che sia disordinato)
Mi manca qualcosa, o sto guardando questo da un angolo sbagliato.
Grazie, ma purtroppo la mia matrice contiene la terza rotazione. Potresti approfondire la questione sulla soluzione dei minimi quadrati non lineari? Ho letto sull'algoritmo di Levenberg-Marquardt, ma non ho idea di come usarlo per il mio problema. – AdrianEddy
Levenberg Marquardt è probabilmente una buona scelta. Fondamentalmente, vuoi trovare il minimizzatore di '|| T - RZ (pitch) * RX (roll) || _2' su 'pitch' e' roll'. La maggior parte delle librerie ti consente di collegare tale definizione in modo più o meno diretto. Ma non conosco nessuna libreria JavaScript per questo. Inoltre, otterrete sempre gli orientamenti flipping se la terza rotazione diventa relativamente grande. Potresti provare ad aggirare questo problema con i termini di regolarizzazione (differenza tra l'ultima e la soluzione corrente). Ma non sono sicuro che questo farà il lavoro. –