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

Die meisten Android-Geräte haben einen Beschleunigungsmesser und viele auch ein Gyroskop. Die Verfügbarkeit der softwarebasierten Sensoren ist variabler, da sie oft auf einem oder mehreren Hardwaresensoren basieren, um ihre Daten abzuleiten. 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 Schwingen zu erfassen. Die Bewegung ist in der Regel eine Reaktion auf direkte Nutzereingaben (z. B. wenn ein Nutzer ein Auto in einem Spiel steuert oder einen Ball in einem Spiel kontrolliert), sie kann aber auch eine Reaktion auf die physische Umgebung sein, 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 Bezugssystem des Geräts oder der Anwendung überwacht, im zweiten Fall relativ zum Bezugssystem der Welt. Bewegungssensoren werden in der Regel nicht verwendet, um die Geräteposition zu überwachen. Sie können jedoch zusammen mit anderen Sensoren wie dem geomagnetischen Feldsensor verwendet werden, um die Position eines Geräts relativ zum Referenzrahmen der Welt zu bestimmen (weitere Informationen finden Sie unter Positionssensoren).

Alle Bewegungssensoren geben mehrdimensionale Arrays von Sensorwerten für jedes SensorEvent zurück. Bei einem einzelnen Sensorereignis gibt der Beschleunigungsmesser beispielsweise Daten zur Beschleunigungskraft für die drei Koordinatenachsen zurück und das Gyroskop Daten zur Drehrate für die drei Koordinatenachsen. Diese Datenwerte werden in einem float-Array (values) zusammen mit anderen SensorEvent-Parametern 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 Sensordaten 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 Bias-Korrektur. m/s2
SensorEvent.values[1] Gemessene Beschleunigung entlang der Y-Achse ohne Bias-Korrektur.
SensorEvent.values[2] Gemessene Beschleunigung entlang der Z-Achse ohne Bias-Korrektur.
SensorEvent.values[3] Gemessene Beschleunigung entlang der X-Achse mit geschätzter Bias-Korrektur.
SensorEvent.values[4] Gemessene Beschleunigung entlang der Y-Achse mit geschätzter Bias-Korrektur.
SensorEvent.values[5] Gemessene Beschleunigung entlang der Z-Achse mit geschätzter Bias-Korrektur.
TYPE_GRAVITY SensorEvent.values[0] Schwerkraft entlang der X-Achse. m/s2
SensorEvent.values[1] Die Schwerkraft entlang der Y-Achse.
SensorEvent.values[2] Die Schwerkraft entlang der Z-Achse.
TYPE_GYROSCOPE SensorEvent.values[0] Rotationsrate um die x-Achse. rad/s
SensorEvent.values[1] Rotationsgeschwindigkeit um die y-Achse.
SensorEvent.values[2] Rotationsgeschwindigkeit 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 um die X-Achse.
SensorEvent.values[4] Geschätzte Abweichung um die Y-Achse.
SensorEvent.values[5] Geschätzte Abweichung 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] Komponente des Rotationsvektors entlang der X-Achse (x * sin(θ/2)). Einheitenlos
SensorEvent.values[1] Komponente des Rotationsvektors entlang der Y-Achse (y * sin(θ/2)).
SensorEvent.values[2] Komponente des Rotationsvektors entlang der Z-Achse (z * sin(θ/2)).
SensorEvent.values[3] Skalare Komponente des Rotationsvektors (cos(θ/2)).1
TYPE_SIGNIFICANT_MOTION
TYPE_STEP_COUNTER SensorEvent.values[0] Die Anzahl der Schritte, die der Nutzer seit dem letzten Neustart ausgeführt hat, während der Sensor aktiviert war. Schritte
TYPE_STEP_DETECTOR

1 Die skalare Komponente ist ein optionaler Wert.

Der Sensor für den Rotationsvektor und der Schwerkraftsensor sind die am häufigsten verwendeten Sensoren für die Bewegungserkennung und ‑überwachung. Der Sensor für Rotationsvektoren 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 Änderungen der relativen Ausrichtung. Der Rotationsvektorsensor ist beispielsweise ideal, wenn Sie ein Spiel, eine Augmented Reality-Anwendung, einen 2- oder 3‑dimensionalen Kompass oder eine App zur Kamerastabilisierung entwickeln. In den meisten Fällen ist die Verwendung dieser Sensoren besser als die Verwendung des Beschleunigungsmessers und des geomagnetischen Feldsensors oder des Orientierungssensors.

Sensoren im Open-Source-Projekt für Android

Das Android Open Source Project (AOSP) bietet drei softwarebasierte Bewegungssensoren: einen Schwerkraftsensor, einen Sensor für lineare Beschleunigung und einen Sensor für Rotationsvektoren. Diese Sensoren wurden in Android 4.0 aktualisiert und verwenden jetzt das Gyroskop eines Geräts (zusätzlich zu anderen Sensoren), um die 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, die Versionsnummer ist 3). Es ist erforderlich, diese Sensoren nach Anbieter und Versionsnummer zu identifizieren, 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 benötigen ein Gyroskop. Wenn ein Gerät kein Gyroskop hat, werden diese Sensoren nicht angezeigt und sind nicht verfügbar.

Schwerkraftsensor 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. Der folgende Code zeigt, wie Sie eine Instanz des Standardsensors für die Schwerkraft 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 die des Beschleunigungssensors (m/s2) und das Koordinatensystem ist dasselbe wie das des Beschleunigungssensors.

Hinweis:Wenn sich ein Gerät in Ruhe befindet, sollte die Ausgabe des Schwerkraftsensors mit der des Beschleunigungsmessers identisch sein.

Lineares Beschleunigungsmessgerät verwenden

Der Sensor für lineare Beschleunigung liefert einen dreidimensionalen Vektor, der die Beschleunigung entlang jeder Geräteachse ohne Berücksichtigung der Schwerkraft darstellt. Sie können diesen Wert für die Gestenerkennung verwenden. Der Wert kann auch als Eingabe für ein Trägheitsnavigationssystem dienen, das auf der Koppelnavigation basiert. Der folgende Code zeigt, wie Sie eine Instanz des Standard-Sensors für 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);

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

linear acceleration = acceleration - acceleration due to gravity

Dieser Sensor wird in der Regel verwendet, wenn Sie Beschleunigungsdaten ohne den Einfluss der Schwerkraft erfassen möchten. Sie können diesen Sensor beispielsweise verwenden, um die Geschwindigkeit Ihres Autos zu ermitteln. Der Sensor für die lineare Beschleunigung hat immer einen Offset, den Sie entfernen müssen. Am einfachsten ist es, wenn Sie einen Kalibrierungsschritt in Ihre Anwendung einbauen. Während der Kalibrierung können Sie den Nutzer bitten, das Gerät auf einen Tisch zu legen und dann die Offsets für alle drei Achsen zu lesen. Sie können diesen Offset dann von den direkten Messwerten des Beschleunigungssensors abziehen, um die tatsächliche lineare Beschleunigung zu erhalten.

Das Koordinatensystem des Sensors ist dasselbe wie das des Beschleunigungssensors. Das gilt auch für die Maßeinheiten (m/s2).

Rotationsvektorsensor verwenden

Der Rotationsvektor stellt die Ausrichtung des Geräts als Kombination aus einem Winkel und einer Achse dar, wobei das Gerät um einen Winkel θ um eine Achse (x, y oder z) gedreht wurde. 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 so ausgedrückt:

x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)

Dabei entspricht die Länge des Rotationsvektors sin(θ/2) und die Richtung des Rotationsvektors der Richtung der Rotationsachse.

Abbildung 1: Koordinatensystem, das vom Sensor für den Rotationsvektor verwendet wird.

Die drei Elemente des Rotationsvektors entsprechen den letzten drei Komponenten eines Einheitsquaternions (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). Die Elemente des Rotationsvektors sind einheitenlos. Die x-, y- und z-Achsen sind genauso definiert wie beim Beschleunigungssensor. Das Referenzkoordinatensystem ist als direkte orthonormale Basis definiert (siehe Abbildung 1). Dieses Koordinatensystem hat die folgenden Eigenschaften:

  • X ist als Kreuzprodukt von Y und Z definiert. Sie verläuft tangential zum Boden am aktuellen Standort des Geräts und zeigt ungefähr nach Osten.
  • Y verläuft tangential zum Boden am aktuellen Standort des Geräts und zeigt zum geomagnetischen Nordpol.
  • Z zeigt in den Himmel und steht senkrecht zur Bodenebene.

Eine Beispielanwendung, die zeigt, wie der Sensor für Rotationsvektoren verwendet wird, finden Sie unter RotationVectorDemo.java.

Sensor für erhebliche Bewegungen verwenden

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

Schrittzähler verwenden

Der Schrittzähler-Sensor gibt die Anzahl der Schritte an, die der Nutzer seit dem letzten Neustart gemacht hat, während der Sensor aktiviert war. Der Schrittzähler hat eine höhere Latenz (bis zu 10 Sekunden), ist aber genauer als der Schrittdetektorsensor.

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 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 zu schonen, auf denen Ihre App ausgeführt wird, sollten Sie die Klasse JobScheduler verwenden, um den aktuellen Wert des Schrittzählersensors in einem bestimmten Intervall abzurufen. Obwohl für verschiedene Arten von Apps unterschiedliche Intervalle für das Lesen von Sensordaten erforderlich sind, sollten Sie dieses Intervall so lang wie möglich gestalten, 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.

Der folgende Code zeigt, wie Sie eine Instanz des Standardsensors für die Schrittzählung 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 rotierenden Kräften, die auf das Gerät wirken. Damit Sie die Werte dieser Sensoren effektiv nutzen können, müssen Sie Faktoren aus der Umgebung herausfiltern, z. B. die Schwerkraft. Möglicherweise müssen Sie auch einen Glättungsalgorithmus auf den Trend der Werte anwenden, um das Rauschen zu reduzieren.

Beschleunigungsmesser verwenden

Ein Beschleunigungssensor misst die auf das Gerät wirkende 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, wird die Aktualisierungsrate dieses Sensors begrenzt.

Ein Beschleunigungssensor bestimmt die Beschleunigung, die auf ein Gerät (Ad) angewendet wird, indem er die Kräfte (Fs) misst, die auf den Sensor selbst angewendet werden. Dabei gilt folgende Beziehung:

A_D=-(1/mass)∑F_S

Die Schwerkraft beeinflusst die gemessene Beschleunigung jedoch immer gemäß der folgenden Beziehung:

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

Wenn das Gerät also auf einem Tisch liegt und nicht beschleunigt wird, zeigt der Beschleunigungsmesser einen Wert von g = 9,81 m/s2 an. Wenn das Gerät im freien Fall ist und daher mit 9, 81 m/s2 schnell auf den Boden zufällt, zeigt der Beschleunigungsmesser einen Wert von g = 0 m/s2 an. Um die tatsächliche Beschleunigung des Geräts zu messen, muss der Beitrag der Schwerkraft aus den Beschleunigungsmesserdaten 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:Sie können Sensordaten auf viele verschiedene Arten filtern. Im Codebeispiel oben wird eine einfache Filterkonstante (alpha) verwendet, um einen Tiefpassfilter zu erstellen. Diese Filterkonstante wird aus einer Zeitkonstante (t) abgeleitet, die eine ungefähre Darstellung der Latenz ist, die der Filter den Sensorereignissen hinzufügt, und der Ereignisübermittlungsrate (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 für Sensoren. 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 nach rechts schieben, ist der Wert für die X-Beschleunigung positiv.
  • Wenn Sie das Gerät unten von sich wegdrücken, ist der Wert für die Y-Beschleunigung positiv.
  • Wenn Sie das Gerät mit einer Beschleunigung von A m/s2 in Richtung Himmel bewegen, entspricht der Z-Beschleunigungswert A + 9,81. Das entspricht der Beschleunigung des Geräts (+A m/s2) abzüglich der Schwerkraft (-9,81 m/s2).
  • Das stationäre 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, wenn Sie die Bewegung des Geräts ü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 Gravitationskräfte zu eliminieren und Rauschen zu reduzieren.

Gyroskop verwenden

Das Gyroskop misst die Rotationsgeschwindigkeit in rad/s um die x-, y- und z-Achse eines Geräts. Der folgende Code zeigt, 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, wird die Aktualisierungsrate dieses Sensors begrenzt.

Das Koordinatensystem des Sensors ist dasselbe wie das des Beschleunigungssensors. Die Drehung ist im Gegenuhrzeigersinn positiv. Das bedeutet, dass ein Beobachter, der von einer positiven Position auf der x-, y- oder z-Achse auf ein Gerät blickt, das sich am Ursprung befindet, eine positive Drehung meldet, wenn sich das Gerät im Gegenuhrzeigersinn dreht. Dies ist die standardmäßige mathematische Definition für die positive Drehung und nicht dieselbe wie die Definition für die Rollbewegung, 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 hinweg 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 rohe Rotationsdaten ohne Filterung oder Korrektur von Rauschen und Drift (Bias). In der Praxis führen Gyroskoprauschen und ‑drift zu Fehlern, die kompensiert werden müssen. Drift (Bias) und Rauschen werden in der Regel durch die Überwachung anderer Sensoren wie dem Schwerkraftsensor oder dem Beschleunigungsmesser bestimmt.

Nicht kalibriertes Gyroskop verwenden

Das unkalibrierte Gyroskop ähnelt dem Gyroskop, mit der Ausnahme, dass keine Kompensation der Gyroskop-Drift auf die Drehrate angewendet wird. Die werkseitige Kalibrierung und die Temperaturkompensation werden weiterhin auf die Drehrate angewendet. Das unkalibrierte Gyroskop ist nützlich für die Nachbearbeitung und das Zusammenführen von Orientierungsdaten. Im Allgemeinen ist gyroscope_event.values[0] nahe an uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Das bedeutet:

calibrated_x ~= uncalibrated_x - bias_estimate_x

Hinweis:Nicht kalibrierte Sensoren liefern mehr Rohdaten und können einige Abweichungen aufweisen. Ihre Messungen enthalten jedoch weniger Sprünge durch Korrekturen, die durch die Kalibrierung angewendet werden. Einige Anwendungen bevorzugen möglicherweise diese nicht kalibrierten Ergebnisse, da sie gleichmäßiger und zuverlässiger sind. Wenn eine Anwendung beispielsweise versucht, eigene Sensorfusion durchzuführen, können Kalibrierungen die Ergebnisse verzerren.

Neben den Rotationsraten liefert das unkalibrierte Gyroskop auch die geschätzte Drift um jede Achse. Der folgende Code zeigt, wie Sie eine Instanz des unkalibrierten Standardgyroskops 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);

Zusätzliche Codebeispiele

Das BatchStepSensor-Beispiel veranschaulicht die Verwendung der auf dieser Seite behandelten APIs.

Lesen Sie auch