Capteurs de mouvement

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

Les capteurs les architectures possibles varient selon le type de capteur:

  • Gravité, accélération linéaire, vecteur de rotation, mouvement significatif, pas les capteurs de compteur et de détecteur de pas sont soit matériels, soit basée sur les logiciels.
  • Les capteurs de l'accéléromètre et du gyroscope sont toujours matériels.

La plupart des appareils Android sont équipés d'un accéléromètre et nombre d'entre eux incluent désormais le gyroscope. Les capteurs logiciels sont plus disponibles car elles reposent souvent sur un ou plusieurs capteurs matériels données. Selon l'appareil, ces capteurs logiciels provenant 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, comme l'inclinaison, le tremblement, la rotation ou swing. Le mouvement est généralement le reflet d’une entrée utilisateur directe (par exemple, un utilisateur pilotant un une voiture dans un jeu ou un utilisateur qui contrôle un ballon dans un jeu), mais cela peut aussi refléter environnement physique dans lequel l'appareil est posé (par exemple, en se déplaçant 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 le cadre de référence de votre application ; Dans le second cas, vous surveillez le mouvement le cadre de référence mondial. Les capteurs de mouvement eux-mêmes 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, comme 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 la section Capteurs de position pour en savoir plus) informations).

Tous les capteurs de mouvement renvoient des tableaux multidimensionnels de valeurs de capteurs pour chaque SensorEvent. Par exemple, si un seul événement de capteur est détecté, l'accéléromètre renvoie les données sur la force d'accélération pour les trois axes de coordonnées et le taux de rotation du gyroscope pour les trois axes de coordonnées. Ces valeurs de données sont renvoyées dans un tableau float (values) et d'autres SensorEvent paramètres. 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énements 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 du biais. m/s2
SensorEvent.values[1] Accélération mesurée sur l'axe Y sans compensation du biais.
SensorEvent.values[2] Accélération mesurée sur l'axe Z sans compensation du biais.
SensorEvent.values[3] Accélération mesurée sur l'axe X avec compensation de biais estimée.
SensorEvent.values[4] Accélération mesurée sur l'axe Y avec compensation estimée du biais.
SensorEvent.values[5] Accélération mesurée sur l'axe Z avec compensation de biais estimée.
TYPE_GRAVITY SensorEvent.values[0] Force de gravité le long de l'axe des abscisses. 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 (hors gravité). m/s2
SensorEvent.values[1] Force d'accélération le long de l'axe Y (hors gravité).
SensorEvent.values[2] Force d'accélération le long de l'axe Z (hors gravité).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Composante du vecteur de rotation le long de l'axe des x (x * sin(raffinées)). Sans unité
SensorEvent.values[1] Composante du vecteur de rotation le long de l'axe y (y * sin(who/2)).
SensorEvent.values[2] Composante du vecteur de rotation le long de l'axe z (z * sin(Percentage/2)).
SensorEvent.values[3] Composante scalaire du vecteur de rotation ((cos(who/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 a été activé. Étapes
TYPE_STEP_DETECTOR N/A N/A N/A

1 Le composant scalaire est une valeur facultative.

Le capteur à vecteur de rotation et le capteur de gravité sont les capteurs de mouvement les plus fréquemment utilisés. la détection et la surveillance. Le capteur à vecteur de rotation est particulièrement polyvalent et peut être utilisé pour un large éventail de tâches liées aux mouvements, comme la détection de gestes, la surveillance des changements angulaires et pour surveiller les changements d'orientation relatives. Par exemple, le capteur à vecteur de rotation est idéal développent un jeu, une application de réalité augmentée, une boussole bidimensionnelle ou tridimensionnelle, ou une appli de stabilisation de l'appareil photo. Dans la plupart des cas, il est préférable d'utiliser ces capteurs 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 basés sur un logiciel: la gravité un capteur d'accélération linéaire et un capteur à vecteur de rotation. Ces capteurs ont été mis à jour en Android 4.0 et utilisent désormais le gyroscope de l'appareil (en plus d'autres capteurs) pour améliorer la stabilité et des performances. Si vous souhaitez tester ces capteurs, vous pouvez les identifier à l'aide des méthodes getVendor() et getVersion(). (le fournisseur est Google LLC et le numéro de version est 3). Identifier ces capteurs par fournisseur et le numéro de version est nécessaire, car le système Android considère ces trois capteurs comme secondaires. capteurs. Par exemple, si un fabricant d'appareils fournit son propre capteur de gravité, l'AOSP le capteur de gravité apparaît comme un capteur de gravité secondaire. Ces trois capteurs reposent sur un système gyroscope: si un appareil n'est pas équipé d'un gyroscope, ces capteurs ne sont pas visibles et ne sont pas disponibles.

Utiliser le capteur de gravité

Le capteur de gravité fournit un vecteur tridimensionnel indiquant la direction et l'amplitude de la gravité. Généralement, ce capteur sert à 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 l'accélération (m/s2), et le système de coordonnées est le même que celui utilisé par la du 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 indique un vecteur tridimensionnel représentant l'accélération le long de l'axe de chaque appareil, à l'exception de la gravité. Vous pouvez utiliser cette valeur pour effectuer une détection des gestes. Cette valeur peut également servir d'entrée pour système de navigation inertial, qui utilise le jugement mort. Le code suivant 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 conformes à ce qui suit : relation:

linear acceleration = acceleration - acceleration due to gravity

Ce capteur est généralement utilisé pour obtenir des données d'accélération sans l'influence la gravité. Par exemple, vous pouvez utiliser ce capteur pour connaître la vitesse de votre voiture. Le modèle linéaire le capteur d'accélération comporte toujours un décalage que vous devez supprimer. Le moyen le plus simple de le faire est pour intégrer une étape d'étalonnage à votre application. Pendant le calibrage, vous pouvez demander à l'utilisateur de définir l'appareil sur une table, puis lire les décalages pour les trois axes. Vous pouvez ensuite le soustraire par rapport aux relevés directs du capteur d'accélération pour obtenir la valeur linéaire réelle de l'accélération matérielle.

Les coordonnées du capteur système est identique à celle utilisée par le capteur d'accélération, de même que 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 de la combinaison d'un angle et d'un axe, dans lequel l'appareil a pivoté selon un angle Terraform autour d'un axe (x, y ou z). Les éléments suivants : vous montre comment obtenir une instance du capteur à 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(Percentage/2), y*sin(raffinées/2), z*sin(Learning)

où l'amplitude du vecteur de rotation est égale à sin(Learning) et la direction du vecteur de rotation est égal au sens de l'axe de rotation.

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

Les trois éléments du vecteur de rotation sont égaux aux trois derniers composants d'une unité quaternion (cos(who/2), x*sin( raffinées/ 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. La référence système de coordonnées est défini comme une base orthonormale directe (voir 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 tangente à la au sol à la position actuelle de l'appareil et pointe vers l'est.
  • Y est tangentiel par rapport au sol à l'emplacement actuel de l'appareil et pointe vers géomagnétique Pôle Nord.
  • Le Z pointe vers le ciel et est perpendiculaire au plan du sol.

Pour un exemple d'application montrant comment utiliser le capteur à vecteur de rotation, voir RotationVectorDemo.java.

Utiliser le capteur de mouvement significatif

Le capteur de mouvements significatifs déclenche un événement chaque fois qu'un mouvement important est détecté. puis il se désactive tout seul. Un mouvement important est un mouvement susceptible d'entraîner un changement dans l'emplacement de l'utilisateur ; par exemple marcher, faire du vélo ou être assis dans une voiture en mouvement. Le code suivant vous montre comment obtenir une instance du capteur de mouvement significatif par défaut et comment enregistrer un événement écouteur:

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 que le capteur était activé. Le compteur de pas a plus de latence (jusqu'à 10 secondes), mais plus que le capteur du détecteur de pas.

Remarque : Vous devez déclarer le ACTIVITY_RECOGNITION pour que votre appli puisse utiliser ce capteur sur les appareils Android 10 (niveau d'API 29) ou version ultérieure

Le code suivant vous montre comment obtenir une instance de l'étape par défaut compteur:

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 l'autonomie de la batterie des appareils qui exécutent votre application, vous devez utiliser la JobScheduler pour récupérer la valeur actuelle le capteur du compteur de pas à un intervalle spécifique. Bien que les différents types d'applications nécessitent différents intervalles de lecture par le capteur, définissez cet intervalle comme aussi longtemps que possible, sauf si votre application requiert des données en temps réel du capteur.

Utiliser le capteur du détecteur de pas

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

Remarque : Vous devez déclarer le ACTIVITY_RECOGNITION pour que votre appli puisse utiliser ce capteur sur les appareils Android 10 (niveau d'API 29) ou version ultérieure

Le code suivant vous montre comment obtenir une instance de l'étape par défaut capteur de sécurité:

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 concernant les métriques linéaires et des forces de rotation appliquées à l'appareil. Pour utiliser les valeurs ces capteurs efficacement, vous devez filtrer les facteurs de l'environnement, comme la gravité. Vous devrez peut-être aussi appliquer un algorithme de lissage à la tendance 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 des la 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 plus haut, 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 qui sont 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 d'après la relation suivante:

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

Pour cette raison, lorsque l'appareil est posé sur une table (sans accélération), l'accéléromètre mesure une magnitude de g = 9,81 m/s2. De même, lorsque l'appareil est en en chute libre et accélérant donc rapidement vers le sol à 9,81 m/s2, l'accéléromètre mesure 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é ne doit pas être prise en compte les données de l'accéléromètre. Pour ce faire, vous pouvez appliquer un filtre passe-haut. À l'inverse, un passage-bas peut être utilisé pour isoler la force de gravité. L'exemple suivant montre comment ceci:

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. Ce filtre est dérivée d'une constante de temps (t), qui est une représentation approximative de la latence le filtre s'ajoute aux événements du capteur, ainsi qu'à la fréquence de diffusion des événements (dt) du capteur. 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 pour choisir une autre valeur alpha.

Les accéléromètres utilisent les coordonnées du capteur standard du système d'exploitation. 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 le déplacer vers la droite), la valeur d'accélération x est positive.
  • Si vous poussez l'appareil vers le bas (pour qu'il s'éloigne de vous), la valeur d'accélération y est positif.
  • Si vous poussez l'appareil vers le ciel avec une accélération de A m/s2, la La valeur d'accélération de z est é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).
  • La valeur d'accélération de l'appareil fixe est 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 à utiliser si vous surveillez 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. Un inconvénient est que vous devrez peut-être mettre en œuvre les filtres passe-bas et passe-haut pour éliminer les forces gravitationnelles et réduire le bruit.

Utiliser le gyroscope

Le gyroscope mesure le taux de rotation en rad/s autour des points x, y, et z. 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 plus haut, ce capteur est limité en débit.

Le système de coordonnées du capteur est identique à celle utilisée pour le capteur d'accélération. La rotation est positive dans dans le sens inverse des aiguilles d'une montre. c'est-à-dire qu'un observateur regarde à partir d'une position positive sur l'axe X, Y ou Z d'un appareil positionné sur l'origine indiquerait une rotation positive si l'appareil semble tourner dans le sens inverse des aiguilles d'une montre. Il s'agit de la définition mathématique standard de rotation positive et n'est pas la même que la définition de utilisé par le capteur d'orientation.

En général, la sortie du gyroscope est intégrée au fil du temps pour calculer une rotation décrivant le changement d'angle au fil du temps. 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 filtrage ni correction du bruit et dérive (biais). En pratique, le bruit et la dérive du gyroscope introduisent des erreurs qui doivent être dédommagé. Vous déterminez généralement la dérive (biais) et le bruit en surveillant d'autres capteurs, tels que comme le capteur de gravité ou l'accéléromètre.

Utiliser le gyroscope non calibré

Le gyroscope non calibré ressemble au gyroscope, sauf qu'aucune compensation de dérive de gyroscope n'est appliquée à la vitesse de rotation. Étalonnage en usine et la compensation de température sont toujours appliquées à la vitesse de rotation. Les données non calibrées le gyroscope est utile pour le post-traitement et la fusion des données d'orientation. En général, gyroscope_event.values[0] sera proche de uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] En d'autres termes,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Remarque:Les capteurs non calibrés fournissent des résultats plus bruts et peuvent incluent un certain biais, mais leurs mesures contiennent moins de sauts provenant des corrections appliquées un étalonnage. Certaines applications peuvent préférer que les résultats non calibrés soient plus fluides et plus fluides fiables. Par exemple, si une application tente de réaliser sa propre fusion de capteurs, l'introduction de calibrages peut en fait fausser les résultats.

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

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

La L'exemple BatchStepSensor) montre davantage l'utilisation des API abordées sur cette page.

Vous pouvez également lire