2013-05-13 25 views
11

Ho un'app che registra gli angoli mentre l'utente sta camminando intorno a un oggetto, mentre punta il dispositivo (preferibilmente) al centro dell'oggetto. L'angolo viene ripristinato sul comando dell'utente, quindi l'atteggiamento di riferimento viene ripristinato.Cambio di posizione - angolo e problema dell'asse - matematica quaternion

con angoli di Eulero produce blocco del giunto cardanico, così Attualmente sto usando quaternioni e calcolando gli angoli in questo modo:

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

Questa emana buona precisione e funziona perfettamente IF beccheggio e imbardata del dispositivo non cambia. In altre parole, quando l'angolo mostra 360 gradi, finisco nello stesso punto in cui inizia il cerchio.

Problema 1: se l'imbardata e l'altezza del dispositivo cambiano leggermente (l'utente non punta direttamente al centro dell'oggetto), lo stesso vale per l'angoloFromLastPosition. Capisco questa parte, poiché la mia formula dell'angolo mostra solo l'angolo tra due atteggiamenti del dispositivo nello spazio 3D.

Scenario:

  • ho segnare l'inizio di atteggiamento rotazione e iniziare a muoversi in cerchio attorno all'oggetto mentre si punta il centro
  • mi fermo a, diciamo, 45 gradi e variazione del passo del dispositivo puntandolo più in alto o più in basso. L'angolo cambia di conseguenza.
  • Quello che mi piacerebbe vedere è: l'angolo rimane a 45 gradi, anche se il pitch o l'imbardata cambiano.

Domanda 1: come posso calcolare solo il rotolo del dispositivo utilizzando i quaternioni e ignorare le modifiche negli altri due assi (almeno entro un numero ragionevole di gradi).

Problema 2: se si ruota per un po 'e poi si blocca completamente il dispositivo (sul treppiede quindi non c'è alcun tipo di tremolio), l'angoloFromLastPosition si sposta a una velocità di 1 grado per circa 10-20 secondi, e non appare essere lineare. In altre parole, all'inizio scorre rapidamente, quindi rallenta considerevolmente. A volte non ho alcuna deriva - l'angolazione è solida come una roccia se il dispositivo è fermo. E questo mi fa perdere la comprensione di cosa sta succedendo.

Domanda 2, cosa sta succedendo qui e come posso occuparmi della deriva?

Ho passato un bel po 'di articoli e tutorial, e la matematica del quaternion è al di fuori di me al momento, spero che qualcuno possa aiutarmi con un suggerimento, un collegamento o poche righe di codice.

+0

può essere legato a [Drifting Yaw] (http://stackoverflow.com/questions/13613239/drifting-yaw-angle-after-moving-fast?rq=1)? in caso affermativo, la ricerca di una formula per la domanda 1 si occuperà di entrambi i problemi :) –

+0

Se si utilizza CMAttitude, esiste un motivo particolare per cui non è possibile utilizzare daLastPositionAttitude.roll per ottenere il risultato del dispositivo? Apprezzo che questo non stia usando la proprietà quaternion, ma è lì da usare! –

+0

sì, iniziato con quello - utilizzando angoli euler produce un blocco cardanico e perdita di gradi di libertà. la rotazione completa non è di 360 gradi quando il dispositivo non è allineato con l'asse Z. almeno questa è la mia comprensione dell'effetto .... –

risposta

4

Ho provato questo e sembra funzionare secondo quello che stai cercando nella domanda 1, Andrei.

Ho impostato inizialmente l'omeroide 0 e immediatamente dopo il primo passaggio memorizzo l'angolo restituito da walkaroundAngleFromAttitude: fromHomeAngle: in homeangle, per uso futuro.

mio test inclusa iniziare gli aggiornamenti del dispositivo utilizzando un sistema di riferimento:

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

ed utilizzando i seguenti metodi chiamati all'interno del gestore:

- (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; 
} 

questo sta usando un codice modificato e esteso da Finding normal vector to iOS device

Modifica per gestire la domanda 2 & Problema 2:

Questo potrebbe non essere risolvibile. L'ho visto in altre app (360 pano per esempio) e ho letto su letture errate in gyro e così via. Se hai provato a compensarlo, ovviamente ti ritroverai con una esperienza nervosa quando un autentico movimento rotazionale viene sballottato dal codice di compensazione. Per quanto ho interpretato negli ultimi anni, questo è un problema basato sull'hardware.

+0

grazie per il vostro aiuto, con alcuni ritocchi ho ottenuto il vostro codice funzionante, e risolve il mio problema_1. Ho bisogno di più tempo per testare e modificare, ma sono sicuro di avere tutto ciò di cui ho bisogno per finirlo. La deriva si comporta in modo diverso ora, si muove per alcuni gradi e poi si arresta: l'angolo è solido come la roccia con una variazione di appena 10 ° di grado. Quale è perfettamente accettabile per questa app. Ci giocherò e pubblicherò se capisco da cosa dipende, fino ad allora, è nella scatola della colpa hardware ed è abbastanza buono :) evviva –

+0

@AndreiG. Roba buona, felice di poterti dare una mano. Inoltre, questo mi ha dato l'esercizio tanto necessario per tornare in matematica quaternion :) Saluti –

+0

@TomPace Ciao, sto anche cercando di trovare una soluzione a qualcosa di simile a questo, potreste per favore dare un'occhiata alla mia domanda qui: [ Link] (http://stackoverflow.com/questions/19239482/using-quaternion-instead-of-roll-pitch-and-yaw-to-track-device-motion). Penso di aver trovato il cambiamento nella parte angolare Ma non sono sicuro che sia sulla strada giusta. Devo ancora capire come monitorare il movimento del telefono in diversi assi. I miei progressi attuali sono [qui] (http://pastebin.com/faPWUVE2). Grazie in anticipo. – iSeeker