2013-03-27 9 views
11

Utilizzo i sensori di gravità e di campo magnetico di Android per calcolare l'orientamento tramite SensorManager.getRotationMatrix e SensorManager.getOrientation. Questo mi dà i numeri di azimuth, pitch e orientation. I risultati sembrano sensati quando il dispositivo è appoggiato su un tavolo.Come devo calcolare azimuth, pitch, orientation quando il mio dispositivo Android non è piatto?

Tuttavia, ho disabilitato le interruzioni tra verticale e orizzontale nel manifest, in modo che getWindowManager(). GetDefaultDisplay(). GetRotation() sia sempre zero. Quando ruoto il dispositivo di 90 gradi in modo che sia in verticale, corro nei guai. A volte i numeri sembrano sbagliati, e ho capito che questo si riferisce a Gimbal lock. Tuttavia, altre app non sembrano avere questo problema. Ad esempio, ho confrontato la mia app con due app di test del sensore gratuite (Sensor Tester (Dicotomica) e Sensor Monitoring (R's Software)). La mia app è d'accordo con queste app quando il dispositivo è piatto, ma quando ruoto il dispositivo in posizione verticale possono esserci differenze significative. Le due app sembrano concordare l'una con l'altra, quindi come fanno a risolvere questo problema?

risposta

7

Penso che il modo migliore per definire gli angoli di orientamento quando il dispositivo non è piano consiste nell'utilizzare un sistema di coordinate angolari più appropriato rispetto agli angoli standard di Eulero che si ottengono da SensorManager.getOrientation(...). Suggerisco quello che descrivo here on math.stackexchange.com. Ho anche inserito del codice che lo implementa in an answer here. A parte una buona definizione di azimuth, ha anche una definizione dell'angolo di inclinazione che è esattamente l'angolo dato da Math.acos(rotationMatrix[8]) che è menzionato in un'altra risposta qui.

È possibile ottenere tutti i dettagli dai due collegamenti che ho fornito nel primo paragrafo. Tuttavia, in sintesi, la matrice di rotazione R da SensorManager.getRotationMatrix (...) È

equation with definition of R matrix

dove (E x, E y, E z), (N x, N y, N z) e (G x, G y, G z) sono vettori che puntano verso Est, Nord e in direzione di Gravità. Poi l'angolo di azimut che si desidera è dato da

equation defining the azimuth angle

+0

Sfortunatamente questo non funziona per la matrice di rotazione che ho ricevuto da 'SensorManager.getRotationMatrixFromVector' (usando il sensore' TYPE_ROTATION_VECTOR'). Quando calcolo 'double a = Math.toDegrees (Math.atan ((r [1] - r [3])/(r [0] + r [4])));' (dove r è la matrice di rotazione) Finisco sempre con angoli di -90 <= 'a' <= 90 – Zardoz

9

Quando il dispositivo non è piatto, è necessario chiamare remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR); prima di chiamare getOrientation.

I azimuth rendimenti di getOrientation si ottiene ortogonalmente proiettare l'unità periferica Y axis nel mondo East-North plane e quindi calcolare l'angolo tra il vettore risultante proiezione e l'asse nord.

Ora normalmente pensiamo alla direzione come alla direzione in cui punta la fotocamera posteriore. Questa è la direzione di -Z dove Z è l'asse del dispositivo che punta fuori dallo schermo. Quando il dispositivo è piatto, non pensiamo alla direzione e accettiamo ciò che è stato dato. Ma quando non è pianeggiante, ci aspettiamo che sia la direzione di -Z. Macalcolare la direzione del Y axis, quindi è necessario scambiare il Y and Z axes prima di chiamare getOrientation. Questo è esattamente ciò che fa remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR), mantiene intatto lo X axis e mappa Z to Y.

Ora, quindi, come sapere quando remap oppure no. Puoi farlo selezionando

float inclination = (float) Math.acos(rotationMatrix[8]); 
if (result.inclination < TWENTY_FIVE_DEGREE_IN_RADIAN 
      || result.inclination > ONE_FIFTY_FIVE_DEGREE_IN_RADIAN) 
{ 
    // device is flat just call getOrientation 
} 
else 
{ 
    // call remap 
} 

L'inclinazione sopra è l'angolo tra lo schermo del dispositivo e il piano est-nord del mondo. Mostra quanto il dispositivo è inclinato.

+0

Grazie per la risposta. Tuttavia, questo non è ciò che stanno facendo queste due app di sensori libere perché quando l'inclinazione supera i 25 (o 155 gradi), con il tuo suggerimento le figure di pitch e roll salgono a causa del cambio degli assi. Le figure di pitch and roll per le app di sensori liberi non saltano. Anche l'interruttore degli assi su AXIS_X e AXIS_Z è corretto solo per inclinare in una direzione, per inclinazioni in altre direzioni causa salti azimut scorretti (anche se senza dubbio potrebbe essere corretto regolando gli assi verso cui si sta commutando). – gisking

+0

per i valori di beccheggio e rollio che non chiamate rimappatura, solo per l'azimut. Non capisco cosa intendi inclinando nell'altra direzione? Se intendi che lo schermo non ti sta di fronte, allora sicuramente la direzione è opposta a ciò che è quando lo schermo ti sta di fronte. –

+0

Thsnks per i tuoi pensieri, ma l'altra risposta sembra fornire uno spunto più consistente. – gisking

Problemi correlati