SensorManager.getRotationMatrix()
fa ciò che è descritto di seguito, scritto prima di averlo scoperto. Lascerò la spiegazione aggiunta, perché se vuoi correggere la differenza tra il nord magnetico e il reale, ne avrai ancora bisogno.
L'algoritmo approssimativo è quello di ottenere la matrice di rotazione, moltiplicare il vettore [0,0,-1]
da esso, quindi regolare questo al sistema di coordinate. Perché? Documenti per Android danno i sistemi di coordinate per i dispositivi e mondo


Nota [0,0,-1]
in coords dispositivi Android punti perpendicolari all'indietro lontano dallo schermo. Se moltiplichi la matrice di rotazione R con questo vettore, otterrai [0,0,-1]
nelle coordie mondiali quando il dispositivo è sul tavolo rivolto verso l'alto come desideri. Quando è rivolto verso nord, otterrai [0,-1,0]
, che indica che hai scelto un sistema di coordinate in cui i valori di x
e vengono scambiati rispetto al sistema Android, ma si tratta semplicemente di un cambio di convenzioni.
Nota R * [0,0,-1]^T
è solo la terza colonna di R
negata. Da questo ottengo lo pseudocodice:
getRotationMatrix(R);
Let v = first three elements of third column of R.
swap v[0] and v[1]
Questo dovrebbe ottenere quello che vuoi.
Ulteriori informazioni su cosa fa getRotationMatrix()
come segue.
Sono necessari entrambi i dati dell'accerometro per stabilire la direzione "in basso" ei dati del magnetometro per determinare la direzione "nord". Dovrai supporre che gli accelerometri percepiscano solo la gravità (il dispositivo è fermo o si muove a velocità costante). Quindi è necessario proiettare il vettore del magnetometro sul piano perpendicolare al vettore di gravità (poiché il campo magnetico non è generalmente tangente alla superficie terrestre). Questo ti dà due assi. Il terzo è ortogonale, quindi può essere calcolato dal prodotto incrociato. Questo ti dà i vettori di coordinate terrestri nel sistema del dispositivo. Sembra che tu voglia l'inverso: coordinate del dispositivo in coordinate terrestri. Per questo basta costruire la matrice dei coseni di direzione e invertirli.
Aggiungo che la discussione precedente presuppone che il vettore del magnetometro punti a nord. Penso (dalla scienza del liceo!) è in realtà verso il sud magnetico, ma non ha alcun dispositivo a portata di mano, quindi non può provarlo. Ovviamente il nord/sud magnetico è diverso dal vero da zero a 180 gradi a seconda di dove sei sulla terra. È possibile recuperare le coordinate GPS e calcolare un offset reale.
Se non si ha familiarità con la matematica necessaria per fare queste, posso spiegare ulteriormente, ma dovrà essere in seguito.
Grazie tanto, questo è davvero utile. Entrambi avete dato risposte così buone, vorrei che ci fosse un modo per selezionarle entrambe. Sembra che io possa ottenere il vettore gravitazionale con solo Sensor.TYPE_GRAVITY - hanno fatto quel lavoro per me. Vorrei che fosse altrettanto facile ottenere un vettore "nord". – Joey
Ho finito per ottenerlo usando la tua spiegazione. Risulta che passo i valori restituiti da un sensore di gravità e un sensore di campo magnetico direttamente in getRotationMatrix() e funziona tutto fuori. Quindi ho semplicemente moltiplicato quella matrice per [0,0, -1] e ottenuto il dv. – Joey