2012-06-24 21 views
20

Ich habe versucht, die Z-Achse Daten von SensorEvent.values ​​zu verwenden, aber es erkennt keine Drehung meines Telefons in der XY-Ebene, dh. um die Z-Achse.So messen Sie die Neigung des Telefons in der XY-Ebene mit Beschleunigungsmesser in Android

Ich verwende dies als Referenz für die Koordinatenachsen. Ist es richtig?

axes

Wie kann ich messen die Beschleunigungsmesser Werte enden Bewegungen?

Diese Spiele tun etwas ähnliches: Extreme Skater, Doodle Jump.

PS: meine Telefonausrichtung wird Landschaft sein.

Antwort

56

Im Wesentlichen gibt es hier zwei Fälle: Das Gerät liegt flach und nicht flach. Flach bedeutet hier, dass der Winkel zwischen der Oberfläche des Bildschirms des Geräts und der Welt-XY-Ebene (ich nenne es die Neigung) weniger als 25 Grad oder mehr als 155 Grad ist. Stellen Sie sich vor, dass das Telefon flach liegt oder nur ein kleines Stück von einem Tisch entfernt ist.

Zuerst müssen Sie den Vektor des Beschleunigungsmessers normalisieren.
Das ist, wenn g der Vektor ist, der durch die Sensorereigniswerte des Beschleunigungsmessers zurückkehrt. In Code

float[] g = new float[3]; 
g = event.values.clone(); 

double norm_Of_g = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]); 

// Normalize the accelerometer vector 
g[0] = g[0]/norm_Of_g 
g[1] = g[1]/norm_Of_g 
g[2] = g[2]/norm_Of_g 

Dann kann die Neigung als

int inclination = (int) Math.round(Math.toDegrees(Math.acos(g[2]))); 

So

if (inclination < 25 || inclination > 155) 
{ 
    // device is flat 
} 
else 
{ 
    // device is not flat 
} 

Für den Fall der Verlegung flach, müssen Sie einen Kompass berechnet werden, wie viel das Gerät zu sehen dreht sich von der Startposition.

Für den Fall der nicht flach wird die Drehung (Neigung) wie folgt berechnet

int rotation = (int) Math.round(Math.toDegrees(Math.atan2(g[0], g[1]))); 

Jetzt Rotation = 0 bedeutet, das Gerät in Normalstellung befindet. Das ist Porträt ohne Neigung für die meisten Handys und wahrscheinlich Landschaft für Tablet. Wenn Sie also ein Telefon wie in Ihrem Bild oben halten und sich zu drehen beginnen, ändert sich die Drehung und wenn das Telefon im Querformat ist, ist die Drehung 90 oder -90 hängt von der Drehrichtung ab.

+4

Brilliant! In der Regel empfehlen die Benutzer die Verwendung von Sensor.TYPE_MAGNETIC_FIELD für diese Aufgabe, jedoch haben Sie die Lösung vereinfacht. und übrigens ist der Beschleunigungssensor der einzige Sensor, der garantiert auf Android vorhanden ist. – southerton

+1

Kann ich Sie fragen, was ist die Mathematik hinter der "Normalisierung des Acc-Vektor?" und warum tust du atan (g [1]/g [0]) (oder atan (y/x)), um die Grade zu bekommen? ? @Hoan Nguyen –

+0

@AndreaBaccega Ich habe vergessen, warum ich normalisieren muss oder es überhaupt keine Notwendigkeit gibt, nur etwas, was ich für andere Dinge tun muss. Der Atan (y/x) ist nur eine einfache trigonometrische Berechnung. Um die Rotation zu finden, müssen Sie zuerst die Schwerkraft in die xy-Ebene projizieren. Wenn es keine Rotation gibt, wird dieser Projektionsvektor eine Koordinate (0,1) haben (unter der Annahme einer Normalisierung). Wenn das Gerät gedreht wird, ist dieser Vektor der gleiche, aber die Koordinaten ändern sich und der Winkel zwischen diesem Vektor und der Geräte-Y-Koordinate ist nur tan (y/x). –

0

Der Beschleunigungssensor ist ausreichend für die Überprüfung, ob das Telefon flach ist, wie Hoan sehr schön demonstriert.

Für alle, die hier ankommen, um nicht nur zu überprüfen, ob das Telefon flach ist, aber was die Drehung des Telefons ist, kann es durch die Rotation Vector Motion Sensor erreicht werden.

private double pitch, tilt, azimuth; 

@Override 
public void onSensorChanged(SensorEvent event) { 
    //Get Rotation Vector Sensor Values 
    double[] g = convertFloatsToDoubles(event.values.clone()); 

    //Normalise 
    double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]); 
    g[0] /= norm; 
    g[1] /= norm; 
    g[2] /= norm; 
    g[3] /= norm; 

    //Set values to commonly known quaternion letter representatives 
    double x = g[0]; 
    double y = g[1]; 
    double z = g[2]; 
    double w = g[3]; 

    //Calculate Pitch in degrees (-180 to 180) 
    double sinP = 2.0 * (w * x + y * z); 
    double cosP = 1.0 - 2.0 * (x * x + y * y); 
    pitch = Math.atan2(sinP, cosP) * (180/Math.PI); 

    //Calculate Tilt in degrees (-90 to 90) 
    double sinT = 2.0 * (w * y - z * x); 
    if (Math.abs(sinT) >= 1) 
     tilt = Math.copySign(Math.PI/2, sinT) * (180/Math.PI); 
    else 
     tilt = Math.asin(sinT) * (180/Math.PI); 

    //Calculate Azimuth in degrees (0 to 360; 0 = North, 90 = East, 180 = South, 270 = West) 
    double sinA = 2.0 * (w * z + x * y); 
    double cosA = 1.0 - 2.0 * (y * y + z * z); 
    azimuth = Math.atan2(sinA, cosA) * (180/Math.PI); 
} 

private double[] convertFloatsToDoubles(float[] input) 
{ 
    if (input == null) 
     return null; 

    double[] output = new double[input.length]; 

    for (int i = 0; i < input.length; i++) 
     output[i] = input[i]; 

    return output; 
} 

dann zu prüfen, ob das Telefon flach ist, dass Sie einfach die tilt und pitch Werte mit Toleranzwerten vergleichen. Zum Beispiel

Der Vorteil auf diese Weise ist, können Sie überprüfen, ob das Telefon in einer bestimmten Rotation gehalten wird.

Es ist erwähnenswert, dass die Ausrichtung der App die Werte für Tonhöhe, Neigung und Azimut nicht beeinflusst.