9

Ich versuche, eine einfache Augmented Reality App zu erstellen, damit ich mit Sensor Daten arbeiten.Android: Probleme bei der Berechnung der Ausrichtung des Geräts

Gemäß dieses Gewinde (Android compass example) und Beispiel (http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html), die Berechnung der Orientierung des Sensor.TYPE_ACCELEROMETER und Sensor.TYPE_MAGNETIC_FIELD verwendet, nicht wirklich passen.

So kann ich nicht "gute" Werte bekommen. Die Azimut-Werte ergeben überhaupt keinen Sinn. Wenn ich das Telefon nur nach oben bewege, ändert sich der Wert extrem. Selbst wenn ich nur das Telefon rotiere, repräsentieren die Werte nicht die Telefonausrichtung.

Hat jemand eine Idee, wer die Wertequalität entsprechend dem gegebenen Beispiel verbessern soll?

Antwort

0

Haben Sie den kombinierten (Sensor-Fusion) Typ Sensor.TYPE_ROTATION_VECTOR versucht. Dies kann zu besseren Ergebnissen führen: Gehen Sie zu https://developer.android.com/reference/android/hardware/SensorEvent.html und suchen Sie nach 'rotation_vector'.

+1

Ok, gibt es ein Beispiel, wie man mit diesem Sensor arbeitet? Ich bekomme Werte für x * sin (θ/2), y * sin (θ/2) und z * sin (θ/2). Aber wie bekomme ich den Wert, ich muss meinen Kompass bauen. Soll ich getRotationMatrix erneut benutzen? Danke für Ihre Hilfe. –

+0

"X ist definiert als das Vektorprodukt Y.Z (es ist tangential zum Boden an der aktuellen Position des Geräts und zeigt grob nach Osten). Y ist tangential zum Boden an der aktuellen Position des Geräts und zeigt in Richtung magnetischen Norden. Z zeigt auf den Himmel und ist senkrecht zum Boden. " Stauben Sie Ihre Geometrie Klassenbücher, oder google es :), und Sie sollten in der Lage sein, es herauszufinden. –

19

In welcher Orientierung verwenden Sie diese Beispiel-App? Von dem, was geschrieben wird, ist dieser Code, die einzige unterstützte Ausrichtung ist Portrait oder flach auf dem Tisch, es hängt von Geräten ab. Was meinst du mit "gut"?

Es ist normal, dass der Wert nicht "gut" ist, wenn das Gerät gedreht wird, das Gerätekoordinatensystem sollte im Hochformat arbeiten, oder flach ich weiß es nicht (Y - Achse vertikal entlang des Bildschirms nach oben, Z Achse zeigt aus dem Bildschirm von der Mitte des Bildschirms, X-Achse senkrecht zur Y-Achse auf der rechten Seite auf dem Bildschirm gehen). Wenn Sie das Gerät drehen, wird das Koordinatensystem des Geräts nicht gedreht. Sie müssen es neu zuordnen.

Aber wenn Sie die Überschrift des Geräts im Hochformat-Orientierung wollen, hier ist ein Stück Code, der für mich gut funktioniert:

@Override 
public void onSensorChanged(SensorEvent event) 
{ 
    // It is good practice to check that we received the proper sensor event 
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) 
    { 
     // Convert the rotation-vector to a 4x4 matrix. 
     SensorManager.getRotationMatrixFromVector(mRotationMatrix, 
       event.values); 
     SensorManager 
       .remapCoordinateSystem(mRotationMatrix, 
         SensorManager.AXIS_X, SensorManager.AXIS_Z, 
         mRotationMatrix); 
     SensorManager.getOrientation(mRotationMatrix, orientationVals); 

     // Optionally convert the result from radians to degrees 
     orientationVals[0] = (float) Math.toDegrees(orientationVals[0]); 
     orientationVals[1] = (float) Math.toDegrees(orientationVals[1]); 
     orientationVals[2] = (float) Math.toDegrees(orientationVals[2]); 

     tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: " 
       + orientationVals[1] + "\n Roll (not used): " 
       + orientationVals[2]); 

    } 
} 

Sie werden die Überschrift erhalten (oder Azimut) in:

orientationVals[0] 
+1

Für den Rekord habe ich diesen Code mit einem 3x3 versucht Matrix, aber es funktioniert nur mit 4x4 (aka float [16]) – MonoThreaded

+0

für meine auch mit 4 * 4 (aka float [16]) –

7

Wahrscheinlich zu spät zur Party. Auf jeden Fall ist hier, wie habe ich den Azimut

private final int sensorType = Sensor.TYPE_ROTATION_VECTOR; 
float[] rotMat = new float[9]; 
float[] vals = new float[3]; 

@Override 
public void onSensorChanged(SensorEvent event) { 
    sensorHasChanged = false; 
    if (event.sensor.getType() == sensorType){ 
     SensorManager.getRotationMatrixFromVector(rotMat, 
       event.values); 
     SensorManager 
       .remapCoordinateSystem(rotMat, 
         SensorManager.AXIS_X, SensorManager.AXIS_Y, 
         rotMat); 
     SensorManager.getOrientation(rotMat, vals); 
     azimuth = deg(vals[0]); // in degrees [-180, +180] 
     pitch = deg(vals[1]); 
     roll = deg(vals[2]); 
     sensorHasChanged = true; 
    } 
} 

Hoffe, dass es

+0

Der 'remapCoordinateSystem' Aufruf ist nur die Identitätstransformation, so dass es redundant ist. Schlimmer noch, es ist "rotMat" für die Eingabe und Ausgabe, etwas, was die Dokumentation explizit sagt, sollten Sie nicht tun. – Thomas

+0

Danke, das funktioniert! – Bogdan

11

Antwort hilft von Tibo ist gut, aber wenn Sie Roll-Wert anmelden, werden Sie unregelmäßige Zahlen erwarten. (Rolle ist wichtig für die AR-Browser)

Dies zu

gebührt
SensorManager.remapCoordinateSystem(mRotationMatrix, 
        SensorManager.AXIS_X, SensorManager.AXIS_Z, 
        mRotationMatrix); 

Sie haben verschiedene Matrix verwenden, um in und aus remap. Dieser folgende Code funktioniert bei mir mit einem korrekten Roll-Wert:

@Override 
public void onSensorChanged(SensorEvent event) 
{ 
    // It is good practice to check that we received the proper sensor event 
    if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) 
    { 
     // Convert the rotation-vector to a 4x4 matrix. 
     SensorManager.getRotationMatrixFromVector(mRotationMatrixFromVector, event.values); 
     SensorManager.remapCoordinateSystem(mRotationMatrixFromVector, 
        SensorManager.AXIS_X, SensorManager.AXIS_Z, 
        mRotationMatrix); 
     SensorManager.getOrientation(mRotationMatrix, orientationVals); 

     // Optionally convert the result from radians to degrees 
     orientationVals[0] = (float) Math.toDegrees(orientationVals[0]); 
     orientationVals[1] = (float) Math.toDegrees(orientationVals[1]); 
     orientationVals[2] = (float) Math.toDegrees(orientationVals[2]); 

     tv.setText(" Yaw: " + orientationVals[0] + "\n Pitch: " 
       + orientationVals[1] + "\n Roll (not used): " 
       + orientationVals[2]); 

    } 
} 
+0

Ja, Sie können im Quellcode einchecken: öffentliche statische boolean remapCoordinateSystem (float [] inR, int X, int Y, float [] outR) * @param outR * die transformierte Rotationsmatrix. inR und outR sollten nicht gleich * array sein. – codevscolor