Pracuję nad symulatorem ruchu z 2 DOF (pitch & roll). Czytam matrycę transformacji z gry i potrzebuję uzyskać kąty i przesłać sprzęt do napędu silników. Ponieważ kąty Eulera mają osobliwości, nie mogę ich naprawdę użyć. Zachowuje się tak:Get pitch and roll z macierzy bez osobliwości
kiedy należy to tak:
przygotowałem przykład online, aby lepiej pokazać problem:
// 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/
O ile rozumiem, są tu dwa problemy.
- Na symulatorze nie ma osi obrotu.
- Nawet jeśli istniała oś odchylenia, silniki po prostu nie zachowują się jak grafika komputerowa, tj. Potrzebują czasu, aby dojść do pozycji docelowej.
Przeczytałem o blokadzie kardana, a nawet zaimplementowanym filtrem Eulera, ale to nie działało zgodnie z oczekiwaniami. Większość porad związanych z blokadą kardana polegała na użyciu kwateroruchów, ale nie mogę prowadzić silnika fizycznego z kwaternionem (lub czy mogę?).
Kolejność osi nie ma tu większego znaczenia, ponieważ zmiana spowoduje przeniesienie pojedynczej pozycji z jednej osi na drugą.
Muszę sobie z tym poradzić w inny sposób.
Próbowałem wektory liczby mnialnej przez matrycę, a następnie za pomocą produktu krzyżowego i punktowego uzyskać kąty, ale to też się nie udało. Sądzę, że powinno być również odwzorowanie osi, aby to naprawić, ale nie mogłem tego rozgryźć. Ale coś mi mówi, że jest to właściwy sposób na zrobienie tego. To było coś takiego: http://jsfiddle.net/qajro0ny/53/
Potem wpadłem na inny pomysł. Wiem, że wcześniejsze stanowisko, więc może wykonać następujące czynności: matryca
- Konwersja do quaternion
- różnicę Compute między obecnym a poprzednim kwaterniony
- Convert wynikającą kwaternion do kąty Eulera
- Dodaj te kąty na boisku statycznej zmienne przechylenia i odchylenia.
Więc spróbowałem i ... zadziałało! Brak osobliwości w żadnym z kierunków, doskonały obrót o 360 stopni w skoku, toczyć i odchylać. Idealne rozwiązanie! Z wyjątkiem ... nie jest. Ramki nie zostały zsynchronizowane, więc po chwili kąty były odbiegające od tego, czym powinny być. Myślałem o jakimś mechanizmie synchronizacji, ale pomyślałem, że to nie jest właściwa droga.
Wyglądało to tak: http://jsfiddle.net/qajro0ny/52/
I z tą samą logiką, lecz bezpośrednio z macierzy: http://jsfiddle.net/qajro0ny/54/
Szukałem wysokiej i niskiej internetowych, czytałem dziesiątki dokumentów i inne pytania/wiadomości i po prostu nie mogę uwierzyć, że w moim przypadku nic tak naprawdę nie działa.
I nie może zrozumieć lub coś przeoczyć, więc o to wszystko znalazłem i próbowałem:
Linki: http://pastebin.com/3G0dYLvu
Kod: http://pastebin.com/PiZKwE2t (Wrzuciłem to wszystko razem, więc jest to brudny)
Muszę czegoś nie mieć lub patrzę na to pod niewłaściwym kątem.
Dzięki, ale niestety moja macierz zawiera trzeci obrót. Czy mógłbyś bardziej rozwinąć nieliniowe rozwiązanie najmniejszych kwadratów? Czytałem o algorytmie Levenberga-Marquardta, ale nie mam pojęcia, jak go wykorzystać w moim problemie. – AdrianEddy
Levenberg Marquardt to prawdopodobnie dobry wybór. Zasadniczo chcesz znaleźć minimizer '|| T - RZ (wysokość) * RX (rolka) || _2' powyżej 'wysokości' i 'toczyć'. Większość bibliotek umożliwia podłączenie tej definicji w mniej lub bardziej bezpośredni sposób. Ale nie znam żadnej biblioteki JavaScript dla tego. Poza tym, zawsze otrzymasz orientację przewracającą, jeśli trzeci obrót będzie stosunkowo duży. Możesz spróbować ominąć to za pomocą warunków regularyzacji (różnica ostatniego i obecnego rozwiązania). Ale nie jestem pewien, czy to się spełni. –