Hallo donathus,
das ist ja schon ganz schön kompliziert.
Ich lese mich gerade ein bißchen durch den android devguide.
Ich habe den Eindruck, dass sich für die Lagebestimmung der
„Rotation Vector Sensor“ eignet
(http://developer.android.com/guide/topics/sensors/se… ganz unten und
http://www.sensorplatforms.com/which-sensors-in-andr…).
Weiß nur noch nicht wie.
Ich beschreib jetzt einfach mal, wie sich das Orientierungsproblem für mich darstellt
und vielleicht kommen wir dann auf einen Nenner.
Also zunächst die „Hardwaresituation“: Jemand hat das Handy am Hinterkopf - vermutlich in irgendeiner Halterung, so dass eine exakte Ausrichtung zu den Drehachsen des Kopfes nicht vorliegt und die reale Ausrichtung des Handys zu der „idealen“ Ausrichtung transformiert werden muss.
Dies könnte man durch eine kurze Kalibrationssequenz sicherstellen, z.B. indem der Spieler auf einen festgelegten Punkt vor ihm auf 0°/0° (links-rechts/oben-unten) schaut und die Rotation des Handys bezüglich der idealen Achsen festgestellt wird (z.B. durch den Gravity Sensor).
Dann stelle ich mir vor, dass der Spieler genau nach vorne schaut, das Handy ist kalibriert.
Entlang der optischen Achse der Augen verläuft die Horizontebene des Spielers. Oder anders ausgedrückt:
Die Sichtachse verläuft in Verlängerung der -z-Achse des Handys, die x-Achse des Handys spannt die Horizontebene auf.
An der folgenden Stelle bin ich mir jetzt nicht mehr sicher:
Erste Möglichkeit: Spielen sich die Aktionen auf einer Bildebene vor dem Betrachter ab? Du schreibst von Mausbewegungen relativ_x und relativ_y, deshalb komme ich darauf.
Oder - zweite Möglichkeit- kann man sich die von den Bildschirmen dargestellten Bilder als Bilder vorstellen, die sich auf einer Kugelfläche vor dem Betrachter projiziert befinden?
Intuitiv würde ich sagen, dass sich die Position des Cursors eher durch Winkel theta (rauf-runter)
und phi (links-rechts) beschreiben lassen sollte.
Sollte dieser zweite Fall stimmen, dann könnte man nämlich ein schönes Koordinatensystem in die Mitte des Kopfes des Spielers konstruieren. Die Sichtachse nach vorne würde sich in Verlängerung der Position des Handys nach hinten befinden. Der Horizont würde über die x-Achse des Handys festgelegt.
Jetzt lassen sich folgende Bewegungen durchführen, die alle für sich detektiert werden müssen.
- Drehung des Kopfes nach links-rechts
- Nicken des Kopfes nach oben-unten
- Kippen (Rollen) des Kopfes entlang der z-Achse des Handys in Neutralposition
Diese Bewegungen können eigentlich durch den Sensor „TYPE_ORIENTATION“ bestimmt werden (http://developer.android.com/guide/topics/sensors/se…)
Allerdings ist dieser Type seit Android 2.2 als „deprecated“ eingestuft. Stattdessen wird auf die Methoden „getRotationMatrix()“ und „getOrientation()“ verwiesen.
Aber vielleicht lässt sich hier der Sensor „TYPE_ROTATION_VECTOR“ ausnutzen. Mit diesem lässt sich die Drehung des Handys bezüglich bestimmter Achsen auslesen
(sieh dazu http://developer.android.com/reference/android/hardw… unter diesem Sensor).
Da wir ja eigentlich nur Drehbewegungen haben, scheint dies ein vielversprechender Weg zu sein.
Mit getRotationMatrix() werden diese Daten dann in ein Weltkoodinatensystem transformiert.
Ich vermute, dass sich Position des Handys auf der Kugelschale dann als Vektor ausgeben lässt.
Der antiparallele Vektor zu diesem wäre dann der Sichtachsenvektor.
Zusammenfassend will ich sagen, dass es wahrscheinlich sinnvoller ist, einen für diesen Zweck geeigneten virtuellen Sensor und ein paar Methoden zu verwenden, als das Rad neu zu erfinden und die Rohdaten der Beschleunigungsensoren mit aufwendiger Mathematik zu beackern.
Da ich von der Androidprogrammierung (noch) nicht so viel verstehe, sind diese ganzen Aussagen natürlich unter Vorbehalt zu verstehen. Bin aber gespannt, was Du dazu meinst. Helfen könnte ich dann wieder bei möglichen Verständnisproblemen bezüglich Sinn und Eigenschaften von Rotationsmatrizen.
Schöne Grüße aus dem Schwabenland,
Daniel
P.S.: Vielleicht hilft diese Demo hier noch weiter http://developer.android.com/resources/samples/ApiDe…