Bewegungssensoren

Die Android-Plattform bietet mehrere Sensoren, mit denen Sie die Bewegung eines Geräts erfassen können.

Die möglichen Architekturen der Sensoren variieren je nach Sensortyp:

  • Die Sensoren für die Schwerkraft, die lineare Beschleunigung, den Rotationsvektor, die signifikante Bewegung, den Schrittzähler und den Schrittdetektor sind entweder hardware- oder softwarebasiert.
  • Der Beschleunigungsmesser und die Gyroskopsensoren sind immer hardwarebasiert.

Die meisten Android-Geräte haben einen Beschleunigungsmesser und viele sind jetzt mit einem Gyroskop ausgestattet. Die Verfügbarkeit der softwarebasierten Sensoren ist variabel, da sie häufig auf einen oder mehrere Hardwaresensoren zurückgreifen, um ihre Daten zu erfassen. 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 Neigung, Schüttel, Drehung oder Schaukel zu überwachen. Die Bewegung spiegelt in der Regel direkte Nutzereingaben wider (z. B. wenn ein Nutzer in einem Spiel ein Auto lenkt oder einen Ball in einem Spiel steuert). Sie kann aber auch die physische Umgebung widerspiegeln, in der das Gerät sitzt (z. B. wenn er sich mit Ihnen bewegt, während Sie Ihr Auto fahren). Im ersten Fall beobachten Sie die Bewegung relativ zum Bezugsrahmen des Geräts oder zum Bezugsrahmen Ihrer App. Im zweiten Fall beobachten Sie die Bewegung relativ zum Bezugsrahmen der Welt. Bewegungssensoren werden normalerweise nicht zur Überwachung der Geräteposition verwendet, können aber mit anderen Sensoren verwendet werden, z. B. dem Sensor für geomagnetische Felder, um die Position eines Geräts relativ zum Bezugsrahmen der Welt zu bestimmen (weitere Informationen finden Sie unter Positionssensoren).

Alle Bewegungssensoren geben für jede SensorEvent mehrdimensionale Arrays von Sensorwerten zurück. Während eines einzelnen Sensorereignisses gibt der Beschleunigungsmesser beispielsweise Beschleunigungskraftdaten für die drei Koordinatenachsen und das Gyroskop Daten zur Rotationsrate 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 Bewegungssensoren zusammengefasst, die auf der Android-Plattform verfügbar sind.

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 der Schwerkraft). m/s2
SensorEvent.values[1] Beschleunigungskraft entlang der Y-Achse (einschließlich der Schwerkraft).
SensorEvent.values[2] Beschleunigungskraft entlang der z-Achse (einschließlich der 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.
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 die Schwerkraft). m/s2
SensorEvent.values[1] Beschleunigungskraft entlang der Y-Achse (ohne die 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] Komponente des Rotationsvektors entlang der Y-Achse (y × sin(Θ/2)).
SensorEvent.values[2] Rotationsvektorkomponente 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] Anzahl der Schritte, die der Nutzer seit dem letzten Neustart gemacht hat, während der Sensor aktiviert war. Schritte
TYPE_STEP_DETECTOR

1 Die Skalarkomponente ist ein optionaler Wert.

Der Rotationsvektorsensor und der Gravitationssensor sind die am häufigsten verwendeten Sensoren zur Bewegungserkennung und -überwachung. Der Rotationsvektorsensor ist besonders vielseitig und kann für eine Vielzahl von bewegungsbezogenen Aufgaben verwendet werden, z. B. das Erkennen von Gesten, das Überwachen von Winkeländerungen und das Überwachen von relativen Ausrichtungsänderungen. Der Rotationsvektorsensor ist 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 der Einsatz dieser Sensoren besser als die Verwendung des Beschleunigungsmessers und des Geomagnetischen Feldsensors oder des Ausrichtungssensors.

Sensoren des Open-Source-Projekts von Android

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 verwenden jetzt neben anderen Sensoren das Gyroskop eines Geräts, um Stabilität und Leistung zu verbessern. Wenn du diese Sensoren ausprobieren möchtest, kannst du sie mithilfe der Methoden getVendor() und getVersion() identifizieren. Der Anbieter ist Google LLC; die Versionsnummer ist 3. Die Identifizierung dieser Sensoren nach Hersteller und Versionsnummer ist erforderlich, 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 nutzen ein Gyroskop: Wenn ein Gerät kein Gyroskop hat, werden diese Sensoren nicht angezeigt und können nicht verwendet werden.

Schwerkraftsensor verwenden

Der Schwerkraftsensor liefert einen dreidimensionalen Vektor, 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 Standardschwerkraftsensors 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 entsprechen denen des Beschleunigungssensors (m/s2) und das Koordinatensystem ist mit dem vom Beschleunigungssensor verwendeten Koordinatensystem identisch.

Hinweis:Bei einem inaktiven Gerät sollte die Ausgabe des Schwerkraftsensors mit der Ausgabe des Beschleunigungsmessers übereinstimmen.

Linearen Beschleunigungsmesser verwenden

Der lineare Beschleunigungssensor liefert Ihnen einen dreidimensionalen Vektor, der die Beschleunigung entlang jeder Geräteachse abzüglich der Schwerkraft darstellt. Sie können diesen Wert für die Gestenerkennung verwenden. Der Wert kann auch als Eingabe für ein inertiales Navigationssystem dienen, das die Funktion „Tatenrechnung“ 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 normalerweise, wenn Sie Beschleunigungsdaten ohne Einfluss der Schwerkraft erfassen möchten. Mit diesem Sensor können Sie beispielsweise feststellen, wie schnell Ihr Auto fährt. Der lineare Beschleunigungssensor hat immer einen Offset, den Sie entfernen müssen. Am einfachsten ist es, einen Kalibrierungsschritt in Ihre Anwendung zu integrieren. Während der Kalibrierung können Sie den Nutzer bitten, das Gerät auf einen Tisch zu stellen, und dann die Offsets für alle drei Achsen lesen. Anschließend können Sie diesen Offset von den direkten Messwerten des Beschleunigungssensors subtrahieren, um die tatsächliche lineare Beschleunigung zu erhalten.

Das Koordinatensystem des Sensors entspricht dem, das vom Beschleunigungssensor verwendet wird, sowie 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 einen Winkel Θ um eine Achse (x, y oder z) gedreht hat. Der folgende Code zeigt, wie Sie eine Instanz des Standardsensors für den Rotationsvektor 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(Θ/2), y*sin(Θ/2), z*sin(Θ/2)

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

Abbildung 1: Vom Rotationsvektorsensor verwendetes Koordinatensystem.

Die drei Elemente des Rotationsvektors sind gleich den letzten drei Komponenten einer Einheitsquaternion (cos(Θ/2), x*sin(Θ/2), y*sin(Θ/2) und z*sin(Θ/2). Elemente des Rotationsvektors sind ohne Einheit. Die x-, y- und z-Achsen sind genauso definiert wie der Beschleunigungssensor. Das Referenzkoordinatensystem ist als direkte Orthonormalbasis definiert (siehe Abbildung 1). Dieses Koordinatensystem hat die folgenden Eigenschaften:

  • X ist definiert als das Vektorprodukt Y x Z. Sie ist an der aktuellen Position des Geräts und annähernd nach Osten ausgerichtet.
  • Y ist am aktuellen Standort des Geräts tangential für den Boden und zeigt auf den geomagnetischen Nordpol.
  • Z zeigt in Richtung Himmel und ist senkrecht zur Bodenebene.

Eine Beispielanwendung, in der die Verwendung des Rotationsvektorsensors veranschaulicht wird, finden Sie unter RotationVectorDemo.java.

Bewegungssensor mit signifikanter

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

Schrittzähler-Sensor 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), aber eine höhere Genauigkeit 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 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 auf Geräten zu schonen, auf denen deine App ausgeführt wird, solltest du die Klasse JobScheduler verwenden, um den aktuellen Wert in einem bestimmten Intervall vom Schrittzählersensor abzurufen. Auch wenn für verschiedene Arten von Anwendungen unterschiedliche Intervalle für die Sensorlese erforderlich sind, sollten Sie dieses Intervall so lang wie möglich halten, es sei denn, Ihre Anwendung benötigt Echtzeitdaten vom Sensor.

Schritterkennungssensor verwenden

Der Schrittdetektorsensor löst jedes Mal ein Ereignis aus, wenn der Nutzer einen Schritt ausführt. Die Latenz liegt voraussichtlich unter 2 Sekunden.

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-Schrittdetektorsensors 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. Damit Sie die Werte dieser Sensoren effektiv nutzen 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 der Werte 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 Standard-Beschleunigungssensors 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, gilt für diesen Sensor eine Ratenbegrenzung.

Konzeptionell bestimmt ein Beschleunigungssensor die Beschleunigung, die auf ein Gerät (Ad) angewendet wird. Dazu werden die Kräfte gemessen, die auf den Sensor selbst (Fs) angewendet werden. Dazu wird die folgende Beziehung verwendet:

A_D=-(1/Masse)∑F_S

Die Schwerkraft hat jedoch immer einen Einfluss auf die gemessene Beschleunigung gemäß der folgenden Beziehung:

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

Aus diesem Grund misst der Beschleunigungsmesser eine Größenordnung von g = 9, 81 m/s2, wenn das Gerät auf einem Tisch liegt und nicht beschleunigt wird. Wenn sich das Gerät im freien Fall befindet und daher mit 9, 81 m/s2 schnell in Richtung Boden beschleunigt, misst sein Beschleunigungsmesser eine Größenordnung von g = 0 m/s2. Daher muss zur Messung der tatsächlichen Beschleunigung des Geräts der Beitrag der Schwerkraft aus den Daten des Beschleunigungsmessers entfernt werden. Dies kann durch die Anwendung eines Hochpassfilters erreicht werden. Umgekehrt kann ein Tiefpassfilter verwendet werden, um die Schwerkraft zu isolieren. Das folgende Beispiel zeigt, wie das geht:

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 grobe Darstellung der Latenz, die der Filter zu den Sensorereignissen hinzufügt, und der Ereignislieferrate (dt) des Sensors ergibt. 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 nutzen das standardmäßige Sensor-Koordinatensystem. In der Praxis bedeutet dies, 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 die linke Seite drücken, sodass es sich nach rechts bewegt, ist der x-Beschleunigungswert positiv.
  • Wenn Sie das Gerät auf die Unterseite drücken (sodass es sich von Ihnen wegbewegt), ist der y-Beschleunigungswert positiv.
  • Wenn Sie das Gerät mit einer Beschleunigung von A m/s2 in Richtung Himmel schieben, 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 entspricht (0 m/s2 minus die Schwerkraft, also -9,81 m/s2).

Im Allgemeinen ist der Beschleunigungsmesser ein guter Sensor zur Überwachung der Gerätebewegung. Nahezu alle Android-Geräte und -Tablets haben einen Beschleunigungsmesser, der im Vergleich zu den anderen Bewegungssensoren etwa zehnmal weniger Energie verbraucht. 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 Drehgeschwindigkeit 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, gilt für diesen Sensor eine Ratenbegrenzung.

Das Koordinatensystem des Sensors entspricht dem, das für den Beschleunigungssensor verwendet wird. Die Drehung ist positiv in die Richtung gegen den Uhrzeigersinn. Das bedeutet, dass ein Beobachter, der von einer positiven Position auf der x-, y- oder z-Achse auf ein am Ursprung positioniertes Gerät blickt, eine positive Drehung meldet, wenn sich das Gerät gegen den Uhrzeigersinn dreht. Dies ist die standardmäßige mathematische Definition der positiven Rotation, die nicht mit der Definition für Roll übereinstimmt, die vom Ausrichtungssensor verwendet wird.

In der Regel wird die Ausgabe des Gyroskops über die Zeit integriert, um eine Drehung zu berechnen, die die Winkeländerung im Zeitverlauf 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;
}

Standard-Gyroskope liefern Rohdaten zu Rotationen ohne Filterung oder Korrektur von Rauschen und Drift (Verzerrung). In der Praxis führen Gyroskoprauschen und -drift zu Fehlern, die behoben werden müssen. In der Regel ermitteln Sie die Abweichung (Verzerrung) und das Rauschen durch Überwachung anderer Sensoren, z. B. des Schwerkraftsensors oder Beschleunigungsmessers.

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 die Temperaturkompensation werden weiterhin auf die Drehgeschwindigkeit angewendet. Das nicht kalibrierte Gyroskop eignet sich für die Nachbearbeitung und Zusammenführung von Ausrichtungsdaten. Im Allgemeinen liegt gyroscope_event.values[0] in der Nähe von 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 Rohergebnisse und können eine gewisse Verzerrung enthalten. Ihre Messungen enthalten jedoch weniger Sprünge aufgrund von Korrekturen, die während der Kalibrierung vorgenommen wurden. Einige Anwendungen bevorzugen diese nicht kalibrierten Ergebnisse möglicherweise als flüssiger und zuverlässiger. Wenn eine Anwendung beispielsweise versucht, eine eigene Sensorfusion durchzuführen, können Kalibrierungen die Ergebnisse verzerren.

Zusätzlich zu den Drehgeschwindigkeiten liefert das nicht kalibrierte Gyroskop auch die geschätzte Abweichung um jede Achse. Der folgende Code zeigt, wie Sie eine Instanz des 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);

Zusätzliche Codebeispiele

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

Weitere Informationen