Bewegungssensoren

Die Android-Plattform bietet mehrere Sensoren, mit denen du die Bewegung eines Geräts überwachen kannst.

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

  • Die Sensoren für Schwerkraft, lineare Beschleunigung, Rotationsvektor, signifikante Bewegung, Schrittzähler und Schritterkennung 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 einen oder mehrere Hardwaresensoren angewiesen sind, 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 überwachen. Die Bewegung ist in der Regel eine Folge direkter Nutzereingaben (z. B. ein Nutzer, der ein Auto in einem Spiel steuert, oder ein Nutzer, der einen Ball in einem Spiel kontrolliert), kann aber auch eine Folge der physischen Umgebung sein, in der sich das Gerät befindet (z. B. Bewegung mit dir, während du dein Auto fährst). Im ersten Fall wird die Bewegung relativ zum Bezugssystem des Geräts oder der Anwendung überwacht. Im zweiten Fall wird die Bewegung relativ zum Bezugssystem der Welt überwacht. Bewegungssensoren werden in der Regel nicht allein zur Überwachung der Geräteposition verwendet, können aber zusammen mit anderen Sensoren wie dem geomagnetischen Feldsensor verwendet werden, um die Position eines Geräts relativ zum Bezugssystem der Welt zu bestimmen (weitere Informationen findest du unter Positionssensoren).

Alle Bewegungssensoren geben für jedes SensorEvent mehrdimensionale Arrays von Sensorwerten zurück. Beispielsweise gibt der Beschleunigungsmesser während eines einzelnen Sensorereignisses Daten zur Beschleunigungskraft für die drei Koordinatenachsen zurück und das Gyroskop Daten zur Rotationsgeschwindigkeit für die drei Koordinatenachsen. 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 Sensordaten zu Ereignissen 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-Kompensation. m/s2
SensorEvent.values[1] Gemessene Beschleunigung entlang der Y-Achse ohne Bias-Kompensation.
SensorEvent.values[2] Gemessene Beschleunigung entlang der Z-Achse ohne Bias-Kompensation.
SensorEvent.values[3] Gemessene Beschleunigung entlang der X-Achse mit geschätzter Bias-Kompensation.
SensorEvent.values[4] Gemessene Beschleunigung entlang der Y-Achse mit geschätzter Bias-Kompensation.
SensorEvent.values[5] Gemessene Beschleunigung entlang der Z-Achse mit geschätzter Bias-Kompensation.
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] Rotationsgeschwindigkeit 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] Rotationsgeschwindigkeit (ohne Driftkompensation) um die x-Achse. rad/s
SensorEvent.values[1] Rotationsgeschwindigkeit (ohne Driftkompensation) um die Y-Achse.
SensorEvent.values[2] Rotationsgeschwindigkeit (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] 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 unternommen hat, während der Sensor aktiviert war. Schritte
TYPE_STEP_DETECTOR – – –

1 Die skalare Komponente 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 Orientierungsänderungen. Der Rotationsvektorsensor ist beispielsweise ideal, wenn du ein Spiel, eine Augmented-Reality-Anwendung, einen 2D- oder 3D-Kompass oder eine App zur Kamerastabilisierung entwickelst. In den meisten Fällen ist die Verwendung dieser Sensoren besser als die Verwendung des Beschleunigungsmessers und des geomagnetischen Feldsensors oder des Orientierungssensors.

Sensoren des Open-Source-Projekts für Android

Das Open-Source-Projekt für Android (AOSP) bietet drei softwarebasierte Bewegungssensoren: einen Schwerkraftsensor, einen Sensor für die lineare Beschleunigung und einen Rotationsvektorsensor. 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 du diese Sensoren ausprobieren möchtest, kannst du sie mit der Methode getVendor() und der Methode getVersion() identifizieren (der Anbieter ist Google LLC, die Versionsnummer ist 3). Die Identifizierung dieser Sensoren nach Anbieter 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 sind auf ein Gyroskop angewiesen. 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 die Richtung und Stärke 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 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 im Ruhezustand befindet, sollte die Ausgabe des Schwerkraftsensors mit der des Beschleunigungsmessers identisch sein.

Linearen Beschleunigungsmesser verwenden

Der Sensor für die lineare Beschleunigung liefert einen dreidimensionalen Vektor, der die Beschleunigung entlang jeder Geräteachse darstellt, ausgenommen die Schwerkraft. Sie können diesen Wert verwenden, um Gesten zu erkennen. Der Wert kann auch als Eingabe für ein Trägheitsnavigationssystem dienen, das die Koppelnavigation verwendet. Der folgende Code zeigt, wie Sie eine Instanz des standardmäßigen Sensors 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);

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

linear acceleration = acceleration - acceleration due to gravity

Dieser Sensor wird normalerweise verwendet, wenn Sie Beschleunigungsdaten ohne den Einfluss der Schwerkraft erhalten möchten. Mit diesem Sensor können Sie beispielsweise sehen, wie schnell Ihr Auto fährt. Der Sensor für die lineare Beschleunigung hat immer einen Offset, den Sie entfernen müssen. Am einfachsten geht das, indem 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 ablesen. Diesen Offset kannst du dann von den direkten Messwerten des Beschleunigungssensors subtrahieren, um die tatsächliche lineare Beschleunigung zu erhalten.

Das Koordinatensystem des Sensors ist mit dem des Beschleunigungssensors identisch, ebenso wie die Maßeinheiten (m/s2).

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 Größe des Rotationsvektors sin(θ/2) und die Richtung des Rotationsvektors der Richtung der Rotationsachse.

Abbildung 1. Koordinatensystem, das vom Rotationsvektorsensor verwendet wird.

Die drei Elemente des Rotationsvektors entsprechen den letzten drei Komponenten einer Einheitsquaternion (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). Die Elemente des Rotationsvektors sind einheitenlos. Die x-, y- und z-Achsen sind auf dieselbe Weise wie beim Beschleunigungssensor definiert. Das Referenzkoordinatensystem ist als direkte Orthonormalbasis definiert (siehe Abbildung 1). Dieses Koordinatensystem hat die folgenden Merkmale:

  • X ist definiert als das Vektorprodukt Y x Z. Sie verläuft tangential zum Boden am aktuellen Standort des Geräts und zeigt ungefähr nach Osten.
  • Y ist tangential zum Boden am aktuellen Standort des Geräts und zeigt in Richtung des geomagnetischen Nordpols.
  • Z zeigt in Richtung Himmel und ist senkrecht zur Bodenebene.

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

Bewegungssensor 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 signifikante 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 du eine Instanz des standardmäßigen Sensors für signifikante Bewegungen abrufst und einen Event-Listener registrierst:

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ählersensor verwenden

Der Schrittzählersensor liefert die Anzahl der Schritte, die der Nutzer seit dem letzten Neustart unternommen 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 : Du musst die Berechtigung ACTIVITY_RECOGNITION deklarieren, damit deine 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 den Schrittzähler abrufen:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);

Um den Akku von Geräten zu schonen, auf denen deine App ausgeführt wird, solltest du die Klasse JobScheduler verwenden, um den aktuellen Wert des Schrittzählersensors in einem bestimmten Intervall abzurufen. Obwohl verschiedene Arten von Apps unterschiedliche Intervalle für das Auslesen von Sensoren erfordern, solltest du dieses Intervall so lang wie möglich festlegen, es sei denn, deine App benötigt Echtzeitdaten vom Sensor.

Schrittzählersensor verwenden

Der Schrittzählersensor löst jedes Mal ein Ereignis aus, wenn der Nutzer einen Schritt macht. Die Latenz wird voraussichtlich unter 2 Sekunden liegen.

Hinweis : Du musst die Berechtigung ACTIVITY_RECOGNITION deklarieren, damit deine 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 deiner App Rohdaten zu den linearen und rotierenden Kräften, die auf das Gerät einwirken. Damit du die Werte dieser Sensoren effektiv nutzen kannst, musst du Umgebungseinflüsse wie die Schwerkraft herausfiltern. Möglicherweise müssen Sie auch einen Glättungsalgorithmus auf den Trend der Werte anwenden, um Rauschen zu reduzieren.

Beschleunigungsmesser verwenden

Ein Beschleunigungssensor misst die auf das Gerät einwirkende 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 deine App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, ist die Frequenz dieses Sensors begrenzt.

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) angewendet werden. Dabei wird die folgende Beziehung verwendet:

A_D=-(1/mass)∑F_S

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

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

Wenn das Gerät auf einem Tisch liegt (und nicht beschleunigt wird), misst der Beschleunigungsmesser daher eine Größe von g = 9,81 m/s2. Wenn sich das Gerät im freien Fall befindet und daher mit 9, 81 m/s2 schnell in Richtung Boden beschleunigt, zeigt der Beschleunigungsmesser einen Wert von g = 0 m/s2 an. Um die tatsächliche Beschleunigung des Geräts zu messen, muss daher der Beitrag der Schwerkraft aus den Beschleunigungsmesserdaten 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 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:Es gibt viele verschiedene Techniken, um Sensordaten zu 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 ist, die der Filter den Sensorereignissen hinzufügt, und der Ereignisbereitstellungsrate des Sensors (dt). Im Codebeispiel wird zu Demonstrationszwecken ein Alphawert von 0,8 verwendet. Wenn Sie diese Filtermethode verwenden, müssen Sie möglicherweise einen anderen Alpha-Wert auswählen.

Beschleunigungsmesser verwenden das standardmäßige Koordinatensystem für Sensoren. 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 du das Gerät auf der linken Seite anschiebst (sodass es sich nach rechts bewegt), ist der x-Beschleunigungswert positiv.
  • Wenn du das Gerät unten drückst (sodass es sich von dir wegbewegt), ist der y-Beschleunigungswert positiv.
  • Wenn Sie das Gerät mit einer Beschleunigung von A m/s2 in Richtung Himmel bewegen, entspricht der Beschleunigungswert auf der Z-Achse A + 9,81. Dies 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 minus der Schwerkraft, die -9,81 m/s2 beträgt) 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 die Schwerkraft zu eliminieren und das 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 deine App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, ist die Frequenz dieses Sensors begrenzt.

Das Koordinatensystem des Sensors ist mit dem des Beschleunigungssensors identisch. Die Drehung ist positiv, wenn sie gegen den Uhrzeigersinn erfolgt. Das heißt, ein Beobachter, der von einem positiven Punkt auf der x-, y- oder z-Achse auf ein Gerät blickt, das sich am Ursprung befindet, würde eine positive Drehung melden, wenn sich das Gerät gegen den Uhrzeigersinn zu drehen scheint. Dies ist die mathematische Standarddefinition für eine positive Drehung und nicht mit der Definition für die Rollbewegung identisch, 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 Rohdaten zur Rotation ohne Filterung oder Korrektur von Rauschen und Drift (Bias). In der Praxis führen Gyroskoprauschen und -drift zu Fehlern, die kompensiert werden müssen. Die Drift (Bias) und das Rauschen werden in der Regel durch die Überwachung anderer Sensoren wie des Schwerkraftsensors oder des Beschleunigungsmessers bestimmt.

Nicht kalibriertes Gyroskop verwenden

Das unkalibrierte Gyroskop ähnelt dem Gyroskop, mit dem Unterschied, dass die Rotationsgeschwindigkeit nicht um die Gyro-Drift korrigiert wird. Die Werkskalibrierung und die Temperaturkompensation werden weiterhin auf die Rotationsrate angewendet. Das unkalibrierte Gyroskop ist nützlich für die Nachbearbeitung und das Zusammenführen von Ausrichtungsdaten. Im Allgemeinen liegt gyroscope_event.values[0] nahe bei uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Das heißt,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Hinweis:Unkalibrierte Sensoren liefern mehr Rohdaten und können gewisse Abweichungen aufweisen. Ihre Messungen enthalten jedoch weniger Sprünge, die durch Korrekturen bei der Kalibrierung entstehen. Einige Anwendungen bevorzugen diese unkalibrierten Ergebnisse, da sie gleichmäßiger und zuverlässiger sind. Wenn eine Anwendung beispielsweise versucht, eine eigene Sensorfusion durchzuführen, können Kalibrierungen die Ergebnisse verzerren.

Zusätzlich zu 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 Beispiel BatchStepSensor veranschaulicht die Verwendung der auf dieser Seite beschriebenen APIs.

Sie sollten auch die