Übersicht über die Ausrichtung des Android-Telefons einschließlich Kompass


107

Ich habe eine Weile versucht, mich mit den Android-Orientierungssensoren zu beschäftigen. Ich dachte, ich hätte es verstanden. Dann wurde mir klar, dass ich es nicht tat. Jetzt denke ich (hoffe), ich habe wieder ein besseres Gefühl dafür, aber ich bin immer noch nicht 100%. Ich werde versuchen, mein lückenhaftes Verständnis davon zu erklären, und hoffentlich können mich die Leute korrigieren, wenn ich in Teilen falsch liege oder Lücken ausfülle.

Ich stelle mir vor, ich stehe bei 0 Grad Länge (Nullmeridian) und 0 Grad Breite (Äquator). Dieser Ort ist eigentlich im Meer vor der Küste Afrikas, aber ertrage es mit mir. Ich halte mein Telefon vor mein Gesicht, sodass die Unterseite des Telefons auf meine Füße zeigt. Ich bin nach Norden ausgerichtet (mit Blick auf Greenwich), daher zeigt die rechte Seite des Telefons nach Osten in Richtung Afrika. In dieser Ausrichtung (unter Bezugnahme auf das folgende Diagramm) zeigt die X-Achse nach Osten, die Z-Achse nach Süden und die Y-Achse zum Himmel.

Jetzt können Sie mit den Sensoren am Telefon die Ausrichtung (nicht den Standort) des Geräts in dieser Situation ermitteln. Dieser Teil hat mich immer verwirrt, wahrscheinlich weil ich verstehen wollte, wie etwas funktioniert, bevor ich akzeptierte, dass es einfach funktioniert. Es scheint, dass das Telefon seine Ausrichtung mithilfe einer Kombination aus zwei verschiedenen Techniken ermittelt.

Bevor ich dazu komme, stellen Sie sich vor, Sie stehen wieder auf diesem imaginären Stück Land bei 0 Grad Breite und Länge in der oben genannten Richtung. Stellen Sie sich auch vor, Sie haben die Augen verbunden und Ihre Schuhe sind an einem Kreisverkehr auf einem Spielplatz befestigt. Wenn dich jemand in den Rücken stößt, fällst du nach vorne (in Richtung Norden) und streckst beide Hände aus, um deinen Sturz zu brechen. Wenn jemand Sie auf die linke Schulter schiebt, fallen Sie auf Ihre rechte Hand. Dein Innenohr hat "Gravitationssensoren" (Youtube-Clip), mit denen du erkennen kannst, ob du vorwärts / rückwärts fällst oder nach links / rechts fällst oder runter (oder rauf !!) fällst. Daher kann der Mensch die Ausrichtung und Drehung um die gleichen X- und Z-Achsen wie das Telefon erkennen.

Stellen Sie sich jetzt vor, jemand dreht Sie jetzt im Kreisverkehr um 90 Grad, sodass Sie jetzt nach Osten schauen. Sie werden um die Y-Achse gedreht. Diese Achse ist anders, weil wir sie biologisch nicht nachweisen können. Wir wissen, dass wir um einen bestimmten Betrag abgewinkelt sind, aber wir kennen die Richtung in Bezug auf den magnetischen Nordpol des Planeten nicht. Stattdessen müssen wir ein externes Werkzeug verwenden ... einen Magnetkompass. Auf diese Weise können wir feststellen, in welche Richtung wir blicken. Gleiches gilt für unser Telefon.

Jetzt hat das Telefon auch einen 3-Achsen-Beschleunigungsmesser. Ich habe NEINDie Idee, wie sie tatsächlich funktionieren, aber wie ich sie mir vorstelle, besteht darin, sich die Schwerkraft als konstanten und gleichmäßigen „Regen“ vorzustellen, der vom Himmel fällt, und sich die Achsen in der obigen Abbildung als Röhren vorzustellen, die die Menge des durchfließenden Regens erfassen können. Wenn das Telefon aufrecht gehalten wird, fließt der gesamte Regen durch die Y-Röhre. Wenn das Telefon allmählich gedreht wird, sodass der Bildschirm zum Himmel zeigt, nimmt die durch Y fließende Regenmenge auf Null ab, während die Lautstärke durch Z stetig zunimmt, bis die maximale Regenmenge durchfließt. Wenn wir das Telefon jetzt auf die Seite kippen, sammelt die X-Röhre schließlich die maximale Regenmenge. Abhängig von der Ausrichtung des Telefons können Sie daher die Ausrichtung berechnen, indem Sie die Regenmenge messen, die durch die 3 Röhren fließt.

Das Telefon verfügt außerdem über einen elektronischen Kompass, der sich wie ein normaler Kompass verhält. Die "virtuelle Nadel" zeigt nach Norden. Die Informationen Android verschmilzt aus diesen beiden Sensoren , so dass , wenn ein SensorEventvon TYPE_ORIENTATIONder erzeugten values[3]Array -
Werten [0]: Azimuth - (die Kompaßpeilung östlich von magnetisch Nord)
Werte [1]: Pitch, eine Drehung um die x-Achse (das Telefon
Werte nach vorne oder hinten lehnen [2]: Rollen, Drehen um die y-Achse (beugt sich das Telefon auf der linken oder rechten Seite vor)

Ich denke (dh ich weiß nicht), warum Android den Azimut (Kompasspeilung) anstelle des Ablesens des dritten Beschleunigungsmessers angibt, ist, dass die Kompasspeilung nur nützlicher ist. Ich bin mir nicht sicher, warum sie diesen Sensortyp veraltet haben, da Sie jetzt anscheinend einen Listener für den SensorEventTyp s beim System registrieren müssen TYPE_MAGNETIC_FIELD. Das value[]Array des Ereignisses muss an die SensorManger.getRotationMatrix(..)Methode übergeben werden, um eine Rotationsmatrix (siehe unten) zu erhalten, die dann an die SensorManager.getOrientation(..)Methode übergeben wird. Weiß jemand, warum das Android-Team veraltet ist Sensor.TYPE_ORIENTATION? Ist es eine Effizienzsache? Dies ist in einem der Kommentare zu einer ähnlichen Frage impliziert , aber Sie müssen immer noch einen anderen Hörertyp in der registrierenBeispiel für Entwicklung / Beispiele / Kompass / src / com / Beispiel / android / Kompass / CompassActivity.java .

Ich möchte jetzt über die Rotationsmatrix sprechen. (Hier bin ich mir am unsichersten.) Oben haben wir die drei Abbildungen aus der Android-Dokumentation. Wir nennen sie A, B und C.

A = SensorManger.getRotationMatrix (..) -Methodenfigur und repräsentiert das Koordinatensystem der Welt

B = Koordinatensystem, das von der SensorEvent-API verwendet wird.

C = SensorManager.getOrientation (..) Methodenabbildung

Mein Verständnis ist also, dass A das "Koordinatensystem der Welt" darstellt, von dem ich annehme, dass es sich auf die Art und Weise bezieht, wie Orte auf dem Planeten als Paar (Breite, Länge) mit einer optionalen Höhe (Höhe) angegeben werden. X ist die "Ost" -Koordinate, Y ist die "Nord" -Koordinate. Z zeigt zum Himmel und repräsentiert die Höhe.

Das Telefonkoordinatensystem ist in Abbildung B dargestellt. Die Y-Achse zeigt immer nach oben. Die Rotationsmatrix wird vom Telefon ständig berechnet und ermöglicht die Zuordnung zwischen beiden. Habe ich also Recht, wenn ich denke, dass die Rotationsmatrix das Koordinatensystem von B nach C transformiert? Wenn Sie also die SensorManager.getOrientation(..)Methode aufrufen, verwenden Sie das values[]Array mit Werten, die Abbildung C entsprechen. Wenn das Telefon zum Himmel zeigt, ist die Rotationsmatrix eine Identitätsmatrix (das mathematische mathematische Äquivalent von 1), was bedeutet, dass keine Ausrichtung erforderlich ist, wenn das Gerät ausgerichtet ist mit dem Koordinatensystem der Welt.

OK. Ich denke, ich höre jetzt besser auf. Wie ich schon sagte, ich hoffe, die Leute werden mir sagen, wo ich Menschen durcheinander gebracht oder geholfen habe (oder Menschen noch weiter verwirrt habe!)


25
Diese Frage gefällt mir sehr gut. Ich kann es nicht beantworten, aber ich mag es.
Octavian A. Damiean

4
Tim, hast du jemals eine Antwort bekommen? Ich habe mir gleichzeitig den Kopf gekratzt. Dies ist eine der am schlechtesten dokumentierten APIs, die ich je gesehen habe.
Pierre-Luc Paour

Ich fürchte nicht wirklich. Ich musste weitermachen. Eines Tages werde ich auf dieses Thema zurückkommen.
Tim

1
Hier habe ich fast die gleiche Frage? Und die Antwort, Lösung auch. Hergestellt Öffentlichkeit meinen Code auf Github.

Das gleiche, worüber ich mich wundere, ich habe einen Kompass auf einem Android-Gerät implementiert und funktioniert einwandfrei, wenn ich Hilfe aus dem Internet genommen habe. Es funktioniert einwandfrei, aber das Verwirrende ist ... Angenommen, mein Gerät befindet sich auf dem Boden auf mich zu und es zeigt nach Norden jetzt nehme ich mein Handy und lege es senkrecht über meinen Kopf ohne und das Gesicht ist immer noch auf mich gerichtet. Erstens sollte die Nadel ihre Richtung ändern und warum. Ich denke, es sollte nicht so sein, da ich meine Richtung nicht geändert habe, aber es ändert sich in meiner App und allen anderen Apps, die ich heruntergeladen habe. Kann jemand erklären warum?
Syed Raza Mehdi

Antworten:


26

Vielleicht möchten Sie sich die One Screen Turn Deserves Another ansehen Artikel lesen. Es erklärt, warum Sie die Rotationsmatrix benötigen.

Kurz gesagt, die Sensoren des Telefons verwenden immer das gleiche Koordinatensystem, auch wenn das Gerät gedreht wird.

In Anwendungen, die nicht an eine einzelne Ausrichtung gebunden sind, ändert sich das Bildschirmkoordinatensystem, wenn Sie das Gerät drehen. Wenn das Gerät aus dem Standardansichtsmodus gedreht wird, stimmt das Sensorkoordinatensystem nicht mehr mit dem Bildschirmkoordinatensystem überein. Die Rotationsmatrix wird in diesem Fall verwendet, um A nach C zu transformieren (B bleibt immer fest).

Hier ist ein Code-Snippet, das Ihnen zeigt, wie es verwendet werden kann.

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);

// Register this class as a listener for the accelerometer sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                    SensorManager.SENSOR_DELAY_NORMAL);

//...
// The following code inside a class implementing a SensorEventListener
// ...

float[] inR = new float[16];
float[] I = new float[16];
float[] gravity = new float[3];
float[] geomag = new float[3];
float[] orientVals = new float[3];

double azimuth = 0;
double pitch = 0;
double roll = 0;

public void onSensorChanged(SensorEvent sensorEvent) {
    // If the sensor data is unreliable return
    if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        return;

    // Gets the value of the sensor that has been changed
    switch (sensorEvent.sensor.getType()) {  
        case Sensor.TYPE_ACCELEROMETER:
            gravity = sensorEvent.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomag = sensorEvent.values.clone();
            break;
    }

    // If gravity and geomag have values then find rotation matrix
    if (gravity != null && geomag != null) {

        // checks that the rotation matrix is found
        boolean success = SensorManager.getRotationMatrix(inR, I,
                                                          gravity, geomag);
        if (success) {
            SensorManager.getOrientation(inR, orientVals);
            azimuth = Math.toDegrees(orientVals[0]);
            pitch = Math.toDegrees(orientVals[1]);
            roll = Math.toDegrees(orientVals[2]);
        }
    }
}

4
Erwähnen Sie einfach, dass Azimut, Pitch und Roll NICHT mit dem veralteten OrientationSensor identisch sind. orientation[0] = orientation[0] >= 0 ? orientation[0]: orientation[0] + 360;wird Azimut normalisieren und if (orientation[1] <= -90) { orientation[1] += (-2*(90+orientation[1])); } else if(orientation[1] >= 90){ orientation[1] += (2*(90 - orientation[1])); }Tonhöhe normalisieren
Rafael T

@ RafaelT und Roll zu normalisieren? Oder macht das keinen Sinn?
Matthias

@RafaelT: Ihre Normalisierung des Azimuts scheint Auswirkungen zu haben: Die Werte reichen von [-180,180] bis [0, 360]. Die Tonhöhenwerte, die ich erhalte, sind jedoch bereits in [-90,90], sodass die von Ihnen vorgeschlagene Normalisierung keine Auswirkung hat.
Matthias

Was bedeutet es, wenn nach der Überprüfung (Schwerkraft! = Null && Geomag! = Null) der Wert von Geomag immer 0 ist, unabhängig davon, wie ich das Tablet bewege? Könnte ein Tablet ohne Geomag-Sensor sein?
Fortgeschrittene

3

Rolle ist eine Funktion der Schwerkraft, eine 90-Grad-Rolle bringt die gesamte Schwerkraft in das x-Register.

Die Tonhöhe ist die gleiche. Bei einer 90-Grad-Steigung wird die gesamte Schwerkraftkomponente in das y-Register eingetragen.

Gieren / Kurs / Azimut hat keinen Einfluss auf die Schwerkraft, es ist IMMER im rechten Winkel zur Schwerkraft, daher ist es unermesslich, egal in welche Richtung Sie der Schwerkraft gegenüberstehen.

Deshalb brauchen Sie einen Kompass, um zu beurteilen, vielleicht macht das Sinn?



0

Ich hatte dieses Problem, also habe ich herausgefunden, was in verschiedene Richtungen passiert. Wenn das Gerät im Querformat montiert ist, z. B. in einer Autohalterung, scheinen die Grad vom Kompass zwischen 0 und 275 (im Uhrzeigersinn) über 269 (zwischen West und Nord) zu liegen. Dann zählt es von -90 bis 0 rückwärts vorwärts von 0 bis 269. 270 wird -90

Immer noch im Querformat, aber mit dem Gerät auf dem Rücken, gibt mein Sensor 0-360 aus. und im Hochformat läuft es 0-360, sowohl auf dem Rücken liegend als auch im Hochformat stehend.

Hoffe das hilft jemandem

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.