La plate-forme Android fournit plusieurs capteurs qui vous permettent de surveiller le mouvement d'un appareil.
Les architectures possibles des capteurs varient en fonction du type de capteur :
- Les capteurs de gravité, d'accélération linéaire, de vecteur de rotation, de mouvement significatif, de compteur de pas et de détecteur de pas sont matériels ou logiciels.
- Les capteurs d'accéléromètre et de gyroscope sont toujours matériels.
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, les secousses, la rotation ou le balancement. Le mouvement est généralement le reflet d'une saisie directe de l'utilisateur (par exemple, un utilisateur qui dirige une voiture dans un jeu ou qui contrôle une balle dans un jeu), mais il peut également refléter l'environnement physique dans lequel l'appareil se trouve (par exemple, se déplacer avec vous lorsque vous conduisez votre voiture). Dans le premier cas, vous surveillez le mouvement par rapport au cadre de référence de l'appareil ou de votre application. Dans le second cas, vous surveillez le mouvement par rapport au cadre de référence du monde. Les capteurs de mouvement ne sont généralement pas utilisés seuls 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 du monde (pour en savoir plus, consultez Capteurs de position).
Tous les capteurs de mouvement renvoient des tableaux multidimensionnels de valeurs de capteur pour chaque SensorEvent
. Par exemple, lors d'un événement de capteur unique, l'accéléromètre renvoie des données de force d'accélération pour les trois axes de coordonnées, et le gyroscope renvoie des données de vitesse de rotation pour les 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énements de capteur | 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 compensation du biais estimée. | ||
SensorEvent.values[4] |
Accélération mesurée le long de l'axe Y avec compensation du biais estimé. | ||
SensorEvent.values[5] |
Accélération mesurée le long de l'axe Z avec compensation du biais estimée. | ||
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] |
Vitesse de rotation autour de l'axe Y. | ||
SensorEvent.values[2] |
Vitesse 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 (sans la gravité). | m/s2 |
SensorEvent.values[1] |
Force d'accélération le long de l'axe Y (gravité exclue). | ||
SensorEvent.values[2] |
Force d'accélération le long de l'axe Z (hors gravité). | ||
TYPE_ROTATION_VECTOR |
SensorEvent.values[0] |
Composant du vecteur de rotation le long de l'axe X (x * sin(θ/2)). | Sans unité |
SensorEvent.values[1] |
Composant du vecteur de rotation le long de l'axe Y (y * sin(θ/2)). | ||
SensorEvent.values[2] |
Composant du vecteur de rotation le long de l'axe z (z * sin(θ/2)). | ||
SensorEvent.values[3] |
Composante scalaire du vecteur de rotation (cos(θ/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 du mouvement. Le capteur de vecteur de rotation est particulièrement polyvalent et peut être utilisé pour un large éventail de tâches liées au mouvement, comme la détection de gestes, la surveillance des changements d'angle et la surveillance des changements d'orientation relative. Par exemple, le capteur de 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 de l'appareil photo. Dans la plupart des cas, l'utilisation de ces capteurs est un meilleur choix que l'utilisation de l'accéléromètre et du capteur de champ géomagnétique ou du capteur d'orientation.
Capteurs du 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 de 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 essayer 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). Il est nécessaire d'identifier ces capteurs par fournisseur et par 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 s'affiche en tant que capteur de gravité secondaire. Ces trois capteurs reposent sur un gyroscope. Si un appareil n'en possède pas, ces capteurs ne s'affichent pas et ne sont pas disponibles.
Utiliser le capteur de gravité
Le capteur de gravité fournit un vecteur tridimensionnel indiquant la direction et la magnitude 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 le même que 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 vous fournit un vecteur tridimensionnel représentant l'accélération le long de chaque axe de l'appareil, en excluant la gravité. Vous pouvez utiliser cette valeur pour effectuer la détection de gestes. Cette valeur peut également servir d'entrée à un système de navigation inertielle, qui utilise l'estimation à l'estime. 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 vous fournit des données d'accélération selon la relation suivante :
linear acceleration = acceleration - acceleration due to gravity
Vous utilisez généralement ce capteur 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 a toujours un décalage que vous devez supprimer. Le moyen le plus simple de procéder est d'intégrer une étape de calibration à votre application. Lors de la calibration, vous pouvez demander à l'utilisateur de poser l'appareil sur une table, puis de lire les décalages pour les trois axes. Vous pouvez ensuite soustraire ce décalage des lectures 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 le même que celui utilisé par le capteur d'accélération, tout comme les unités de mesure (m/s2).
Utiliser le capteur de vecteur de rotation
Le vecteur de rotation représente l'orientation de l'appareil comme une combinaison d'un angle et d'un axe, dans laquelle l'appareil a pivoté d'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 :

Où la magnitude du vecteur de rotation est égale à sin(θ/2) et la direction du vecteur de rotation est égale à la direction 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 derniers composants d'un quaternion unitaire (cos(θ/2), x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)). 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 orthonormée 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 tangente au sol à l'emplacement actuel de l'appareil et pointe approximativement vers l'est.
- Y est tangent au sol à l'emplacement actuel de l'appareil et pointe vers le pôle Nord géomagnétique.
- L'axe Z pointe vers le ciel et est perpendiculaire au plan du sol.
Pour obtenir un exemple d'application montrant comment utiliser le capteur de vecteur de rotation, consultez RotationVectorDemo.java.
Utiliser le capteur de mouvement important
Le capteur de mouvement important déclenche un événement chaque fois qu'un mouvement important est détecté, puis se désactive. Un mouvement important est un mouvement qui peut entraîner un changement de position 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 écouteur d'événement :
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 de compteur de pas
Le capteur de compteur de pas fournit le nombre de pas effectués par l'utilisateur depuis le dernier redémarrage, lorsque le capteur était activé. Le compteur de pas a une latence plus élevée (jusqu'à 10 secondes), mais il est plus précis que le capteur de détection 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 différents types d'applications nécessitent des intervalles de lecture de capteur différents, vous devez rendre cet intervalle aussi long que possible, sauf si votre application nécessite des données en temps réel du capteur.
Utiliser le capteur de détecteur de pas
Le capteur de détection de pas déclenche un événement chaque fois que l'utilisateur fait un pas. La latence doit ê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);
Utiliser des données brutes
Les capteurs suivants fournissent à votre application des données brutes sur les forces linéaires et de rotation appliquées à l'appareil. Pour utiliser efficacement les valeurs de ces capteurs, vous devez filtrer les facteurs environnementaux, tels que la gravité. Vous devrez peut-être également appliquer un algorithme de lissage à la tendance des valeurs pour 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 version ultérieure, ce capteur est limité en fréquence.
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 :

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

C'est pourquoi, lorsque l'appareil est posé sur une table (et n'accélère pas), l'accéléromètre indique une magnitude de g = 9,81 m/s2. De même, lorsque l'appareil est en chute libre et qu'il accélère donc rapidement vers le sol à 9,81 m/s2, son accéléromètre indique 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 du capteur, et du taux de distribution des événements du capteur (dt). 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 (pour l'éloigner 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, la valeur de l'accélération 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).
- L'appareil immobile 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é, qui est de -9,81 m/s2).
En général, l'accéléromètre est un bon capteur à utiliser si vous surveillez le mouvement de l'appareil. Presque tous les téléphones et tablettes Android sont équipés d'un accéléromètre, qui consomme environ 10 fois moins d'énergie que les autres capteurs de mouvement. Un inconvénient 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 version ultérieure, ce capteur est limité en fréquence.
Le système de coordonnées du capteur est le même que 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 un appareil positionné à l'origine depuis un emplacement positif sur l'axe X, Y ou Z indiquerait 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, qui n'est pas la même que celle du roulis utilisée 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 la variation des angles au cours du pas de 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 aucun filtrage ni correction du bruit et de la dérive (biais). En pratique, le bruit et la dérive du gyroscope introduisent des erreurs qui doivent être compensées. Vous déterminez généralement 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 la dérive gyroscopique n'est appliquée à la vitesse de rotation. L'étalonnage en usine et la compensation de température sont toujours appliqués au taux 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 un certain biais, mais leurs mesures contiennent moins de sauts dus aux corrections appliquées lors de la calibration. Certaines applications peuvent préférer ces résultats non calibrés, car ils sont plus fluides et plus fiables. Par exemple, si une application tente d'effectuer sa propre fusion de capteurs, l'introduction de calibrages peut en fait fausser les résultats.
En plus des taux de rotation, le gyroscope non calibré fournit également une estimation de la dérive 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 illustre davantage l'utilisation des API abordées sur cette page.