La plate-forme Android fournit plusieurs capteurs qui vous permettent de surveiller les mouvements 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étecteurs de pas sont soit matériels, soit 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 un gyroscope. La disponibilité des capteurs logiciels est plus variable, car ils reposent souvent sur un ou plusieurs capteurs matériels pour extraire leurs données. Selon l'appareil, ces capteurs logiciels peuvent extraire leurs données 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 mouvement. Le mouvement est généralement le reflet d'une entrée utilisateur directe (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 s'agir de l'environnement physique dans lequel l'appareil est assis (par exemple, se déplacer 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 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, 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 événement de capteur unique, l'accéléromètre renvoie des données sur les forces d'accélération pour les trois axes de coordonnées, et le gyroscope renvoie le taux de données 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 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 sur 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/b |
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/b |
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 était 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 les plus utilisés pour la détection et la surveillance des mouvements. Le capteur vectoriel 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 relatives. 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 en deux ou trois dimensions, ou une application de stabilisation de l'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 basés sur un logiciel: un capteur de gravité, un capteur d'accélération linéaire et un capteur à vecteur de rotation. Ces capteurs ont été mis à jour sous 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, le numéro de version est 3). L'identification de ces capteurs par fournisseur et par numéro de version est nécessaire, 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 AOSP se présente alors en tant que capteur de gravité secondaire. Ces trois capteurs dépendent d'un gyroscope: si un appareil n'en est pas équipé, ces capteurs ne sont pas visibles 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 permet de déterminer l'orientation relative de l'appareil dans l'espace. Le code suivant 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 fournit 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 de gestes. Cette valeur peut également servir d'entrée à un 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 en fonction de 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 possède toujours un décalage que vous devez supprimer. Pour ce faire, le moyen le plus simple consiste à intégrer une étape de calibration 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 des 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, 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é d'un angle RH autour d'un axe (x, y ou z). Le code suivant montre comment obtenir une instance du capteur vectoriel 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)](https://developer.android.com/static/images/guide/topics/sensors/rotational_vec.png?authuser=5&hl=fr)
où l'amplitude du vecteur de rotation est égale à sin(Learning) et où la direction du vecteur de rotation est égale à la direction de l'axe de rotation.
![](https://developer.android.com/static/images/axis_globe.png?authuser=5&hl=fr)
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 dernières composantes d'un quaternion unitaire (cos( Learning) 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 tangente au sol à l'emplacement actuel de l'appareil et pointe vers l'est.
- Y est tangentiel par rapport au sol à l'emplacement actuel de l'appareil et pointe vers le pôle Nord géomagnétique.
- Le Z pointe vers le ciel et est perpendiculaire au plan du sol.
Pour obtenir un exemple d'application montrant comment utiliser le capteur à vecteur de rotation, consultez RotationVectorDemo.java.
Utiliser le capteur de mouvement significatif
Le capteur de mouvement significatif déclenche un événement chaque fois qu'un mouvement significatif est détecté, puis se désactive automatiquement. Un mouvement important est un mouvement qui peut entraîner un changement de l'emplacement de l'utilisateur (par exemple, marcher, faire du vélo ou être assis dans une voiture en mouvement). Le code suivant montre comment obtenir une instance du capteur de mouvement significatif 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 après activation du capteur. Le compteur de pas a une latence plus importante (jusqu'à 10 secondes), mais une plus grande 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 l'autonomie de la batterie sur les appareils exécutant votre application, vous devez utiliser la classe JobScheduler
afin de récupérer la valeur actuelle du capteur du compteur de pas à un intervalle spécifique. Bien que les différents types d'applications nécessitent des intervalles de mesure différents, vous devez définir cet intervalle le plus longtemps possible, sauf si votre application nécessite 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 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 montre comment obtenir une instance du capteur de détection 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 exclure des 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 qui sont appliquées au capteur lui-même (Fs) à l'aide de la relation suivante:
![A_D=-(1/masse)ΨF_S](https://developer.android.com/static/images/guide/topics/sensors/acceleration.png?authuser=5&hl=fr)
Cependant, la force de gravité influence toujours l'accélération mesurée selon la relation suivante:
![A_D=-g-(1/masse)ΨF_S](https://developer.android.com/static/images/guide/topics/sensors/acceleration_with_grav.png?authuser=5&hl=fr)
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 chute libre et accélère donc rapidement vers le sol à 9,81 m/s2, son 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é 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 de la fréquence de diffusion 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. 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 vers la gauche (pour le déplacer vers la droite), la valeur d'accélération X est positive.
- Si vous poussez l'appareil par le bas (pour 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, la valeur d'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).
- 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é, qui est de -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 consomment environ 10 fois moins d'énergie que les autres capteurs de mouvement. L'un des inconvénients est que vous devrez peut-être mettre en œuvre des 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 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 à partir d'un emplacement positif sur l'axe x, y ou z 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 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'angle 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 rotation brutes sans filtrage ni correction du bruit et des dérives (biais). En pratique, le bruit et la dérive du gyroscope entraînent des erreurs qui doivent faire l'objet d'une compensation. 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 du gyroscope n'est appliquée au taux de rotation. Le calibrage en 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]
.
En d'autres termes,
calibrated_x ~= uncalibrated_x - bias_estimate_x
Remarque:Les capteurs non calibrés fournissent plus de résultats bruts et peuvent comporter un certain biais, mais leurs mesures contiennent moins de sauts causés par les 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 réaliser sa propre fusion de capteurs, l'introduction d'un étalonnage peut 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 de manière plus approfondie l'utilisation des API abordées sur cette page.