Bewegungssensoren

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, Rotationsvektor, wichtige Bewegung, Schrittzähler und Schritterkennung sind entweder hardware- oder softwarebasiert.
  • Beschleunigungsmesser und Gyroskopsensoren sind immer hardwarebasiert.

Die meisten Android-Geräte verfügen über einen Beschleunigungsmesser, viele jetzt auch mit einem 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 Daten entweder vom Beschleunigungsmesser und dem Magnetometer oder vom Gyroskop ableiten.

Bewegungssensoren dienen zur Überwachung der Gerätebewegung, z. B. Neigen, Schütteln, Drehen oder Schwenken. Die Bewegung ist normalerweise eine Reflexion direkter Nutzereingaben, z. B. wenn ein Nutzer ein Auto in einem Spiel steuert oder einen Ball in einem Spiel steuert. Sie kann aber auch die physische Umgebung widerspiegeln, in der sich das Gerät befindet (z. B. die Bewegung beim Fahren des Autos). Im ersten Fall überwachen Sie die Bewegung relativ zum Referenzrahmen des Geräts oder zum Referenzrahmen Ihrer Anwendung. Im zweiten Fall beobachten Sie die Bewegung relativ zum Bezugsrahmen der Welt. Bewegungssensoren an sich werden in der Regel nicht zur Überwachung der Geräteposition verwendet. Sie können jedoch zusammen mit anderen Sensoren (z. B. dem geomagnetischen Feldsensor) verwendet werden, um die Position eines Geräts relativ zum Bezugsrahmen der Welt zu ermitteln. Weitere Informationen finden Sie unter Positionssensoren.

Alle Bewegungssensoren geben mehrdimensionale Arrays von Sensorwerten für jede SensorEvent zurück. Beispielsweise gibt der Beschleunigungsmesser während eines einzelnen Sensorereignisses Daten zur Beschleunigungskraft für die drei Koordinatenachsen zurück, während das Gyroskop die Rotationsrate für die drei Koordinatenachsen zurückgibt. 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.

Tabelle 1 Bewegungssensoren, die auf der Android-Plattform unterstützt werden.

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 Verzerrungskompensation. m/s2
SensorEvent.values[1] Gemessene Beschleunigung entlang der Y-Achse ohne Verzerrungskompensation.
SensorEvent.values[2] Gemessene Beschleunigung entlang der Z-Achse ohne Verzerrungskompensation.
SensorEvent.values[3] Gemessene Beschleunigung entlang der X-Achse mit geschätzter Verzerrungskompensation.
SensorEvent.values[4] Gemessene Beschleunigung entlang der Y-Achse mit geschätzter Verzerrungskompensation.
SensorEvent.values[5] Gemessene Beschleunigung entlang der Z-Achse mit geschätzter Verzerrungskompensation.
TYPE_GRAVITY SensorEvent.values[0] Schwerkraft entlang der x-Achse. m/s2
SensorEvent.values[1] Schwerkraft entlang der y-Achse.
SensorEvent.values[2] Schwerkraft entlang der z-Achse.
TYPE_GYROSCOPE SensorEvent.values[0] Rotationsrate um die x-Achse. Rad/s
SensorEvent.values[1] Rotationsrate um die y-Achse.
SensorEvent.values[2] Rotationsrate um die z-Achse.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Rotationsrate (ohne Driftkompensation) um die x-Achse. Rad/s
SensorEvent.values[1] Rotationsrate (ohne Driftkompensation) um die y-Achse.
SensorEvent.values[2] Rotationsrate (ohne Driftkompensation) um die z-Achse herum.
SensorEvent.values[3] Geschätzte Drift um die x-Achse.
SensorEvent.values[4] Geschätzte Drift um die y-Achse.
SensorEvent.values[5] Geschätzte Drift um die 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] Rotationsvektorkomponente entlang der x-Achse (x * sin(Θ/2)). Ohne Einheit
SensorEvent.values[1] Rotationsvektorkomponente entlang der y-Achse (y * sin(Θ/2))
SensorEvent.values[2] Rotationsvektorkomponente entlang der z-Achse (z * sin(Θ/2))
SensorEvent.values[3] Skalarkomponente des Rotationsvektors ((cos(Θ/2)))1
TYPE_SIGNIFICANT_MOTION
TYPE_STEP_COUNTER SensorEvent.values[0] Anzahl der Schritte, die der Nutzer seit dem letzten Neustart bei Aktivierung des Sensors ausgeführt hat. Schritte
TYPE_STEP_DETECTOR

1 Die Komponente „Skalar“ ist ein optionaler Wert.

Der Rotationsvektorsensor und der Schwerkraftsensor sind die am häufigsten verwendeten Sensoren für die Bewegungserkennung und -überwachung. Der Rotationsvektorsensor ist besonders vielseitig und kann für eine Vielzahl von bewegungsbezogenen Aufgaben verwendet werden, z. B. zum Erkennen von Gesten, zum Überwachen von Winkeländerungen und zum Überwachen von relativen Ausrichtungsänderungen. Der Rotationsvektorsensor ist beispielsweise ideal, wenn Sie ein Spiel, eine Augmented-Reality-Anwendung, einen zwei- oder dreidimensionalen Kompass oder eine Kamerastabilisierungs-App entwickeln. In den meisten Fällen ist die Verwendung dieser Sensoren eine bessere Wahl als die Verwendung des Beschleunigungsmessers und geomagnetischen Feldsensors oder des Ausrichtungssensors.

Sensoren im Android Open-Source-Projekt

Das Android Open Source Project (AOSP) bietet drei softwarebasierte Bewegungssensoren: einen Schwerkraftsensor, einen linearen Beschleunigungssensor und einen Rotationsvektorsensor. Diese Sensoren wurden in Android 4.0 aktualisiert und nutzen jetzt zusätzlich zu anderen Sensoren ein Gyroskop eines Geräts, um Stabilität und Leistung zu verbessern. Wenn Sie diese Sensoren ausprobieren möchten, können Sie sie mit den Methoden getVendor() und getVersion() identifizieren (der Anbieter ist Google LLC; die Versionsnummer ist 3). Diese Sensoren müssen anhand des Anbieters und der Versionsnummer ermittelt werden, da das Android-System diese drei Sensoren als sekundäre Sensoren betrachtet. Wenn ein Gerätehersteller beispielsweise einen eigenen Schwerkraftsensor bereitstellt, wird der AOSP-Schwerkraftsensor als sekundärer Schwerkraftsensor angezeigt. Alle drei Sensoren basieren auf einem Gyroskop: Wenn ein Gerät kein Gyroskop hat, werden diese Sensoren nicht angezeigt und können nicht verwendet werden.

Schwerkraftsensor verwenden

Der Schwerkraftsensor stellt einen dreidimensionalen Vektor bereit, der Richtung und Größe der Schwerkraft angibt. In der Regel wird dieser Sensor verwendet, um die relative Ausrichtung des Geräts im Raum zu bestimmen. Der folgende Code zeigt, wie Sie eine Instanz des Standard-Schwerkraftsensors erhalten:

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 mit denen des Beschleunigungssensors (m/s2) identisch und das Koordinatensystem stimmt mit dem des Beschleunigungssensors überein.

Hinweis:Wenn ein Gerät in Ruhe ist, sollte die Ausgabe des Schwerkraftsensors der Ausgabe des Beschleunigungsmessers entsprechen.

Linearen Beschleunigungsmesser verwenden

Der lineare Beschleunigungssensor stellt einen dreidimensionalen Vektor bereit, der die Beschleunigung entlang jeder Geräteachse ohne Schwerkraft darstellt. Sie können diesen Wert für die Gestenerkennung verwenden. Der Wert kann auch als Eingabe für ein Inertial-Navigationssystem dienen, das Dead-Ruckoning verwendet. Der folgende Code zeigt, wie Sie eine Instanz des standardmäßigen linearen Beschleunigungssensors 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);

Konzeptionell liefert dieser Sensor Beschleunigungsdaten gemäß der folgenden Beziehung:

linear acceleration = acceleration - acceleration due to gravity

Sie verwenden diesen Sensor in der Regel, wenn Sie Beschleunigungsdaten ohne Einfluss der Schwerkraft erhalten möchten. Mit diesem Sensor können Sie zum Beispiel sehen, wie schnell Ihr Auto fährt. 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 stellen und dann die Versätze für alle drei Achsen zu lesen. Sie können diesen Offset dann von den direkten Messwerten des Beschleunigungssensors subtrahieren, um die tatsächliche lineare Beschleunigung zu erhalten.

Das Sensor-Koordinatensystem ist dasselbe wie das vom Beschleunigungssensor verwendete Sensorsystem, ebenso wie die Maßeinheiten (m/s2).

Rotationsvektorsensor verwenden

Der Rotationsvektor stellt die Ausrichtung des Geräts als Kombination aus einem Winkel und einer Achse dar, in der sich das Gerät um eine Achse (x, y oder z) um einen Winkel Θ gedreht hat. Der folgende Code zeigt, wie Sie eine Instanz des Standard-Rotationsvektorsensors 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 Rotationsvektors werden wie folgt ausgedrückt:

x*sin(relative/2), y*sin(Θ/2), z*sin(Θ/2)

Dabei ist die Größe des Rotationsvektors gleich sin(Θ/2) und die Richtung des Rotationsvektors der Richtung der Drehachse.

Abbildung 1: Vom Rotationsvektorsensor verwendete Koordinatensystem.

Die drei Elemente des Rotationsvektors sind gleich den letzten drei Komponenten einer Einheitsquaternion (cos(Θ/2), x*sin(Θ/2), y*sin(Θ/2), z*sin(Θ/2)). Elemente des Rotationsvektors sind ohne Einheit. Die x-, y- und z-Achse werden auf die gleiche Weise wie der Beschleunigungssensor definiert. Das Referenzkoordinatensystem wird auf direkter orthonormaler Basis definiert (siehe Abbildung 1). Dieses Koordinatensystem hat folgende Eigenschaften:

  • X ist definiert als das Vektorprodukt Y x Z. Sie ist am aktuellen Standort des Geräts tangential mit dem Boden und zeigt ungefähr nach Osten.
  • Y ist am aktuellen Standort des Geräts tangential mit der Erde und zeigt auf den geomagnetischen Nordpol.
  • Z zeigt zum Himmel und ist senkrecht zur Bodenebene.

Eine Beispielanwendung, die die Verwendung des Rotationsvektorsensors zeigt, finden Sie unter RotationVectorDemo.java.

Den signifikanten Bewegungssensor verwenden

Der signifikante Bewegungssensor löst jedes Mal ein Ereignis aus, wenn eine signifikante Bewegung erkannt wird, und deaktiviert sich dann selbst. Eine signifikante Bewegung ist eine Bewegung, die zu einer Änderung des Standorts des Nutzers führen kann, z. B. beim Gehen, Radfahren oder Sitzen in einem fahrenden Auto. Der folgende Code zeigt, wie Sie eine Instanz des Standard-Bewegungssensors abrufen und einen Event-Listener 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 findest du unter TriggerEventListener.

Schrittzählersensor verwenden

Der Schrittzählersensor gibt die Anzahl der Schritte an, die der Nutzer seit dem letzten Neustart bei aktiviertem Sensor ausgeführt hat. Der Schrittzähler hat eine höhere Latenz (bis zu 10 Sekunden), aber eine höhere Genauigkeit als der Schrittsensorsensor.

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.

Der folgende Code zeigt, wie Sie eine Instanz des Standard-Schrittzählersensors 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 der Geräte zu schonen, auf denen deine App ausgeführt wird, solltest du mit der Klasse JobScheduler den aktuellen Wert vom Schrittzählersensor in einem bestimmten Intervall abrufen. Obwohl unterschiedliche Arten von Apps unterschiedliche Sensorleseintervalle erfordern, sollten Sie dieses Intervall so lang wie möglich halten, es sei denn, Ihre App benötigt Echtzeitdaten vom Sensor.

Schritterkennungssensor verwenden

Der Schrittsensor löst jedes Mal ein Ereignis aus, wenn der Nutzer einen Schritt macht. Die Latenz wird voraussichtlich 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.

Der folgende Code zeigt, wie Sie eine Instanz des Standardsensors für die Schritterkennung 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 liefern Ihrer App Rohdaten zu den linearen und Rotationskräften, die auf das Gerät angewendet werden. Um die Werte dieser Sensoren effektiv nutzen zu können, müssen Sie Faktoren wie die Schwerkraft aus der Umgebung herausfiltern. Möglicherweise müssen Sie auch einen Glättungsalgorithmus auf den Trend von Werten anwenden, um das Rauschen zu reduzieren.

Beschleunigungsmesser verwenden

Ein Beschleunigungssensor misst die auf das Gerät angewendete Beschleunigung, einschließlich der Schwerkraft. Der folgende Code zeigt, 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 ratenbegrenzt.

Konzeptionell bestimmt ein Beschleunigungssensor die Beschleunigung, die auf ein Gerät (Ad) angewendet wird, indem er die Kräfte misst, die auf den Sensor selbst (Fs) aufgewendet werden, und zwar unter Verwendung der folgenden Beziehung:

A_D=-(1/Masse)∑F_S

Die Schwerkraft beeinflusst jedoch immer die gemessene Beschleunigung gemäß dem folgenden Verhältnis:

A_D=-g-(1/Masse)∑F_S

Wenn das Gerät auf einem Tisch liegt und nicht beschleunigt, misst der Beschleunigungsmesser die Größe „g = 9,81 m/s2“. Ähnlich verhält es sich, wenn sich das Gerät im freien Fall befindet und daher mit 9, 81 m/s2 schnell auf den Boden zubeschleunigt.Dann misst der Beschleunigungsmesser die Größe „g = 0 m/s2“. Daher muss der Beitrag der Schwerkraft aus den Daten des Beschleunigungsmessers entfernt werden, um die tatsächliche Beschleunigung des Geräts zu messen. 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 dies 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:Sie können Sensordaten mit vielen verschiedenen Techniken filtern. Im obigen Codebeispiel wird eine einfache Filterkonstante (Alpha) verwendet, um einen Tiefpassfilter zu erstellen. Diese Filterkonstante wird von einer Zeitkonstante (t) abgeleitet, die eine grobe Darstellung der Latenz darstellt, die der Filter zu den Sensorereignissen hinzufügt, und der Ereignislieferrate (dt) des Sensors. Im Codebeispiel wird zu Demonstrationszwecken der Alphawert 0,8 verwendet. Wenn Sie diese Filtermethode verwenden, müssen Sie möglicherweise einen anderen Alphawert auswählen.

Beschleunigungsmesser verwenden das standardmäßige Sensorkoordinatensystem. In der Praxis bedeutet dies, dass die folgenden Bedingungen gelten, wenn ein Gerät in seiner natürlichen Ausrichtung flach auf einem Tisch aufliegt:

  • 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 nach unten drücken, damit es sich von Ihnen wegbewegt, ist der Beschleunigungswert y positiv.
  • Wenn Sie das Gerät mit einer Beschleunigung von A m/s2 zum Himmel bewegen, entspricht der z-Beschleunigungswert A + 9,81, was der Beschleunigung des Geräts (+A m/s2) abzüglich der Schwerkraft (-9,81 m/s2) entspricht.
  • Das unbewegliche Gerät hat einen Beschleunigungswert von +9,81, was der Beschleunigung des Geräts (0 m/s2 abzüglich der Schwerkraft -9,81 m/s2) entspricht.

Im Allgemeinen ist der Beschleunigungsmesser ein guter Sensor zur Überwachung der Gerätebewegung. Fast alle Android-Mobilgeräte und -Tablets sind mit einem Beschleunigungsmesser ausgestattet und benötigen etwa zehnmal weniger Energie als die anderen Bewegungssensoren. Ein Nachteil ist, dass Sie unter Umständen Tief- und Hochpassfilter implementieren müssen, um Gravitationskräfte zu eliminieren und das Rauschen zu reduzieren.

Gyroskop verwenden

Das Gyroskop misst die Rotationsrate in Rad/s um die x-, y- und z-Achse eines Geräts. Der folgende Code zeigt, wie Sie eine Instanz des Standard-Gyroskops 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 ratenbegrenzt.

Das Koordinatensystem des Sensors ist dasselbe wie das für den Beschleunigungssensor verwendete. Die Drehung ist positiv und gegen den Uhrzeigersinn. Das heißt, ein Beobachter, der von einem positiven Ort auf der x-, y- oder z-Achse auf ein Gerät schaut, das sich am Ursprung befindet, würde eine positive Drehung melden, wenn das Gerät gegen den Uhrzeigersinn drehen würde. Dies ist die mathematische Standarddefinition der positiven Rotation und entspricht nicht der Definition für Rollen, die vom Ausrichtungssensor verwendet wird.

Normalerweise wird die Ausgabe des Gyroskops über einen längeren Zeitraum integriert, um eine Rotation zu berechnen, die die Winkeländerung über den Zeitschritt beschreibt. Beispiele:

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 Rohdaten zu Rotationen ohne Filterung oder Korrektur von Rauschen und Drift (Verzerrungen). In der Praxis führen Gyroskoprauschen und -drift zu Fehlern, die kompensiert werden müssen. Normalerweise bestimmen Sie die Drift (Verzerrung) und das Rauschen, indem Sie andere Sensoren wie den Schwerkraftsensor oder Beschleunigungsmesser beobachten.

Nicht kalibriertes Gyroskop verwenden

Das nicht kalibrierte Gyroskop ähnelt dem Gyroskop, mit der Ausnahme, dass keine Gyroskopkompensation auf die Rotationsrate angewendet wird. Die Werkskalibrierung und Temperaturkompensation werden weiterhin auf die Rotationsrate angewendet. Das nicht kalibrierte Gyroskop ist nützlich für die Nachbearbeitung und Verschmelzung von Ausrichtungsdaten. Im Allgemeinen liegt gyroscope_event.values[0] nahe an uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Das heißt:

calibrated_x ~= uncalibrated_x - bias_estimate_x

Hinweis:Nicht kalibrierte Sensoren liefern mehr Rohdaten und können eine gewisse Verzerrung enthalten, aber ihre Messungen enthalten weniger Abweichungen aufgrund von Korrekturen, die durch die Kalibrierung vorgenommen wurden. Einige Anwendungen bevorzugen diese nicht kalibrierten Ergebnisse möglicherweise als reibungslosere und zuverlässigere Ergebnisse. Wenn eine Anwendung beispielsweise versucht, ihre eigene Sensorfusion durchzuführen, kann die Einführung von Kalibrierungen die Ergebnisse verzerren.

Zusätzlich zu den Rotationsraten liefert das nicht kalibrierte Gyroskop auch die geschätzten Driften um jede Achse. Der folgende Code zeigt, wie Sie eine Instanz des nicht kalibrierten Standard-Gyroskops erhalten:

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);

Zusätzliche Codebeispiele

Im Beispiel BatchStepSensor wird die Verwendung der auf dieser Seite behandelten APIs weiter veranschaulicht.

Weitere Informationen