La plate-forme Android fournit deux capteurs qui vous permettent de déterminer la position d'un appareil: le capteur de champ géomagnétique et l'accéléromètre. Android est également dotée d'un capteur permettant de déterminer la distance entre un appareil et un objet (également appelé capteur de proximité). La le capteur de champ géomagnétique et le capteur de proximité sont matériels. La plupart les fabricants de téléphones et de tablettes incluent un capteur de champ géomagnétique. De même, les fabricants de téléphones portables proposent généralement un capteur de proximité pour déterminer le téléphone est tenu près du visage de l'utilisateur (lors d'un appel appel). Pour déterminer l'orientation d'un appareil, vous pouvez utiliser les mesures l'accéléromètre et le capteur de champ géomagnétique de l'appareil.
Remarque:Le capteur d'orientation a été abandonné dans Android 2.2. (niveau d'API 8), et le type de capteur d'orientation a été abandonné dans Android 4.4W (niveau d'API 20).
Les capteurs de position sont utiles pour déterminer la position physique d'un appareil le cadre de référence mondial. Par exemple, vous pouvez utiliser le champ géomagnétique capteur combiné à l'accéléromètre pour déterminer la position de l'appareil par rapport au pôle Nord magnétique. Vous pouvez également utiliser ces capteurs déterminer l'orientation d'un appareil dans le cadre de référence de votre application. En général, les capteurs de position ne sont pas utilisés pour surveiller le mouvement de l'appareil. par exemple en cas de tremblement, d'inclinaison ou de poussée. Pour en savoir plus, consultez l'article Capteurs de mouvement.
Le capteur de champ géomagnétique et l'accéléromètre renvoient des tableaux multidimensionnels
de valeurs de capteurs pour chaque SensorEvent
. Par exemple :
le capteur de champ géomagnétique fournit des valeurs d'intensité du champ géomagnétique pour
chacun des trois axes de coordonnées
lors d'un événement de capteur unique. De même,
de l'accéléromètre mesure l'accélération appliquée à l'appareil
événement du capteur. Pour en savoir plus sur les systèmes de coordonnées utilisés
par capteurs, voir la section
Systèmes de coordonnées des capteurs Le capteur de proximité fournit une valeur unique
pour chaque événement de capteur. Le tableau 1 récapitule les capteurs de position
compatibles avec la plate-forme Android.
Tableau 1. Capteurs de position compatibles avec la plate-forme Android
Capteur | Données d'événements des capteurs | Description | Unités de mesure |
---|---|---|---|
TYPE_GAME_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)). | ||
TYPE_GEOMAGNETIC_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)). | ||
TYPE_MAGNETIC_FIELD |
SensorEvent.values[0] |
Intensité du champ géomagnétique le long de l'axe X. | μT |
SensorEvent.values[1] |
Intensité du champ géomagnétique le long de l'axe Y. | ||
SensorEvent.values[2] |
Intensité du champ géomagnétique le long de l'axe Z. | ||
TYPE_MAGNETIC_FIELD_UNCALIBRATED |
SensorEvent.values[0] |
Intensité du champ géomagnétique (sans étalonnage du fer dur) le long de l'axe X. | μT |
SensorEvent.values[1] |
Intensité du champ géomagnétique (sans étalonnage du fer dur) le long de l'axe Y. | ||
SensorEvent.values[2] |
Intensité du champ géomagnétique (sans étalonnage du fer dur) le long de l'axe Z. | ||
SensorEvent.values[3] |
Estimation du biais du fer le long de l'axe des x. | ||
SensorEvent.values[4] |
Estimation du biais du fer le long de l'axe des ordonnées. | ||
SensorEvent.values[5] |
Estimation du biais du fer le long de l'axe Z. | ||
TYPE_ORIENTATION 1. |
SensorEvent.values[0] |
Azimut (angle autour de l'axe Z). | Degrés |
SensorEvent.values[1] |
Inclinaison (angle autour de l'axe X). | ||
SensorEvent.values[2] |
Roulis (angle autour de l'axe Y) | ||
TYPE_PROXIMITY |
SensorEvent.values[0] |
Distance par rapport à l'objet2. | cm |
1 Ce capteur a été abandonné dans Android 2.2 (API niveau 8), et ce type de capteur a été abandonné dans Android 4.4W (niveau d'API 20). Le framework du capteur offre d'autres méthodes pour acquérir des données de calcul, qui sont abordés dans la section l'orientation de l'appareil.
2 Certains capteurs de proximité ne fournissent que des valeurs binaires représentant les proches et les lointains.
Utiliser le capteur à vecteur de rotation du jeu
Le capteur du vecteur de rotation du jeu est identique au capteur Rotation capteur vectoriel, sauf qu'il n'utilise pas le champ géomagnétique. Par conséquent, l'axe Y vers le nord, mais à une autre référence. Cette référence peut varier même ordre de grandeur que le gyroscope dérive autour de l'axe Z.
Comme le capteur du vecteur de rotation du jeu n'utilise pas le champ magnétique, les rotations relatives sont plus précises et ne sont pas affectées par les changements du champ magnétique. Utilisez ce capteur dans un jeu si Peu importe l'endroit où se trouve le nord, et le vecteur de rotation normal n'est pas adapté à vos besoins en raison de sa dépendance au champ magnétique.
Le code suivant vous montre comment obtenir une instance du vecteur de rotation par défaut du jeu capteur:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
Utiliser le capteur à vecteur de rotation géomagnétique
Le capteur à vecteur de rotation géomagnétique est similaire capteur à vecteur de rotation, mais il n'utilise pas le gyroscope. La précision de ce capteur est inférieure au vecteur de rotation normale capteur, mais la consommation d'énergie est réduite. N'utilisez ce capteur que si vous souhaitez collecter la rotation en arrière-plan sans consommer trop de batterie. Ce capteur est particulièrement utile lorsqu'il est utilisé avec le traitement par lot.
Le code suivant montre comment obtenir une instance de la rotation géomagnétique par défaut capteur vectoriel:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
Calculer l'orientation de l'appareil
En calculant l'orientation d'un appareil, vous pouvez surveiller la position par rapport au cadre de référence de la Terre (plus précisément, (pôle Nord). Le code suivant vous montre comment calculer le score d'un appareil orientation:
Kotlin
private lateinit var sensorManager: SensorManager ... // Rotation matrix based on current readings from accelerometer and magnetometer. val rotationMatrix = FloatArray(9) SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading) // Express the updated rotation matrix as three orientation angles. val orientationAngles = FloatArray(3) SensorManager.getOrientation(rotationMatrix, orientationAngles)
Java
private SensorManager sensorManager; ... // Rotation matrix based on current readings from accelerometer and magnetometer. final float[] rotationMatrix = new float[9]; SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // Express the updated rotation matrix as three orientation angles. final float[] orientationAngles = new float[3]; SensorManager.getOrientation(rotationMatrix, orientationAngles);
Le système calcule les angles d'orientation à l'aide de la fonction géomagnétique d'un appareil capteur de champ utilisé conjointement avec l'accéléromètre de l'appareil. L'utilisation de ces deux capteurs matériels, le système fournit des données pour angles d'orientation:
- Azimut (degrés de rotation autour de l'axe -z). C'est l'angle entre la direction actuelle de la boussole et le nord magnétique. Si le bord supérieur de l'appareil est orienté vers le nord magnétique, l'azimut est de 0. diplômes ; si le bord supérieur est orienté vers le sud, l'azimut est de 180 degrés. De même, si le bord supérieur est orienté vers l'est, l'azimut est de 90 degrés, et si le bord supérieur orientée vers l'ouest, l'azimut est de 270 degrés.
- Inclinaison (degrés de rotation autour de l'axe X). Il s'agit de la angle entre un plan parallèle à l'écran de l'appareil et un plan parallèle au sol. Si vous tenez l'appareil parallèlement au sol, la partie inférieure bord le plus proche de vous et inclinez le bord supérieur de l'appareil vers le sol, l'angle d'inclinaison devient positif. Si vous inclinez dans la direction opposée— éloignez le bord supérieur de l'appareil du sol. l'angle d'inclinaison devient négatif. La plage de valeurs est de -90 degrés à 90 degrés.
- Roulis (degrés de rotation par rapport à l'axe Y) Il s'agit de la angle entre un plan perpendiculaire à l'écran de l'appareil et un plan perpendiculaire au sol. Si vous tenez l'appareil parallèlement au sol avec le bord inférieur le plus proche de vous et inclinez le bord gauche de l'appareil vers le sol, l'angle de roulis devient positif. Inclinaison inverse (en déplaçant le bord droit de l'appareil vers le sol) : l'angle de roulis devient négatif. La plage de valeurs est -180 degrés sur 180 degrés.
Remarque:La définition du mouvement du capteur a changé pour refléter pour la grande majorité des implémentations dans l'écosystème des géocapteurs.
Notez que ces angles fonctionnent à partir d'un système de coordonnées différent de celui l'une utilisée en aviation (pour le lacet, le tangage et le roulis). Dans le système aéronautique, L'axe des abscisses se situe le long du côté le plus long de l'avion, de la queue au nez.
Le capteur d'orientation extrait ses données en traitant les données brutes.
de l'accéléromètre et du capteur de champ géomagnétique. À cause du poids
du traitement impliqué, la précision et la précision de l'orientation
le capteur est diminué. Plus précisément, ce capteur n'est fiable que lorsque le mouvement
est égal à 0. Par conséquent, le capteur d'orientation a été abandonné dans Android
2.2 (niveau d'API 8), et le type de capteur d'orientation a été abandonné dans Android
4.4W (niveau d'API 20).
Au lieu d'utiliser les données brutes du capteur d'orientation,
utiliser l'getRotationMatrix()
en association avec
Méthode getOrientation()
pour calculer les valeurs d'orientation, comme illustré dans l'exemple de code suivant. Dans le cadre
de ce processus, vous pouvez utiliser
remapCoordinateSystem()
pour traduire les valeurs d'orientation dans le cadre de votre application
référence.
Kotlin
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private val accelerometerReading = FloatArray(3) private val magnetometerReading = FloatArray(3) private val rotationMatrix = FloatArray(9) private val orientationAngles = FloatArray(3) public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. // You must implement this callback in your code. } override fun onResume() { super.onResume() // Get updates from the accelerometer and magnetometer at a constant rate. // To make batch operations more efficient and reduce power consumption, // provide support for delaying updates to the application. // // In this example, the sensor reporting delay is small enough such that // the application receives an update before the system checks the sensor // readings again. sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer -> sensorManager.registerListener( this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField -> sensorManager.registerListener( this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } } override fun onPause() { super.onPause() // Don't receive any more updates from either sensor. sensorManager.unregisterListener(this) } // Get readings from accelerometer and magnetometer. To simplify calculations, // consider storing these readings as unit vectors. override fun onSensorChanged(event: SensorEvent) { if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size) } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size) } } // Compute the three orientation angles based on the most recent readings from // the device's accelerometer and magnetometer. fun updateOrientationAngles() { // Update rotation matrix, which is needed to update orientation angles. SensorManager.getRotationMatrix( rotationMatrix, null, accelerometerReading, magnetometerReading ) // "rotationMatrix" now has up-to-date information. SensorManager.getOrientation(rotationMatrix, orientationAngles) // "orientationAngles" now has up-to-date information. } }
Java
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private final float[] accelerometerReading = new float[3]; private final float[] magnetometerReading = new float[3]; private final float[] rotationMatrix = new float[9]; private final float[] orientationAngles = new float[3]; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. // You must implement this callback in your code. } @Override protected void onResume() { super.onResume(); // Get updates from the accelerometer and magnetometer at a constant rate. // To make batch operations more efficient and reduce power consumption, // provide support for delaying updates to the application. // // In this example, the sensor reporting delay is small enough such that // the application receives an update before the system checks the sensor // readings again. Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelerometer != null) { sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); } Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); if (magneticField != null) { sensorManager.registerListener(this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); } } @Override protected void onPause() { super.onPause(); // Don't receive any more updates from either sensor. sensorManager.unregisterListener(this); } // Get readings from accelerometer and magnetometer. To simplify calculations, // consider storing these readings as unit vectors. @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.length); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.length); } } // Compute the three orientation angles based on the most recent readings from // the device's accelerometer and magnetometer. public void updateOrientationAngles() { // Update rotation matrix, which is needed to update orientation angles. SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // "rotationMatrix" now has up-to-date information. SensorManager.getOrientation(rotationMatrix, orientationAngles); // "orientationAngles" now has up-to-date information. } }
En général, il n'est pas nécessaire d'effectuer un traitement ni un filtrage des données les angles d'orientation bruts de l'appareil autres que la traduction le système de coordonnées au référentiel de votre application.
Utiliser le capteur de champ géomagnétique
Le capteur de champ géomagnétique vous permet de surveiller les variations du champ magnétique terrestre. La Le code suivant vous montre comment obtenir une instance du capteur de champ géomagnétique par défaut:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
Remarque : Si votre application cible Android 12 (niveau d'API 31) ou plus haut, ce capteur est limité en débit.
Ce capteur fournit des données brutes sur l'intensité du champ (en μT) pour chacun des trois axes de coordonnées.
En règle générale, vous n'avez pas besoin d'utiliser ce capteur directement. À la place, vous pouvez utiliser le vecteur de rotation
pour déterminer le mouvement de rotation brut, ou vous pouvez utiliser l'accéléromètre et le champ géomagnétique
capteur conjointement avec la méthode getRotationMatrix()
pour obtenir la matrice de rotation et la matrice d'inclinaison. Vous pouvez ensuite
utiliser ces matrices avec la fonction getOrientation()
et getInclination()
pour obtenir l'azimut
et d'inclinaison géomagnétique.
Remarque : Lorsque vous testez votre application, vous pouvez l'améliorer la précision du capteur en agitant l'appareil en forme de huit.
Utiliser le magnétomètre non calibré
Le magnétomètre non calibré est semblable au champ géomagnétique
, sauf qu'aucun étalonnage du fer dur n'est appliqué au champ magnétique. Étalonnage en usine
et la compensation de température sont
toujours appliquées au champ magnétique. Magnétomètre non calibré
est utile pour gérer les mauvaises estimations
de fer dur. En général, geomagneticsensor_event.values[0]
sera proche de uncalibrated_magnetometer_event.values[0] -
uncalibrated_magnetometer_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 du champ magnétique, le magnétomètre non calibré fournit également une estimation du biais de fer dur dans chaque axe. Le code suivant vous montre comment récupérer une instance de la classe magnétomètre non calibré par défaut:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
Utiliser le capteur de proximité
Le capteur de proximité permet de déterminer la distance entre un objet et un appareil. Les éléments suivants : vous montre comment obtenir une instance du capteur de proximité par défaut:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
Le capteur de proximité est généralement utilisé pour déterminer la distance entre la tête d'une personne et son visage d'un combiné (par exemple, lorsqu'un utilisateur passe ou reçoit un appel téléphonique). La plupart Les capteurs de proximité renvoient la distance absolue, en cm, mais certains n'en renvoient qu'à des les valeurs éloignées.
Remarque:Sur certains modèles d'appareils, le capteur de proximité se trouve sous l'écran, ce qui peut faire apparaître un point clignotant si l'option est activée alors que l'écran est activé.
Le code suivant montre comment utiliser le capteur de proximité:
Kotlin
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private var proximity: Sensor? = null public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) // Get an instance of the sensor service, and use that to get an instance of // a particular sensor. sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. } override fun onSensorChanged(event: SensorEvent) { val distance = event.values[0] // Do something with this sensor data. } override fun onResume() { // Register a listener for the sensor. super.onResume() proximity?.also { proximity -> sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL) } } override fun onPause() { // Be sure to unregister the sensor when the activity pauses. super.onPause() sensorManager.unregisterListener(this) } }
Java
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private Sensor proximity; @Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get an instance of the sensor service, and use that to get an instance of // a particular sensor. sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); } @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. } @Override public final void onSensorChanged(SensorEvent event) { float distance = event.values[0]; // Do something with this sensor data. } @Override protected void onResume() { // Register a listener for the sensor. super.onResume(); sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { // Be sure to unregister the sensor when the activity pauses. super.onPause(); sensorManager.unregisterListener(this); } }
Remarque:Certains capteurs de proximité renvoient des valeurs binaires qui représentent
"à proximité de" ou « loin ». Dans ce cas, le capteur indique généralement sa plage maximale à l'état éloigné.
et une valeur inférieure dans l'état proche. Généralement, la valeur "loin" est une valeur > 5 cm, mais cela peut varier
entre les différents capteurs. Vous pouvez déterminer la portée maximale d'un capteur à l'aide de la méthode getMaximumRange()
.