Die Android-Plattform bietet mehrere Sensoren, mit denen Sie die Bewegung eines Geräts überwachen können.
Die möglichen Architekturen der Sensoren variieren je nach Sensortyp:
- Die Sensoren für Schwerkraft, lineare Beschleunigung, Drehvektor, signifikante Bewegung, Schrittzähler und Schritterkennung sind entweder hardware- oder softwarebasiert.
- Beschleunigungsmesser und Gyroskop sind immer hardwarebasiert.
Die meisten Android-Geräte haben einen Beschleunigungsmesser und viele haben jetzt auch ein Gyroskop. Die Verfügbarkeit der softwarebasierten Sensoren ist variabler, da sie oft einen oder mehrere Hardwaresensoren zur Ableitung ihrer Daten benötigen. Je nach Gerät können diese softwarebasierten Sensoren ihre Daten entweder vom Beschleunigungsmesser und Magnetometer oder vom Gyroskop ableiten.
Bewegungssensoren sind nützlich, um Gerätebewegungen wie Neigen, Schütteln, Drehen oder Schwenken zu überwachen. Die Bewegung ist in der Regel eine direkte Folge der Nutzereingaben (z. B. wenn ein Nutzer in einem Spiel ein Auto steuert oder einen Ball steuert). Sie kann aber auch die physische Umgebung widerspiegeln, in der sich das Gerät befindet (z. B. wenn es sich mit Ihnen bewegt, während Sie mit dem Auto fahren). Im ersten Fall wird die Bewegung relativ zum Referenzpunkt des Geräts oder der Anwendung überwacht. Im zweiten Fall wird die Bewegung relativ zum Weltraum überwacht. Bewegungssensoren werden in der Regel nicht zur Überwachung der Geräteposition verwendet, sondern können zusammen mit anderen Sensoren wie dem Geomagnetfeldsensor verwendet werden, um die Position eines Geräts relativ zum Weltkoordinatensystem zu bestimmen. Weitere Informationen finden Sie unter Positionssensoren.
Alle Bewegungssensoren geben für jede SensorEvent
mehrdimensionale Arrays von Sensorwerten zurück. Beispielsweise gibt der Beschleunigungsmesser bei einem einzelnen Sensorereignis Daten zur Beschleunigungskraft für die drei Koordinatenachsen zurück und das Gyroskop gibt Daten zur Drehgeschwindigkeit für die drei Koordinatenachsen zurück. Diese Datenwerte werden zusammen mit anderen SensorEvent
-Parametern in einem float
-Array (values
) zurückgegeben. In Tabelle 1 sind die auf der Android-Plattform verfügbaren Bewegungssensoren zusammengefasst.
Sensor | Sensorereignisdaten | Beschreibung | Maßeinheiten |
---|---|---|---|
TYPE_ACCELEROMETER |
SensorEvent.values[0] |
Beschleunigungskraft entlang der X-Achse (einschließlich Schwerkraft). | m/s2 |
SensorEvent.values[1] |
Beschleunigungskraft entlang der Y-Achse (einschließlich Schwerkraft). | ||
SensorEvent.values[2] |
Beschleunigungskraft entlang der Z‑Achse (einschließlich Schwerkraft). | ||
TYPE_ACCELEROMETER_UNCALIBRATED |
SensorEvent.values[0] |
Gemessene Beschleunigung entlang der X-Achse ohne Voreinstellbare Neigungsausgleiche. | m/s2 |
SensorEvent.values[1] |
Gemessene Beschleunigung entlang der Y-Achse ohne Vorabglättung. | ||
SensorEvent.values[2] |
Gemessene Beschleunigung entlang der Z‑Achse ohne Vorzeichenkorrektur. | ||
SensorEvent.values[3] |
Gemessene Beschleunigung entlang der X-Achse mit geschätzter Voreingenommenheitskompensation. | ||
SensorEvent.values[4] |
Gemessene Beschleunigung entlang der Y-Achse mit geschätzter Voreingenommenheitskompensation. | ||
SensorEvent.values[5] |
Gemessene Beschleunigung entlang der Z‑Achse mit geschätzter Voreingenommenheitskompensation. | ||
TYPE_GRAVITY |
SensorEvent.values[0] |
Die Schwerkraft entlang der X-Achse. | m/s2 |
SensorEvent.values[1] |
Die Schwerkraft entlang der Y-Achse. | ||
SensorEvent.values[2] |
Schwerkraft entlang der Z‑Achse. | ||
TYPE_GYROSCOPE |
SensorEvent.values[0] |
Drehgeschwindigkeit um die x-Achse. | rad/s |
SensorEvent.values[1] |
Drehgeschwindigkeit um die y-Achse. | ||
SensorEvent.values[2] |
Drehgeschwindigkeit um die Z‑Achse. | ||
TYPE_GYROSCOPE_UNCALIBRATED |
SensorEvent.values[0] |
Drehgeschwindigkeit (ohne Driftkompensation) um die x-Achse. | rad/s |
SensorEvent.values[1] |
Drehgeschwindigkeit (ohne Driftkompensation) um die y-Achse. | ||
SensorEvent.values[2] |
Drehgeschwindigkeit (ohne Driftkompensation) um die Z‑Achse. | ||
SensorEvent.values[3] |
Geschätzte Abweichung entlang der X-Achse. | ||
SensorEvent.values[4] |
Geschätzte Abweichung um die y-Achse. | ||
SensorEvent.values[5] |
Geschätzte Abweichung entlang der Z‑Achse. | ||
TYPE_LINEAR_ACCELERATION |
SensorEvent.values[0] |
Beschleunigungskraft entlang der X-Achse (ohne Schwerkraft). | m/s2 |
SensorEvent.values[1] |
Beschleunigungskraft entlang der y-Achse (ohne Schwerkraft). | ||
SensorEvent.values[2] |
Beschleunigungskraft entlang der Z‑Achse (ohne Schwerkraft). | ||
TYPE_ROTATION_VECTOR |
SensorEvent.values[0] |
Komponente des Drehvektors entlang der X-Achse (x * sin(θ/2)). | Ohne Einheit |
SensorEvent.values[1] |
Komponente des Drehvektors entlang der Y-Achse (y * sin(θ/2)). | ||
SensorEvent.values[2] |
Komponente des Drehvektors entlang der Z‑Achse (z * sin(θ/2)). | ||
SensorEvent.values[3] |
Skalare Komponente des Drehvektors ((cos(θ/2)).1 | ||
TYPE_SIGNIFICANT_MOTION |
– | – | – |
TYPE_STEP_COUNTER |
SensorEvent.values[0] |
Anzahl der Schritte, die der Nutzer seit dem letzten Neustart gemacht hat, während der Sensor aktiviert war. | Schritte |
TYPE_STEP_DETECTOR |
– | – | – |
1 Die skalare Komponente ist ein optionaler Wert.
Der Drehvektorsensor und der Schwerkraftsensor sind die am häufigsten verwendeten Sensoren für die Bewegungserkennung und -überwachung. Der Drehvektorsensor ist besonders vielseitig und kann für eine Vielzahl von bewegungsbezogenen Aufgaben verwendet werden, z. B. für die Erkennung von Gesten, die Überwachung von Winkeländerungen und die Überwachung von Änderungen der relativen Ausrichtung. Der Drehvektorsensor eignet sich beispielsweise ideal, wenn Sie ein Spiel, eine Augmented-Reality-Anwendung, einen zweidimensionalen oder dreidimensionalen Kompass oder eine Kamerastabilisierungs-App entwickeln. In den meisten Fällen ist die Verwendung dieser Sensoren die bessere Wahl als die Verwendung des Beschleunigungsmessers und des Geomagnetfeldsensors oder des Orientierungssensors.
Sensoren des Android Open Source-Projekts
Das Android Open Source Project (AOSP) bietet drei softwarebasierte Bewegungssensoren: einen Schwerkraftsensor, einen linearen Beschleunigungssensor und einen Drehvektorsensor. Diese Sensoren wurden in Android 4.0 aktualisiert und verwenden jetzt zusätzlich zu anderen Sensoren das Gyroskop eines Geräts, um Stabilität und Leistung zu verbessern. Wenn Sie diese Sensoren ausprobieren möchten, können Sie sie mit der getVendor()
-Methode und der getVersion()
-Methode identifizieren. Der Anbieter ist Google LLC und die Versionsnummer ist 3. Die Identifizierung dieser Sensoren anhand des Anbieters und der Versionsnummer ist erforderlich, da das Android-System diese drei Sensoren als sekundäre Sensoren betrachtet. Wenn ein Gerätehersteller beispielsweise einen eigenen Gravitationssensor bereitstellt, wird der AOSP-Gravitationssensor als sekundärer Gravitationssensor angezeigt. Alle drei Sensoren benötigen ein Gyroskop: Wenn ein Gerät kein Gyroskop hat, werden diese Sensoren nicht angezeigt und können nicht verwendet werden.
Gravitationssensor verwenden
Der Schwerkraftsensor liefert einen dreidimensionalen Vektor, der die Richtung und Stärke der Schwerkraft angibt. Normalerweise wird dieser Sensor verwendet, um die relative Ausrichtung des Geräts im Raum zu bestimmen. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardgravitationssensors abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
Die Einheiten sind dieselben wie beim Beschleunigungssensor (m/s2) und das Koordinatensystem ist das gleiche wie beim Beschleunigungssensor.
Hinweis:Wenn sich ein Gerät nicht bewegt, sollte die Ausgabe des Schwerkraftsensors mit der des Beschleunigungsmessers übereinstimmen.
Linearen Beschleunigungsmesser verwenden
Der lineare Beschleunigungssensor liefert einen dreidimensionalen Vektor, der die Beschleunigung entlang jeder Geräteachse abzüglich der Schwerkraft darstellt. Sie können diesen Wert für die Gestenentdeckung verwenden. Der Wert kann auch als Eingabe für ein inertiales Navigationssystem dienen, das die Triangulation verwendet. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardsensors für die lineare Beschleunigung abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
Dieser Sensor liefert Ihnen konzeptionell Beschleunigungsdaten gemäß der folgenden Beziehung:
linear acceleration = acceleration - acceleration due to gravity
Sie verwenden diesen Sensor in der Regel, wenn Sie Beschleunigungsdaten ohne den Einfluss der Schwerkraft erhalten möchten. So können Sie beispielsweise die Geschwindigkeit Ihres Autos messen. Der lineare Beschleunigungssensor hat immer einen Versatz, den Sie entfernen müssen. Am einfachsten ist es, einen Kalibrierungsschritt in Ihre Anwendung einzubinden. Während der Kalibrierung können Sie den Nutzer bitten, das Gerät auf einen Tisch zu legen und dann die Abweichungen für alle drei Achsen abzulesen. Sie können diesen Versatz dann von den direkten Messwerten des Beschleunigungssensors abziehen, um die tatsächliche lineare Beschleunigung zu erhalten.
Das Koordinatensystem des Sensors ist mit dem des Beschleunigungssensors identisch, ebenso wie die Maßeinheiten (m/s2).
Drehvektorsensor verwenden
Der Drehvektor stellt die Ausrichtung des Geräts als Kombination aus einem Winkel und einer Achse dar, um die sich das Gerät um einen Winkel θ gedreht hat. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardsensors für den Drehvektor abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
Die drei Elemente des Drehvektors werden so ausgedrückt:
Dabei ist die Größe des Drehvektors gleich sin(θ/2) und die Richtung des Drehvektors gleich der Richtung der Drehachse.
Die drei Elemente des Drehvektors entsprechen den letzten drei Komponenten einer Einheitsquaternion (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). Die Elemente des Drehvektors sind ohne Maßeinheit. Die X-, Y- und Z-Achsen werden auf die gleiche Weise wie der Beschleunigungssensor definiert. Das Referenzkoordinatensystem wird als direkte orthonormale Basis definiert (siehe Abbildung 1). Dieses Koordinatensystem hat folgende Eigenschaften:
- X wird als Vektorprodukt Y × Z definiert. Sie ist am aktuellen Standort des Geräts tangential zum Boden und zeigt ungefähr nach Osten.
- Y ist am aktuellen Standort des Geräts tangential zum Boden und zeigt zum geomagnetischen Nordpol.
- Z zeigt zum Himmel und ist senkrecht zur Bodenebene.
Eine Beispielanwendung, die die Verwendung des Drehvektorsensors zeigt, finden Sie unter RotationVectorDemo.java.
Sensor für relevante Bewegungen verwenden
Der Sensor für relevante Bewegungen löst jedes Mal ein Ereignis aus, wenn eine relevante Bewegung erkannt wird, und deaktiviert sich dann selbst. Eine erhebliche Bewegung ist eine Bewegung, die zu einer Änderung des Standorts des Nutzers führen kann, z. B. wenn er zu Fuß unterwegs ist, Fahrrad fährt oder in einem fahrenden Auto sitzt. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardsensors für wichtige Bewegungen abrufen und einen Ereignisempfänger registrieren:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION) val triggerEventListener = object : TriggerEventListener() { override fun onTrigger(event: TriggerEvent?) { // Do work } } mSensor?.also { sensor -> sensorManager.requestTriggerSensor(triggerEventListener, sensor) }
Java
private SensorManager sensorManager; private Sensor sensor; private TriggerEventListener triggerEventListener; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); triggerEventListener = new TriggerEventListener() { @Override public void onTrigger(TriggerEvent event) { // Do work } }; sensorManager.requestTriggerSensor(triggerEventListener, mSensor);
Weitere Informationen finden Sie unter TriggerEventListener
.
Schrittzähler verwenden
Der Schrittzählersensor gibt die Anzahl der Schritte an, die der Nutzer seit dem letzten Neustart zurückgelegt hat, während der Sensor aktiviert war. Der Schrittzähler hat eine längere Latenz (bis zu 10 Sekunden), ist aber genauer als der Schritterkennungssensor.
Hinweis : Sie müssen die Berechtigung ACTIVITY_RECOGNITION
deklarieren, damit Ihre App diesen Sensor auf Geräten mit Android 10 (API-Level 29) oder höher verwenden kann.
Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardsensors für den Schrittzähler abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
Um den Akku von Geräten, auf denen Ihre App ausgeführt wird, zu schonen, sollten Sie die Klasse JobScheduler
verwenden, um den aktuellen Wert des Schrittzählersensors in einem bestimmten Intervall abzurufen. Für verschiedene Arten von Apps sind unterschiedliche Intervalle für die Sensorabfragen erforderlich. Sie sollten dieses Intervall jedoch so lang wie möglich halten, es sei denn, Ihre App benötigt Echtzeitdaten vom Sensor.
Schrittzähler verwenden
Der Schrittzähler löst jedes Mal ein Ereignis aus, wenn der Nutzer einen Schritt macht. Die Latenz sollte unter 2 Sekunden liegen.
Hinweis : Sie müssen die Berechtigung ACTIVITY_RECOGNITION
deklarieren, damit Ihre App diesen Sensor auf Geräten mit Android 10 (API-Level 29) oder höher verwenden kann.
Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardsensors für den Schrittzähler abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
Mit Rohdaten arbeiten
Die folgenden Sensoren stellen Ihrer App Rohdaten zu den linearen und Rotationskräften zur Verfügung, die auf das Gerät ausgeübt werden. Damit die Werte dieser Sensoren effektiv genutzt werden können, müssen Umgebungsfaktoren wie die Schwerkraft herausgefiltert werden. Möglicherweise müssen Sie auch einen Glättealgorithmus auf den Werttrend anwenden, um Rauschen zu reduzieren.
Beschleunigungsmesser verwenden
Ein Beschleunigungssensor misst die Beschleunigung, die auf das Gerät ausgeübt wird, einschließlich der Schwerkraft. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardbeschleunigungssensors abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Hinweis : Wenn Ihre App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, ist dieser Sensor taktgesteuert.
Ein Beschleunigungssensor bestimmt die Beschleunigung, die auf ein Gerät (Ad) ausgeübt wird, indem er die Kräfte misst, die auf den Sensor selbst (Fs) ausgeübt werden, und dabei die folgende Beziehung verwendet:
Die Schwerkraft beeinflusst die gemessene Beschleunigung jedoch immer gemäß der folgenden Beziehung:
Wenn sich das Gerät also auf einem Tisch befindet und nicht beschleunigt wird, misst der Beschleunigungsmesser einen Wert von g = 9,81 m/s2. Wenn sich das Gerät im freien Fall befindet und daher mit 9, 81 m/s2 beschleunigt, misst der Beschleunigungsmesser eine Größe von g = 0 m/s2. Um die tatsächliche Beschleunigung des Geräts zu messen, muss der Beitrag der Schwerkraft aus den Beschleunigungssensordaten entfernt werden. Dies kann durch Anwenden eines Hochpassfilters erreicht werden. Umgekehrt kann ein Tiefpassfilter verwendet werden, um die Schwerkraft zu isolieren. Das folgende Beispiel zeigt, wie Sie das tun können:
Kotlin
override fun onSensorChanged(event: SensorEvent) { // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. val alpha: Float = 0.8f // Isolate the force of gravity with the low-pass filter. gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0] gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1] gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2] // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0] linear_acceleration[1] = event.values[1] - gravity[1] linear_acceleration[2] = event.values[2] - gravity[2] }
Java
public void onSensorChanged(SensorEvent event){ // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. final float alpha = 0.8; // Isolate the force of gravity with the low-pass filter. gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0]; linear_acceleration[1] = event.values[1] - gravity[1]; linear_acceleration[2] = event.values[2] - gravity[2]; }
Hinweis:Es gibt viele verschiedene Methoden, um Sensordaten zu filtern. Im Codebeispiel oben wird eine einfache Filterkonstante (Alpha) verwendet, um einen Tiefpassfilter zu erstellen. Diese Filterkonstante wird aus einer Zeitkonstanten (t) abgeleitet, die eine grobe Darstellung der Latenz ist, die der Filter den Sensorereignissen hinzufügt, und der Ereignisübertragungsrate (dt) des Sensors. Im Codebeispiel wird zu Demonstrationszwecken ein Alphawert von 0,8 verwendet. Wenn Sie diese Filtermethode verwenden, müssen Sie möglicherweise einen anderen Alphawert auswählen.
Beschleunigungsmesser verwenden das standardmäßige Koordinatensystem des Sensors. In der Praxis bedeutet das, dass die folgenden Bedingungen gelten, wenn ein Gerät in seiner natürlichen Ausrichtung flach auf einem Tisch liegt:
- Wenn Sie das Gerät auf der linken Seite drücken, sodass es nach rechts bewegt wird, ist der Wert für die X‑Beschleunigung positiv.
- Wenn Sie das Gerät von unten drücken, sodass es sich von Ihnen weg bewegt, ist der Wert für die Y‑Beschleunigung positiv.
- Wenn Sie das Gerät mit einer Beschleunigung von A m/s2 nach oben drücken, entspricht der Wert für die Z‑Beschleunigung A + 9,81. Das entspricht der Beschleunigung des Geräts (+A m/s2) abzüglich der Schwerkraft (–9,81 m/s2).
- Das ruhende Gerät hat einen Beschleunigungswert von +9,81, was der Beschleunigung des Geräts entspricht (0 m/s2 minus die Schwerkraft, also -9,81 m/s2).
Im Allgemeinen eignet sich der Beschleunigungsmesser gut, wenn Sie die Gerätebewegung überwachen möchten. Fast jedes Android-Smartphone und -Tablet hat einen Beschleunigungsmesser, der etwa zehnmal weniger Strom verbraucht als die anderen Bewegungssensoren. Ein Nachteil ist, dass Sie möglicherweise Tiefpass- und Hochpassfilter implementieren müssen, um die Gravitationskräfte zu eliminieren und Geräusche zu reduzieren.
Gyroskop verwenden
Das Gyroskop misst die Drehgeschwindigkeit in rad/s um die X-, Y- und Z-Achse eines Geräts. Im folgenden Code wird gezeigt, wie Sie eine Instanz des Standardgyroskops abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
Hinweis : Wenn Ihre App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, ist dieser Sensor taktgesteuert.
Das Koordinatensystem des Sensors ist mit dem des Beschleunigungssensors identisch. Eine positive Drehung ist eine Drehung gegen den Uhrzeigersinn. Das bedeutet, dass ein Beobachter, der von einem positiven Ort auf der X-, Y- oder Z-Achse auf ein Gerät am Ursprung blickt, eine positive Drehung meldet, wenn sich das Gerät scheinbar gegen den Uhrzeigersinn dreht. Dies ist die standardmäßige mathematische Definition einer positiven Drehung und entspricht nicht der Definition für die Rollung, die vom Ausrichtungssensor verwendet wird.
Normalerweise wird die Ausgabe des Gyroskops über die Zeit integriert, um eine Drehung zu berechnen, die die Änderung der Winkel über den Zeitschritt beschreibt. Beispiel:
Kotlin
// Create a constant to convert nanoseconds to seconds. private val NS2S = 1.0f / 1000000000.0f private val deltaRotationVector = FloatArray(4) { 0f } private var timestamp: Float = 0f override fun onSensorChanged(event: SensorEvent?) { // This timestep's delta rotation to be multiplied by the current rotation // after computing it from the gyro sample data. if (timestamp != 0f && event != null) { val dT = (event.timestamp - timestamp) * NS2S // Axis of the rotation sample, not normalized yet. var axisX: Float = event.values[0] var axisY: Float = event.values[1] var axisZ: Float = event.values[2] // Calculate the angular speed of the sample val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ) // Normalize the rotation vector if it's big enough to get the axis // (that is, EPSILON should represent your maximum allowable margin of error) if (omegaMagnitude > EPSILON) { axisX /= omegaMagnitude axisY /= omegaMagnitude axisZ /= omegaMagnitude } // Integrate around this axis with the angular speed by the timestep // in order to get a delta rotation from this sample over the timestep // We will convert this axis-angle representation of the delta rotation // into a quaternion before turning it into the rotation matrix. val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f val sinThetaOverTwo: Float = sin(thetaOverTwo) val cosThetaOverTwo: Float = cos(thetaOverTwo) deltaRotationVector[0] = sinThetaOverTwo * axisX deltaRotationVector[1] = sinThetaOverTwo * axisY deltaRotationVector[2] = sinThetaOverTwo * axisZ deltaRotationVector[3] = cosThetaOverTwo } timestamp = event?.timestamp?.toFloat() ?: 0f val deltaRotationMatrix = FloatArray(9) { 0f } SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector); // User code should concatenate the delta rotation we computed with the current rotation // in order to get the updated rotation. // rotationCurrent = rotationCurrent * deltaRotationMatrix; }
Java
// Create a constant to convert nanoseconds to seconds. private static final float NS2S = 1.0f / 1000000000.0f; private final float[] deltaRotationVector = new float[4](); private float timestamp; public void onSensorChanged(SensorEvent event) { // This timestep's delta rotation to be multiplied by the current rotation // after computing it from the gyro sample data. if (timestamp != 0) { final float dT = (event.timestamp - timestamp) * NS2S; // Axis of the rotation sample, not normalized yet. float axisX = event.values[0]; float axisY = event.values[1]; float axisZ = event.values[2]; // Calculate the angular speed of the sample float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ); // Normalize the rotation vector if it's big enough to get the axis // (that is, EPSILON should represent your maximum allowable margin of error) if (omegaMagnitude > EPSILON) { axisX /= omegaMagnitude; axisY /= omegaMagnitude; axisZ /= omegaMagnitude; } // Integrate around this axis with the angular speed by the timestep // in order to get a delta rotation from this sample over the timestep // We will convert this axis-angle representation of the delta rotation // into a quaternion before turning it into the rotation matrix. float thetaOverTwo = omegaMagnitude * dT / 2.0f; float sinThetaOverTwo = sin(thetaOverTwo); float cosThetaOverTwo = cos(thetaOverTwo); deltaRotationVector[0] = sinThetaOverTwo * axisX; deltaRotationVector[1] = sinThetaOverTwo * axisY; deltaRotationVector[2] = sinThetaOverTwo * axisZ; deltaRotationVector[3] = cosThetaOverTwo; } timestamp = event.timestamp; float[] deltaRotationMatrix = new float[9]; SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector); // User code should concatenate the delta rotation we computed with the current rotation // in order to get the updated rotation. // rotationCurrent = rotationCurrent * deltaRotationMatrix; }
Standardgyroskope liefern Rohdrehungsdaten ohne Filterung oder Korrektur von Rauschen und Drift (Voreingenommenheit). In der Praxis führen Gyroskopflätscher und -abweichungen zu Fehlern, die ausgeglichen werden müssen. Normalerweise werden Abweichung (Bias) und Rauschen durch das Überwachen anderer Sensoren wie des Gravitationssensors oder des Beschleunigungsmessers bestimmt.
Nicht kalibriertes Gyroskop verwenden
Das nicht kalibrierte Gyroskop ähnelt dem Gyroskop, mit der Ausnahme, dass die Drehgeschwindigkeit nicht durch eine Gyroskopabweichung kompensiert wird. Die werksseitige Kalibrierung und die Temperaturkompensation werden weiterhin auf die Drehgeschwindigkeit angewendet. Das nicht kalibrierte Gyroskop ist für die Nachbearbeitung und Zusammenführung von Orientierungsdaten nützlich. Im Allgemeinen ist gyroscope_event.values[0]
nahe bei uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]
.
Das bedeutet:
calibrated_x ~= uncalibrated_x - bias_estimate_x
Hinweis:Nicht kalibrierte Sensoren liefern Rohdaten und können eine gewisse Abweichung aufweisen. Ihre Messungen enthalten jedoch weniger Sprünge durch Korrekturen, die durch die Kalibrierung angewendet werden. Für einige Anwendungen sind diese nicht kalibrierten Ergebnisse möglicherweise geeigneter, da sie flüssiger und zuverlässiger sind. Wenn eine Anwendung beispielsweise versucht, eine eigene Sensorfusion durchzuführen, können Kalibrierungen die Ergebnisse verfälschen.
Zusätzlich zu den Drehraten liefert das nicht kalibrierte Gyroskop auch die geschätzte Drift um jede Achse. Im folgenden Code wird gezeigt, wie Sie eine Instanz des standardmäßigen nicht kalibrierten Gyroskops abrufen:
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
Weitere Codebeispiele
Im Beispiel BatchStepSensor wird die Verwendung der auf dieser Seite beschriebenen APIs veranschaulicht.