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 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 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 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 Referenzpunkt der Welt ü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.

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 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 Verzerrungskompensation.
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 Vorabglättung.
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] Rotationsrate um die z-Achse.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Drehgeschwindigkeit (ohne Driftkompensation) um die X-Achse. rad/s
SensorEvent.values[1] Rotationsrate (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 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 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 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 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 neben 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 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. 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 entsprechen denen des Beschleunigungssensors (m/s2) und das Koordinatensystem ist mit dem vom Beschleunigungssensor verwendeten Koordinatensystem identisch.

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 entspricht dem, das vom Beschleunigungssensor verwendet wird, sowie 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. 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 Drehvektors werden so 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 ist mit der Richtung der Achse der Drehachse identisch.

Abbildung 1: Koordinatensystem, das vom Drehvektorsensor verwendet wird.

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-Achsen sind genauso definiert wie der Beschleunigungssensor. Das Referenzkoordinatensystem wird als direkte orthonormale Basis 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 gerichtet.
  • Y ist am aktuellen Standort des Geräts tangential für den Boden und zeigt auf den 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 wichtige Bewegungen verwenden

Der Sensor für signifikante Bewegungen löst jedes Mal ein Ereignis aus, wenn eine signifikante 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. 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 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 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 Standardschrittzä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 von Geräten, auf denen Ihre App ausgeführt wird, zu schonen, sollten Sie die JobScheduler-Klasse verwenden, um den aktuellen Wert des Schrittzählersensors in einem bestimmten Intervall 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.

Schrittzähler verwenden

Der Schritterkennungssensor 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 stellen Ihrer App Rohdaten zu den linearen und Rotationskräften zur Verfügung, die auf das Gerät ausgeübt werden. 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ä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. 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.

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:

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

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 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 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: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 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 Sensorkoordinatensystem. 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 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 abzüglich der 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. In der Regel ermitteln Sie die Abweichung (Verzerrung) und das Rauschen durch Überwachung anderer Sensoren, z. B. des Schwerkraft- 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 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 liegt 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.

Lesen Sie auch