La plate-forme Android fournit plusieurs capteurs qui vous permettent de surveiller le mouvement d'un appareil.
Les architectures possibles des capteurs varient selon le 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 basés sur du matériel ou sur des logiciels.
- Les capteurs d'accéléromètre et de gyroscope sont toujours basés sur du matériel.
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 dériver 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 l'oscillation. 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 référentiel de l'appareil ou du référentiel de votre application. Dans le second cas, vous surveillez le mouvement par rapport au référentiel 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 référentiel mondial (pour en savoir plus, consultez la section Capteurs de position).
Tous les capteurs de mouvement renvoient des tableaux multidimensionnels de valeurs de capteur pour chaque SensorEvent
. Par exemple, lors d'un seul événement de capteur, 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.
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 de 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 estimée du biais. | ||
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 estimée du biais. | ||
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] |
Vitesse 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/b |
SensorEvent.values[1] |
Vitesse de rotation (sans compensation de dérive) autour de l'axe Y. | ||
SensorEvent.values[2] |
Vitesse de rotation (sans compensation de dérive) autour de l'axe Z. | ||
SensorEvent.values[3] |
Déviation 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 sur l'axe X (sans la gravité). | m/s2 |
SensorEvent.values[1] |
Force d'accélération le long de l'axe Y (sans la gravité). | ||
SensorEvent.values[2] |
Force d'accélération le long de l'axe Z (sans gravité). | ||
TYPE_ROTATION_VECTOR |
SensorEvent.values[0] |
Composante du vecteur de rotation le long de l'axe X (x * sin(θ/2)). | Sans unité |
SensorEvent.values[1] |
Composante du vecteur de rotation le long de l'axe Y (y * sin(θ/2)). | ||
SensorEvent.values[2] |
Composante du vecteur de rotation le long de l'axe z (z * sin(raffinées)). | ||
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 à 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 de 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 de vecteur de rotation est idéal si vous développez un jeu, une application de réalité augmentée, une boussole en deux dimensions ou en trois dimensions, ou une application de stabilisation de l'appareil photo. Dans la plupart des cas, l'utilisation de ces capteurs est préférable à 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 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 essayer 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). Il est nécessaire d'identifier ces capteurs par fournisseur et 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 comme un capteur de gravité secondaire. Ces trois capteurs reposent sur un gyroscope: si un appareil ne dispose pas de gyroscope, 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 permet de 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 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 la détection de gestes. La valeur peut également servir d'entrée à un système de navigation inertielle, qui utilise le calcul de position par 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 possède toujours un décalage que vous devez supprimer. Le moyen le plus simple de procéder est d'intégrer une étape de calibrage à votre application. Lors du calibrage, 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 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 sous la forme d'une combinaison d'un angle et d'un axe, dans lequel l'appareil a pivoté d'un angle θ autour d'un axe (x, y ou z). Le code suivant 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.
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 n'ont pas d'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 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. Il est tangent au sol à l'emplacement actuel de l'appareil et pointe approximativement 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 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 il s'arrête. Un mouvement important est un mouvement qui peut entraîner un changement de l'emplacement de l'utilisateur (par exemple, en marchant, à vélo ou 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 de podomètre indique le nombre de pas effectués par l'utilisateur depuis le dernier redémarrage lorsque le capteur était activé. Le compteur de pas présente une latence plus élevée (jusqu'à 10 secondes), mais une précision supérieure à celle du 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 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 podomètre à 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 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 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 rotatives appliquées à l'appareil. Pour utiliser efficacement les valeurs de ces capteurs, vous devez filtrer les facteurs de l'environnement, comme la gravité. Vous devrez peut-être également appliquer un algorithme d'atténuation à 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 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:
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 qu'il 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 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 temporelle (t), qui est une représentation approximative de la latence que le filtre ajoute aux événements du capteur et du débit de diffusion d'é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 vers la gauche (pour le déplacer vers la droite), la valeur d'accélération x est positive.
- Si vous poussez l'appareil en 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 règle générale, 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 et consomment environ 10 fois moins d'énergie que les autres capteurs de mouvement. L'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 le taux de rotation en rad/s autour des axes x, y et z d'un appareil. Le code suivant 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 débit.
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. Autrement dit, un observateur regardant depuis un point positif sur les axes X, Y ou Z un appareil positionné à l'origine indiquera 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 n'est pas la même que la définition 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 l'évolution des angles au cours de l'intervalle 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 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 étalonné
Le gyroscope non étalonné est semblable au gyroscope, à la différence qu'aucune compensation de dérive du gyroscope n'est appliquée à la vitesse de rotation. Le calibrage d'usine et la compensation de température sont toujours appliqués à la vitesse de rotation. Le gyroscope non étalonné 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]
.
C'est-à-dire,
calibrated_x ~= uncalibrated_x - bias_estimate_x
Remarque:Les capteurs non étalonnés fournissent des résultats plus bruts et peuvent inclure un biais, mais leurs mesures contiennent moins de sauts dus aux corrections appliquées lors de l'étalonnage. 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 de calibrages peut en fait fausser les résultats.
En plus des vitesses de rotation, le gyroscope non étalonné fournit également la dérive estimée autour de chaque axe. Le code suivant montre comment obtenir une instance du gyroscope non étalonné 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.