# Sensor Orientierung -> GLRotation stimmt nicht



## JavaTobi (30. Jul 2012)

Hallo zusammen,
ich weiß, das ist eine etwas komplexere Frage, aber ich hoffe, irgendwer hat eine Idee für mich.
Das Ziel ist einfach: Mit den Sensordaten die Lage des Handys bekommen und meiner GLES Kamera als Rotationsmatrix zuweisen.
Ich habe hier ein sehr gutes Beispiel gefunden, das allerdings mit GL1.0 funktioniert:
android - How to use onSensorChanged sensor data in combination with OpenGL - Stack Overflow

Nun arbeite ich aber mit eigenen Shadern. Diese funktionieren soweit auch. Jedenfalls wenn ich die Kamera manuell über die Methoden der Matrix Klasse benutze.

Ich nutze also die selben Methoden und generiere über

```
SensorManager.getRotationMatrix(rotationMatrix, null, bufferedAccelGData, bufferedMagnetData);
```
meine Rotationsmatrix.
Da meine Applikation / Activity in LANDSCAPE läuft, nutze ich noch folgende Methode:


```
float[] result = new float[16];
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, result);
return result;
```

Die schon in der GL1.0 Version (Siehe ogn. Link) in Landscape Modus funktioniert hat.
Das Problem ist, der Screen sieht beim Starten so aus:






Die Rotationsmatrix scheint also offenbar gedreht zu sein. Ich habe schon überlegt, ob meine RemapMethode irgendwie falsch ist, aber andere Werte ergeben keinen Sinn. Die Kamerabewegung funktioniert jetzt nämlich genau richtig. (Abgesehen von der Rotation). Neige ich das Handy nach unten, neigt sich meine gedrehte Kamera auch nach unten. Also in die richtige Richtung. Es sind nur alle Objekte praktisch um 90° nach rechts (CCW auf der Z Achse) verschoben. Mein Boden ist eine  rechte Wand...
In der Draw Methode passiert aber nichts, was das jetzt rechtfertigen würde, denke ich:


```
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
MatrixStack.glLoadMatrix(sensorManager.getRotationMatrix());  // Schreibt die MVMatrix mit der ogn. Rotationsmatrix
GameRenderer.setPerspMatrix(); // Schreibt die Perspektivmatrix Uniform für GLES. Daran sollte es nicht liegen.
MatrixStack.mvPushMatrix();
  drawGround();    
MatrixStack.mvPopMatrix();
```

Wie gesagt, gebe ich manuell Werte ein, klappt alles wunderbar. Was ist also mit meiner Rotationsmatrix falsch?
Ich weiß, es ist schwer zu sagen, aber vielleicht hat irgendwer einen Tipp für mich.

Vielen Dank, ich hoffe, ihr könnt mir helfen!

  Tobias


----------



## Marco13 (30. Jul 2012)

Sorry, ich kenn mich damit nicht aus, eher aus Neugier: Was passiert, wenn man das "remapCoordinateSystem" NICHT macht?


----------



## JavaTobi (30. Jul 2012)

Danke trotzdem, dass Du es versuchst.
Tja, abgesehen davon, dass es in dem GL10 Beispiel ja auch genau so funktioneirt löst es leider mein Problem nicht, macht es nur kryptischer.
Lasse ich das aus, stimmen die Koordinaten gar nicht mehr. Schwer zu beschreiben. Die Achsen "laufen nicht mit". Das bedeutet wenn ich mich in eine gewisse Richtung drehe, stimmt alles.
Beispielsweise nach "Vorne". Wenn ich jetzt das Handy nach unten Neige, beugt sich die GLKamera auch mit nach unten.
Drehe ich mich allerdings um 90° zur Seite und neige das Handy, beugt sich die Kamera immernoch in die gleiche Richtung (also jetzt zur Seite.) Ich habe also einen Schaukeleffekt. So als ob "Nach vorne Rotieren" immer in die gleiche Richtung geht.
Das führt soweit, dass bei 180° Drehung plötzlich alles auf dem Kopf steht, auch wenn dann ein Neigen wieder in der richtigen Achse ist - wenn auch umgekehrt...
Ich hoffe, das war verständlich?


----------



## JavaTobi (3. Aug 2012)

Huh, tut mir leid, dass ich ständig frage aber hat denn niemand eine Idee?


----------



## Marco13 (3. Aug 2012)

Vermutlich gibt es nicht viele Leute, die das in dieser Form verwenden (was ein gutes oder ein schlechtes Zeichen sein kann, aber ich glaube, hier ist es für dich eher ein gutes  ). 

Die Beschreibung war ... auch nicht besonders verständlich. Wie soll man das auch beschreiben? Ich weiß leider nicht mal, wie die "Achsen des Gerätes" definiert sind 

Die _Bewegung_ des Handys (sorry: Smartphones) wird, wenn das "remapCoordinateSystem" verwendet wird, richtig übersetzt? Bedeutet das nicht, dass die Matrix, die von dem Sensor geliefert wird, "richtig" ist, aber eine andere Matrix (die ggf. mit dieser Sensormatrix multipliziert wird) "falsch" ist? (Wenn man die dann korrigieren würde, müßten wohl auch diese AXIS_aaa und AXIS_bbb vom remapCoordinateSystem entsprechend angepasst werden, aber im Moment habe ich einen leichten Knoten im Hirn  ). Vielleicht mal ganz pragmatisch: Wenn man diese Orientierung, die vom Sensor geliefert wird, ignoriert (also ggf. auskommentiert oder die Einheitsmatrix verwendet) - stimmt dann das, was gerendert wird? Also stimmen dann das, was OpenGL 1.0 und das, was dein Shaderprogramm rendern, genau überein? (Nur um den Fehler einzugrenzen...)


----------



## JavaTobi (3. Aug 2012)

Hallo Marco,
danke für die Antwort.
Ja, es ist schwer, etwas räumliches zu beschreiben. Ich wills nochmal anders versuchen.
Mein Problem ist einfach eine Verschiebung der Achsen. Das soll heißen, wenn ich das Handy flach auf den Tisch lege und im Porträt / Längs drauf schaue, stimmt alles. Hebe ich dann das Handy "hoch" (Was wohl der Y Achse der Sensoren entspricht, wird auch die Kamera nach oben bewegt. 
Rotiere ich das Handy flach auf dem Tisch hin und her wird die Kamera auch um die Z Achse gerollt. Soweit stimmt alles und ich bin mir folglich sicher, dass die Sensoren stimmen. Auch die GL Kamera funktioniert. Wenn ich alles über einzelne Methoden selber bewege - also wie bei GL1.1 mit gl.Rotate() - klappt das auch soweit.
Das klingt soweit nicht nach einem Problem, bis ich jetzt aber das Handy in LANDSCAPE vor mich halten will. Denn dann ist die Ausrichtung für das Handy ja gedreht. Ich habe also, wenn ich das Handy auf Augenhöhe vor mir halte ein gegen den Uhrzeigersinn gedrehtes Bild.
Ich habe mit SensorManager.remapCoordinateSystem schon vergeblich herumprobiert und vermute, dass sich das irgendwie damit lösen lassen könnte aber ich weiß nicht wie.
Auch die dazugehörige Activity ist bereits in LANDSCAPE definiert, nur falls die Sensoren davon irgendwie beeinflusst werden sollten.
Und jetzt stellt sich die Frage, was ich da tun kann...
Ich hoffe, das ist soweit verständlicher gewesen.


----------



## JavaTobi (3. Aug 2012)

Okay, vielleicht versuch ich es auch in zu großen Schritten.
In der Android API steht hier:
SensorEvent | Android Developers

"The axes are not swapped when the device's screen orientation changes."
Das klingt ja schon einmal nach meinem Problem. Immerhin würde es ja im Porträtmodus besser aussehen. Aber ich weiß leider nicht, wie ich die Sensordaten dann mit dem LANDSCAPE Modus verrechnen kann.
Vielleicht hat ja einer von euch eine Idee!
Danke nochmals,
 Tobias


----------



## Marco13 (4. Aug 2012)

Hm. Bei der Doku der "remap"-Methode stand was, dass man die Rotation direkt mit Display.getRotation() bekommen könnte, aber wie man die dann mit der Kameramatrix verwusten könnte, da müßte ich auch erst überlegen (schwierig vor allem wenn man's nicht testen kann und eigentlich kein Hintergrundwissen hat). Ich hatte kurz überlegt, ob das durch eine reine zusätzliche Rotation um die "Sichtlinie" (also um die Z-Achse) abgedeckt werden könnte - DA bin ich dann aber davon ausgegangen, dass sich das mit den Sensorinformationen beißt, und man die AXIS-Parameter beim remap irgendwie darauf anpassen müßte...


----------



## JavaTobi (4. Aug 2012)

Ja, das Remappen bewirkt ja das rotieren um die Z Achse und damit die Drehung nach rechts (also praktisch -90° um Z).
Lasse ich das weg, komme ich zu dem Zustand wie ich ihn zuletzt beschrieben habe, dass ich das Handy flach auf den Tisch legen kann und dann dort alle Achsen stimmen.
Ich müsste also praktisch 2mal die Achsen neu remappen. Einmal, dass "unten" (G) nicht in Z-Achse des Handys sondern jetzt in X Richtung liegt (Ich drehe es ja so, dass das Handy mit der Kante nach unten zeigt, wenn ich es hoch hebe.
Und dann _nochmal_ weil ich es zur Seite gekippt habe und es nun in _Landscape_ liegt.
Hmm, wenn ich so drüber nachdenke... ob man die remap-Methode auch mehrmals anwenden kann??? Ich werde das mal ausprobieren, vielleichtklappt das ja. Nur leider bietet die nur Möglichkeit die X und Y Achse neu zu mappen aber bei mir ist es ja auch die Z-Achse, die sich verschiebt (durch das Ändern der Lage von Liegend auf Stehend)
Huh, ich weiß, schwerer Brocken. Danke trotzdem schon mal für den Versuch!


----------



## Marco13 (4. Aug 2012)

Ich betone nochmal: Ich habe das alles nie verwendet, kann es nicht testen, und habe die Doku (deswegen?) auch bisher nur überflogen. Aber bisher sehe ich keinen Grund, warum man remap nicht zweimal anwenden können sollte. Vermutlich muss man vorsichtig sein, wegen der Reihenfolge (also man muss sich genau überlegen, auf welche Achse sich das zweite "remap" dann bezieht), aber ... einen Versuch ist's wert  (sorry dass ich nicht zielgerichteter helfen kann  )


----------



## Matthias K. (5. Aug 2012)

Hi,
bearbeite doch die Rotationsmatrix lokal.

```
Matrix matrix = sensorManger.getRotationMatrix();
```
Nun kannst du die Werte der Matrix z.B. per LogCat anzeigen lassen und die Rotationwerte ermitteln.
Normalerweise beschreibt diese Matrix nämlich immer die Position, Rotation und Skalierung.
Schreibe die Matrix in ein Array, ändere den falschen Wert und setzte sie als deine OpenGL-Matrix.


----------



## JavaTobi (6. Aug 2012)

Matthias K. hat gesagt.:


> Hi,
> bearbeite doch die Rotationsmatrix lokal.
> 
> ```
> ...



Tja, das Problem ist, dass hier haufenweise Mathematik (lauter Cosinuswerte verrechnen) und Arbeitsaufwand drin steckt. Dabei klingt es ja so, als wenn man bspw. mit der remap Methode hier relativ einfach die Achsen vertauschen könnte... Deshalb hatte ich ja gehofft, dafür gäbe es eine praktikable Lösung.


----------



## lumo (20. Aug 2012)

ich hab jetzt mal alles überflogen was ihr hier schon behandelt habt...
hast du schon mal versucht deine GL_PERSPECTIVE einfach per GL_ROTATE um 90° zu drehen? (nur bei dem modus der nicht passt...)?
h
PS:  hab mit OGL schon recht lange nix mehr gemacht, aber damals (OGL2.0) ging das so


----------

