2013-05-13 10 views
11

Mam aplikację, która rejestruje kąty, gdy użytkownik chodzi po obiekcie, jednocześnie wskazując urządzenie (najlepiej) w środku obiektu. Kąt zostaje zresetowany na polecenie użytkownika - w ten sposób ustawienie referencyjne zostanie zresetowane.Zmiana podejścia - problemy z kątami i osią - matematyka kwaternionowa

Korzystanie kąty Eulera powoduje blokadę przegubowego, więc Obecnie używam quaternions i obliczanie kątów w ten sposób:

double angleFromLastPosition = acos(fromLastPositionAttitude.quaternion.w) * 2.0f; 

ten wydziela dobrą precyzję i działa prawidłowo, jeżeli wysokość i odchylenie urządzenia nie zmieni się. Innymi słowy, ponieważ kąt pokazuje 360 ​​stopni, kończę w tym samym miejscu co początek koła.

Problem 1: jeśli odchylenie urządzenia i jego wysokość zmieniają się nieznacznie (użytkownik nie wskazuje bezpośrednio na środek obiektu), zmienia się także kątFromLastPosition. Rozumiem tę część, ponieważ moja formuła kątowa pokazuje kąt pomiędzy dwiema postawami urządzenia w przestrzeni 3D.

Scenariusz:

  • oznaczyć początek postawy rotacji i ruszyć w kręgu wokół obiektu, wskazując jednocześnie na środku
  • zatrzymać w, powiedzmy, 45 stopni i zmiana skoku urządzenia wskazując go wyżej lub niżej. Kąt zmienia się odpowiednio.
  • Co chciałbym zobaczyć, to: kąt pozostaje pod kątem 45 stopni, nawet jeśli zmienia się nachylenie lub odchylenie.

Pytanie 1 brzmi, w jaki sposób mogę obliczyć tylko rzut urządzenia za pomocą kwaternionów i pominąć zmiany w innych dwóch osiach (przynajmniej w rozsądnej liczbie stopni).

Problem 2: jeśli obrócę na chwilę, a następnie całkowicie zamroszę urządzenie (na statywie, aby nie było w ogóle drgań), kątFromLastPosition dryfuje z prędkością 1 stopnia na około 10-20 sekund, i wydaje się nie być być liniowe. Innymi słowy, początkowo szybko dryfuje, a następnie znacznie zwalnia. Czasami nie mam żadnego dryfu - kąt jest stabilny, gdy urządzenie jest nieruchome. A to sprawia, że ​​tracę rozumienie tego, co się dzieje.

Pytanie 2, co się tutaj dzieje i jak mogę dbać o dryf?

Przeszedłem przez kilka artykułów i samouczków, a matematyka czwartorzędowa jest obecnie poza mną, mam nadzieję, że ktoś będzie w stanie pomóc z napiwkiem, linkiem lub kilkoma liniami kodu.

+0

dryft może być związany z [Drifting Yaw] (http://stackoverflow.com/questions/13613239/drifting-yaw-angle-after-moving-fast? Rq=1)? jeśli tak, znalezienie wzoru na pytanie 1 zajmie się obydwoma problemami :) –

+0

Jeśli używasz CMAttitude, czy istnieje jakiś szczególny powód, którego nie możesz po prostu użyć zLastPositionAttitude.roll, aby uzyskać przewinięcie urządzenia? Doceniam to, że nie używa się własności kwaternionowej, ale jest tam do użycia! –

+0

tak, zacząłem od tego - używanie kątów Eulera powoduje zablokowanie kardana i utratę stopni swobody. pełny obrót nie wynosi 360 stopni, gdy urządzenie nie jest wyrównane z osią Z. a przynajmniej to jest moje zrozumienie efektu ... –

Odpowiedz

4

Testowałem to i wygląda na to, że działa zgodnie z tym, czego szukasz w pytaniu 1, Andrei.

Ustawiam homeangle początkowo 0 i natychmiast po pierwszym przejściu przechowuje się kąt zwrócony z walkaroundAngleFromAttitude: fromHomeAngle: in homeangle, do wykorzystania w przyszłości.

My badania obejmował rozpoczęciem aktualizacji urządzenie za pomocą układu odniesienia:

[_motionManager 
startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical 
toQueue:operationQueue 
withHandler:handler]; 

i stosując następujące metody zwane wewnątrz uchwytu:

- (CMQuaternion) multiplyQuanternion:(CMQuaternion)left withRight:(CMQuaternion)right { 

    CMQuaternion newQ; 
    newQ.w = left.w*right.w - left.x*right.x - left.y*right.y - left.z*right.z; 
    newQ.x = left.w*right.x + left.x*right.w + left.y*right.z - left.z*right.y; 
    newQ.y = left.w*right.y + left.y*right.w + left.z*right.x - left.x*right.z; 
    newQ.z = left.w*right.z + left.z*right.w + left.x*right.y - left.y*right.x; 

    return newQ; 
} 

-(float)walkaroundRawAngleFromAttitude:(CMAttitude*)attitude { 

    CMQuaternion e = (CMQuaternion){0,0,1,1}; 
    CMQuaternion quatConj = attitude.quaternion; 
    quatConj.x *= -1; quatConj.y *= -1; quatConj.z *= -1; 
    CMQuaternion quat1 = attitude.quaternion; 
    CMQuaternion quat2 = [self multiplyQuanternion:quat1 withRight:e]; 
    CMQuaternion quat3 = [self multiplyQuanternion:quat2 withRight:quatConj]; 

    return atan2f(quat3.y, quat3.x); 
} 
-(float)walkaroundAngleFromAttitude:(CMAttitude*)attitude fromHomeAngle:(float)homeangle { 

    float rawangle = [self walkaroundRawAngleFromAttitude:attitude]; 
    if (rawangle <0) rawangle += M_PI *2; 
    if (homeangle < 0) homeangle += M_PI *2; 
    float finalangle = rawangle - homeangle; 
    if (finalangle < 0) finalangle += M_PI *2; 

    return finalangle; 
} 

tej wykorzystuje się pewne zmodyfikowane i rozszerzony kod Finding normal vector to iOS device

Edytuj, aby poradzić sobie z pytaniem 2 & Problem 2:

To może nie dać się rozwiązać. Widziałem to w innych aplikacjach (na przykład 360 panoram) i czytałem o błędnych odczytach w Gyro i tym podobnych. Jeśli próbujesz to zrekompensować, oczywiście skończy się to rozkojarzeniem, gdy jakiś autentyczny ruch obrotowy zostanie rzucony przez kod kompensacyjny. O ile interpretuję przez ostatnie kilka lat, jest to kwestia sprzętowa.

+0

dziękuję za pomoc, po drobnym poprawieniu kodu działam i rozwiązuje on mój problem_1. Potrzebujesz więcej czasu na testowanie i dostrajanie, ale jestem pewien, że mam wszystko, czego potrzebuję, aby to zakończyć. Drift zachowuje się teraz inaczej, dryfuje o kilka stopni, a następnie zatrzymuje się - kąt jest solidny jak z wariacją 10 stopnia. Które jest całkowicie dopuszczalne dla tej aplikacji. Będę się z tym bawić i opublikuję, jeśli się zorientuję, od czego to zależy, do tego czasu jest w pudełku z winy sprzętu i jest wystarczająco dobre :) Pozdrawiam: –

+0

@AndreiG. Dobre rzeczy, cieszę się, że mogłem ci pomóc. Poza tym dało mi to bardzo potrzebne ćwiczenie, aby wrócić do matematyki kwaternionowej :) Pozdrawiam –

+0

@TomPace Witam, próbuję również znaleźć rozwiązanie czegoś podobnego, Czy mógłbyś rzucić okiem na moje pytanie tutaj: [ Link] (http://stackoverflow.com/questions/19239482/using-quaternion-instead-of-roll-pitch-and-yaw-to-track-device-motion). Myślę, że znalazłem zmianę w części kątowej , Ale nie jestem pewien, czy jestem na dobrej drodze. Nadal muszę dowiedzieć się, jak śledzić ruch telefonu w różnych osiach. Mój obecny postęp jest [tutaj] (http://pastebin.com/faPWUVE2). Z góry dziękuję. – iSeeker

Powiązane problemy