Capteurs de mouvement

La plate-forme Android fournit plusieurs capteurs qui vous permettent de surveiller le mouvement d'un appareil.

L'architecture possible des capteurs varie selon leur type:

  • Les capteurs de gravité, d'accélération linéaire, de vecteur de rotation, de mouvement important, de compteur de pas et de détecteur de pas sont basés sur le matériel ou sur un logiciel.
  • Les capteurs de l'accéléromètre et du gyroscope sont toujours basés sur le matériel.

La plupart des appareils Android sont équipés d'un accéléromètre, et beaucoup incluent désormais un gyroscope. La disponibilité des capteurs logiciels est plus variable, car ils s'appuient souvent sur un ou plusieurs capteurs matériels pour obtenir leurs données. Selon l'appareil, ces capteurs logiciels peuvent obtenir leurs données à partir de l'accéléromètre et du magnétomètre ou du gyroscope.

Les capteurs de mouvement sont utiles pour surveiller les mouvements de l'appareil, tels que l'inclinaison, le tremblement, la rotation ou le swing. Le mouvement est généralement le reflet d'une entrée directe de l'utilisateur (par exemple, un utilisateur qui dirige une voiture dans un jeu ou un utilisateur qui contrôle un ballon dans un jeu), mais il peut également refléter l'environnement physique dans lequel l'appareil est assis (par exemple, lorsqu'il se déplace avec vous pendant que vous conduisez votre voiture). Dans le premier cas, vous surveillez le mouvement par rapport au cadre de référence de l'appareil ou du cadre de référence de votre application. Dans le second cas, vous surveillez le mouvement par rapport au cadre de référence mondial. Les capteurs de mouvement ne sont généralement pas utilisés pour surveiller la position de l'appareil, mais ils peuvent être utilisés avec d'autres capteurs, tels que le capteur de champ géomagnétique, pour déterminer la position d'un appareil par rapport au cadre de référence mondial (voir Capteurs de position pour en savoir plus).

Tous les capteurs de mouvement renvoient des tableaux multidimensionnels de valeurs de capteurs pour chaque SensorEvent. Par exemple, lors d'un seul événement de capteur, l'accéléromètre renvoie les données de force d'accélération pour les trois axes de coordonnées, et le gyroscope renvoie les données de taux de rotation des trois axes de coordonnées. Ces valeurs de données sont renvoyées dans un tableau float (values) avec d'autres paramètres SensorEvent. Le tableau 1 récapitule les capteurs de mouvement disponibles sur la plate-forme Android.

Tableau 1. Capteurs de mouvement compatibles avec la plate-forme Android

Capteur Données d'événement des capteurs Description Unités de mesure
TYPE_ACCELEROMETER SensorEvent.values[0] Force d'accélération le long de l'axe X (y compris la gravité). m/s2
SensorEvent.values[1] Force d'accélération le long de l'axe Y (y compris la gravité).
SensorEvent.values[2] Force d'accélération le long de l'axe Z (y compris la gravité).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Accélération mesurée le long de l'axe X sans compensation de biais. m/s2
SensorEvent.values[1] Accélération mesurée le long de l'axe Y sans compensation de biais.
SensorEvent.values[2] Accélération mesurée le long de l'axe Z sans compensation de biais.
SensorEvent.values[3] Accélération mesurée le long de l'axe X avec estimation de la compensation de biais.
SensorEvent.values[4] Accélération mesurée le long de l'axe Y avec estimation de la compensation de biais.
SensorEvent.values[5] Accélération mesurée le long de l'axe Z avec estimation de la compensation de biais.
TYPE_GRAVITY SensorEvent.values[0] Force de gravité le long de l'axe X. m/s2
SensorEvent.values[1] Force de gravité le long de l'axe Y.
SensorEvent.values[2] Force de gravité le long de l'axe Z.
TYPE_GYROSCOPE SensorEvent.values[0] Taux de rotation autour de l'axe X. rad/s
SensorEvent.values[1] Taux de rotation autour de l'axe Y.
SensorEvent.values[2] Taux de rotation autour de l'axe Z.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Taux de rotation (sans compensation de la dérive) autour de l'axe X. rad/s
SensorEvent.values[1] Taux de rotation (sans compensation de la dérive) autour de l'axe Y.
SensorEvent.values[2] Taux de rotation (sans compensation de la dérive) autour de l'axe Z.
SensorEvent.values[3] Dérive estimée autour de l'axe X.
SensorEvent.values[4] Dérive estimée autour de l'axe Y.
SensorEvent.values[5] Dérive estimée autour de l'axe Z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] Force d'accélération le long de l'axe X (à l'exclusion de la gravité). m/s2
SensorEvent.values[1] Force d'accélération le long de l'axe Y (à l'exclusion de la gravité).
SensorEvent.values[2] Force d'accélération le long de l'axe Z (à l'exclusion de la gravité).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Composante de vecteur de rotation le long de l'axe x (x * sin(chèque/2)). Sans unité
SensorEvent.values[1] Composante de vecteur de rotation le long de l'axe y (y * sin(theme/2)).
SensorEvent.values[2] Composante de vecteur de rotation le long de l'axe z (z * sin(theme/2)).
SensorEvent.values[3] Composante scalaire du vecteur de rotation ((cos(View/2)).1
TYPE_SIGNIFICANT_MOTION N/A N/A N/A
TYPE_STEP_COUNTER SensorEvent.values[0] Nombre de pas effectués par l'utilisateur depuis le dernier redémarrage lorsque le capteur était activé. Étapes
TYPE_STEP_DETECTOR N/A N/A N/A

1 Le composant scalaire est une valeur facultative.

Le capteur de vecteur de rotation et le capteur de gravité sont les capteurs les plus fréquemment utilisés pour la détection et la surveillance des mouvements. Le capteur à vecteur de rotation est particulièrement polyvalent et peut être utilisé pour un large éventail de tâches liées au mouvement, telles que la détection de gestes, la surveillance des changements angulaires et la surveillance des changements d'orientation relative. Par exemple, le capteur à vecteur de rotation est idéal si vous développez un jeu, une application de réalité augmentée, une boussole bidimensionnelle ou tridimensionnelle, ou une application de stabilisation d'appareil photo. Dans la plupart des cas, il est préférable d'utiliser ces capteurs plutôt que l'accéléromètre et le capteur de champ géomagnétique ou le capteur d'orientation.

Capteurs de projet Android Open Source

Le projet Android Open Source (AOSP) fournit trois capteurs de mouvement logiciels: un capteur de gravité, un capteur d'accélération linéaire et un capteur à vecteur de rotation. Ces capteurs ont été mis à jour dans Android 4.0 et utilisent désormais le gyroscope d'un appareil (en plus d'autres capteurs) pour améliorer la stabilité et les performances. Si vous souhaitez tester ces capteurs, vous pouvez les identifier à l'aide des méthodes getVendor() et getVersion() (le fournisseur est Google LLC, dont le numéro de version est 3). Il est nécessaire d'identifier ces capteurs selon leur fournisseur et leur numéro de version, car le système Android considère ces trois capteurs comme des capteurs secondaires. Par exemple, si un fabricant d'appareils fournit son propre capteur de gravité, le capteur de gravité AOSP apparaît comme un capteur de gravité secondaire. Ces trois capteurs reposent sur un gyroscope: si un appareil n'en est pas équipé, ils ne s'affichent pas et ne peuvent pas être utilisés.

Utiliser le capteur de gravité

Le capteur de gravité fournit un vecteur tridimensionnel indiquant la direction et l'amplitude de la gravité. En règle générale, ce capteur est utilisé pour déterminer l'orientation relative de l'appareil dans l'espace. Le code suivant vous montre comment obtenir une instance du capteur de gravité par défaut:

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

Les unités sont les mêmes que celles utilisées par le capteur d'accélération (m/s2), et le système de coordonnées est identique à celui utilisé par le capteur d'accélération.

Remarque:Lorsqu'un appareil est au repos, la sortie du capteur de gravité doit être identique à celle de l'accéléromètre.

Utiliser l'accéléromètre linéaire

Le capteur d'accélération linéaire fournit un vecteur tridimensionnel représentant l'accélération le long de chaque axe de l'appareil, à l'exclusion de la gravité. Vous pouvez utiliser cette valeur pour effectuer la détection des gestes. La valeur peut également servir d'entrée à un système de navigation inertielle, qui utilise le mode de calcul à mort. Le code suivant vous montre comment obtenir une instance du capteur d'accélération linéaire par défaut:

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

Conceptuellement, ce capteur fournit des données d'accélération selon la relation suivante:

linear acceleration = acceleration - acceleration due to gravity

Vous l'utilisez généralement lorsque vous souhaitez obtenir des données d'accélération sans l'influence de la gravité. Par exemple, vous pouvez utiliser ce capteur pour connaître la vitesse de votre voiture. Le capteur d'accélération linéaire présente toujours un décalage, que vous devez supprimer. Pour ce faire, le plus simple est de créer une étape de calibrage dans votre application. Lors de l'étalonnage, vous pouvez demander à l'utilisateur de placer l'appareil sur une table, puis de lire les décalages pour les trois axes. Vous pouvez ensuite soustraire ce décalage des mesures directes du capteur d'accélération pour obtenir l'accélération linéaire réelle.

Le système de coordonnées du capteur est identique à celui utilisé par le capteur d'accélération, tout comme les unités de mesure (m/s2).

Utiliser le capteur à vecteur de rotation

Le vecteur de rotation représente l'orientation de l'appareil sous la forme d'un angle et d'un axe, dans lequel l'appareil a pivoté selon un angle Θ autour d'un axe (x, y ou z). Le code suivant vous montre comment obtenir une instance du capteur de vecteur de rotation par défaut:

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

Les trois éléments du vecteur de rotation sont exprimés comme suit:

x*sin(/2), y*sin(tests/2), z*sin(lake/2)

Où l'amplitude du vecteur de rotation est égale à sin(theme/2) et le sens du vecteur de rotation est égal au sens de l'axe de rotation.

Figure 1 : Système de coordonnées utilisé par le capteur de vecteur de rotation.

Les trois éléments du vecteur de rotation sont égaux aux trois dernières composantes d'un quaternion unitaire (cos(View/2), x*sin(basées/2), y*sin(achevé/2), z*sin(identifiant ). Les éléments du vecteur de rotation sont sans unité. Les axes x, y et z sont définis de la même manière que le capteur d'accélération. Le système de coordonnées de référence est défini comme une base orthonormale directe (voir la figure 1). Ce système de coordonnées présente les caractéristiques suivantes:

  • X est défini comme le produit vectoriel Y x Z. Elle est tangentielle au sol à l'emplacement actuel de l'appareil et pointe approximativement à l'est.
  • Y est tangentielle au sol à l'emplacement actuel de l'appareil et pointe vers le pôle Nord géomagnétique.
  • L'axe Z est perpendiculaire au ciel et au sol.

Pour obtenir un exemple d'application montrant comment utiliser le capteur de vecteur de rotation, consultez le fichier RotationVectorDemo.java.

Utiliser le capteur de mouvement significatif

Le capteur de mouvement significatif déclenche un événement chaque fois qu'un mouvement important est détecté, puis se désactive lui-même. Un mouvement important est un mouvement qui peut entraîner un changement de position de l'utilisateur (à pied, à vélo ou assis dans une voiture en mouvement, par exemple). Le code suivant vous montre comment obtenir une instance du capteur de mouvement important par défaut et comment enregistrer un écouteur d'événements:

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

Pour en savoir plus, consultez TriggerEventListener.

Utiliser le capteur du compteur de pas

Le capteur du compteur de pas indique le nombre de pas effectués par l'utilisateur depuis le dernier redémarrage alors qu'il était activé. Le compteur de pas a plus de latence (jusqu'à 10 secondes), mais plus de précision que le capteur du détecteur de pas.

Remarque : Vous devez déclarer l'autorisation ACTIVITY_RECOGNITION pour que votre application puisse utiliser ce capteur sur les appareils équipés d'Android 10 (niveau d'API 29) ou version ultérieure.

Le code suivant vous montre comment obtenir une instance du capteur de compteur de pas par défaut:

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

Pour préserver la batterie des appareils exécutant votre application, vous devez utiliser la classe JobScheduler pour récupérer la valeur actuelle du capteur de compteur de pas à un intervalle spécifique. Bien que les différents types d'applications nécessitent des intervalles de lecture du capteur différents, vous devez définir cet intervalle le plus long possible, sauf si votre application a besoin de données en temps réel du capteur.

Utiliser le capteur de détection de pas

Le capteur du détecteur de pas déclenche un événement chaque fois que l'utilisateur fait un pas. La latence devrait être inférieure à deux secondes.

Remarque : Vous devez déclarer l'autorisation ACTIVITY_RECOGNITION pour que votre application puisse utiliser ce capteur sur les appareils équipés d'Android 10 (niveau d'API 29) ou version ultérieure.

Le code suivant vous montre comment obtenir une instance du capteur de détecteur de pas par défaut:

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

Travailler avec des données brutes

Les capteurs suivants fournissent à votre application des données brutes sur les forces linéaires et rotationnelles appliquées à l'appareil. Pour utiliser efficacement les valeurs de ces capteurs, vous devez filtrer les facteurs de l'environnement, tels que la gravité. Vous devrez peut-être également appliquer un algorithme de lissage à la tendance des valeurs afin de réduire le bruit.

Utiliser l'accéléromètre

Un capteur d'accélération mesure l'accélération appliquée à l'appareil, y compris la force de gravité. Le code suivant vous montre comment obtenir une instance du capteur d'accélération par défaut:

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

Remarque : Si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, ce capteur est limité en débit.

Conceptuellement, un capteur d'accélération détermine l'accélération appliquée à un appareil (Ad) en mesurant les forces appliquées au capteur lui-même (Fs) à l'aide de la relation suivante:

A_D=-(1/masse)∑F_S

Cependant, la force de gravité influence toujours l'accélération mesurée selon la relation suivante:

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

Pour cette raison, lorsque l'appareil est posé sur une table (et n'accélère pas), l'accéléromètre lit une magnitude de g = 9,81 m/s2. De même, lorsque l'appareil est en chute libre et s'accélère donc rapidement vers le sol à 9,81 m/s2, son accéléromètre affiche une magnitude de g = 0 m/s2. Par conséquent, pour mesurer l'accélération réelle de l'appareil, la contribution de la force de gravité doit être supprimée des données de l'accéléromètre. Pour ce faire, vous pouvez appliquer un filtre passe-haut. À l'inverse, un filtre passe-bas peut être utilisé pour isoler la force de gravité. L'exemple suivant montre comment procéder:

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];
}

Remarque:Vous pouvez utiliser de nombreuses techniques différentes pour filtrer les données des capteurs. L'exemple de code ci-dessus utilise une constante de filtre simple (alpha) pour créer un filtre passe-bas. Cette constante de filtre est dérivée d'une constante de temps (t), qui est une représentation approximative de la latence que le filtre ajoute aux événements de capteur, et du taux de diffusion des événements (dt) du capteur. L'exemple de code utilise une valeur alpha de 0,8 à des fins de démonstration. Si vous utilisez cette méthode de filtrage, vous devrez peut-être choisir une autre valeur alpha.

Les accéléromètres utilisent le système de coordonnées standard des capteurs. En pratique, cela signifie que les conditions suivantes s'appliquent lorsqu'un appareil est posé à plat sur une table dans son orientation naturelle:

  • Si vous poussez l'appareil sur le côté gauche (pour qu'il se déplace vers la droite), la valeur d'accélération X est positive.
  • Si vous poussez l'appareil vers le bas (afin qu'il s'éloigne de vous), la valeur d'accélération y est positive.
  • Si vous poussez l'appareil vers le ciel avec une accélération de A m/s2, cette accélération sera égale à A + 9,81, ce qui correspond à l'accélération de l'appareil (+ A m/s2) moins la force de gravité (-9,81 m/s2).
  • L'appareil fixe aura une valeur d'accélération de +9,81, ce qui correspond à l'accélération de l'appareil (0 m/s2 moins la force de gravité, soit -9,81 m/s2).

En général, l'accéléromètre est un bon capteur pour surveiller les mouvements de l'appareil. Presque tous les téléphones et tablettes Android sont équipés d'un accéléromètre et utilisent environ 10 fois moins d'énergie que les autres capteurs de mouvement. L'un des inconvénients est que vous devrez peut-être implémenter des filtres passe-bas et passe-haut pour éliminer les forces gravitationnelles et réduire le bruit.

Utiliser le gyroscope

Le gyroscope mesure la vitesse de rotation en rad/s autour des axes x, y et z d'un appareil. Le code suivant vous montre comment obtenir une instance du gyroscope par défaut:

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

Remarque : Si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, ce capteur est limité en débit.

Le système de coordonnées du capteur est identique à celui utilisé pour le capteur d'accélération. La rotation est positive dans le sens inverse des aiguilles d'une montre. En d'autres termes, un observateur regardant depuis un point positif sur l'axe x, y ou z à un appareil positionné à l'origine enregistrerait une rotation positive si l'appareil semblait tourner dans le sens inverse des aiguilles d'une montre. Il s'agit de la définition mathématique standard de la rotation positive. Elle est différente de la définition du roulis utilisée par le capteur d'orientation.

En règle générale, la sortie du gyroscope est intégrée au fil du temps pour calculer une rotation décrivant le changement d'angles au fil du temps. Par exemple :

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

Les gyroscopes standards fournissent des données de rotation brutes sans aucun filtrage ni correction du bruit et de la dérive (biais). En pratique, le bruit et la dérive du gyroscope engendrent des erreurs qui doivent être compensées. En général, vous déterminez la dérive (biais) et le bruit en surveillant d'autres capteurs, tels que le capteur de gravité ou l'accéléromètre.

Utiliser le gyroscope non calibré

Le gyroscope non calibré est semblable au gyroscope, sauf qu'aucune compensation de dérive gyroscope n'est appliquée au taux de rotation. Le calibrage d'usine et la compensation de température sont toujours appliqués à la vitesse de rotation. Le gyroscope non calibré est utile pour le post-traitement et la fusion des données d'orientation. En général, gyroscope_event.values[0] est proche de uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Autrement dit,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Remarque:Les capteurs non calibrés fournissent des résultats plus bruts et peuvent inclure des biais, mais leurs mesures contiennent moins de sauts liés aux corrections appliquées par calibrage. Certaines applications peuvent préférer que ces résultats non calibrés soient plus fluides et plus fiables. Par exemple, si une application tente de fusionner ses propres capteurs, l'introduction de calibrages peut fausser les résultats.

En plus des vitesses de rotation, le gyroscope non calibré fournit également la dérive estimée autour de chaque axe. Le code suivant vous montre comment obtenir une instance du gyroscope non calibré par défaut:

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

Autres exemples de code

L'exemple BatchStepSensor présente davantage l'utilisation des API abordées sur cette page.

Vous devriez également lire