web-dev-qa-db-fra.com

Android Présentation de l'orientation du téléphone, y compris la boussole

Cela fait un moment que j'essaie de comprendre les capteurs d'orientation Android Android. Je pensais l'avoir compris. Puis je me suis rendu compte que je ne l'avais pas fait. Maintenant, je pense (j'espère) que j'ai un mieux le ressentir à nouveau mais je ne suis toujours pas à 100%. J'essaierai d'expliquer ma compréhension inégale et j'espère que les gens pourront me corriger si je me trompe dans certaines parties ou remplir des blancs.

J'imagine que je me tiens à 0 degrés de longitude (méridien principal) et 0 degrés de latitude (équateur). Cet endroit est en fait dans la mer au large des côtes de l'Afrique, mais restez avec moi. Je tiens mon téléphone devant mon visage de sorte que le bas du téléphone pointe vers mes pieds; Je fais face au nord (en regardant vers Greenwich) donc le côté droit du téléphone pointe vers l'est en direction de l'Afrique. Dans cette orientation (en référence au diagramme ci-dessous), j'ai l'axe X pointant vers l'est, l'axe Z pointant vers le sud et l'axe Y pointant vers le ciel.

Les capteurs du téléphone vous permettent désormais de déterminer l'orientation (et non l'emplacement) de l'appareil dans cette situation. Cette partie m'a toujours dérouté, probablement parce que je voulais comprendre comment quelque chose fonctionnait avant d'accepter que cela fonctionne. Il semble que le téléphone détermine son orientation en combinant deux techniques différentes.

Avant d'en arriver là, imaginez être de retour debout sur ce morceau de terre imaginaire à 0 degrés de latitude et de longitude dans la direction mentionnée ci-dessus. Imaginez aussi que vous avez les yeux bandés et que vos chaussures sont fixées sur un rond-point de jeux. Si quelqu'un vous pousse dans le dos, vous tomberez en avant (vers le nord) et déploierez vos deux mains pour interrompre votre chute. De même, si quelqu'un vous pousse l'épaule gauche, vous tomberez sur votre main droite. Votre oreille interne a des "capteurs gravitationnels" (clip youtube) qui vous permettent de détecter si vous tombez en avant/en arrière, ou en tombant à gauche/à droite ou en tombant (ou en haut !!). Par conséquent, les humains peuvent détecter l'alignement et la rotation autour des mêmes axes X et Z que le téléphone.

Imaginez maintenant que quelqu'un vous fasse pivoter de 90 degrés sur le rond-point afin que vous soyez maintenant face à l'Est. Vous êtes en rotation autour de l'axe Y. Cet axe est différent car nous ne pouvons pas le détecter biologiquement. Nous savons que nous sommes inclinés d'une certaine quantité, mais nous ne connaissons pas la direction par rapport au pôle Nord magnétique de la planète. Au lieu de cela, nous devons utiliser un outil externe ... une boussole magnétique. Cela nous permet de déterminer dans quelle direction nous sommes confrontés. C'est la même chose avec notre téléphone.

Maintenant, le téléphone dispose également d'un accéléromètre à 3 axes. Je n'ai [~ # ~] aucune [~ # ~] idée de la façon dont ils fonctionnent mais la façon dont je le visualise est d'imaginer la gravité comme constante et uniforme "pluie" tombant du ciel et d'imaginer les axes dans la figure ci-dessus comme des tubes qui peuvent détecter la quantité de pluie qui coule à travers. Lorsque le téléphone est en position verticale, toute la pluie coule à travers le "tube" en Y. Si le téléphone pivote progressivement de façon à ce que son écran soit orienté vers le ciel, la quantité de pluie passant par Y diminuera à zéro tandis que le volume passant par Z augmentera régulièrement jusqu'à ce que la quantité maximale de pluie traverse. De même, si nous inclinons maintenant le téléphone sur le côté, le tube X finira par collecter la quantité maximale de pluie. Par conséquent, en fonction de l'orientation du téléphone en mesurant la quantité de pluie qui coule à travers les 3 tubes, vous pouvez calculer l'orientation.

Le téléphone possède également une boussole électronique qui se comporte comme une boussole normale - son "aiguille virtuelle" pointe vers le nord magnétique. Android fusionne les informations de ces deux capteurs afin qu'à chaque fois qu'un SensorEvent de TYPE_ORIENTATION Soit généré, le tableau values[3] Ait
valeurs [0]: Azimut la boussole portant à l'est du nord magnétique)
Valeurs [1]: Pas, rotation autour de l'axe x (le téléphone est-il penché en avant ou en arrière)
valeurs [2]: roulis, rotation autour de l'axe y (le téléphone est-il penché sur son côté gauche ou droit)

Je pense donc (c'est-à-dire que je ne sais pas) que la raison Android donne l'azimut (relèvement de la boussole) plutôt que la lecture du troisième accéléromètre est que le relèvement de la boussole est juste plus utile. I ' Je ne sais pas pourquoi ils ont déconseillé ce type de capteur, car il semble maintenant que vous devez enregistrer un écouteur auprès du système pour SensorEvents de type TYPE_MAGNETIC_FIELD. Le tableau value[] de l'événement doit passé dans la méthode SensorManger.getRotationMatrix(..) pour obtenir une matrice de rotation (voir ci-dessous) qui est ensuite passée dans la méthode SensorManager.getOrientation(..). Quelqu'un sait-il pourquoi la Android team obsolète Sensor.TYPE_ORIENTATION? Est-ce une question d'efficacité? C'est ce qui est impliqué dans l'un des commentaires à un similaire --- (question mais vous devez toujours enregistrer un type d'écoute différent dans le - development/samples/Compass/src/com/example/Android/compass/CompassActivity.Java exemple.

J'aimerais maintenant parler de la matrice de rotation. (C'est là que je ne suis pas sûr) Donc, ci-dessus, nous avons les trois chiffres de la documentation Android, nous les appellerons A, B et C.

A = figure de la méthode SensorManger.getRotationMatrix (..) et représente le système de coordonnées du monde

B = Système de coordonnées utilisé par l'API SensorEvent.

C = Figure de la méthode SensorManager.getOrientation (..)

Donc, je crois comprendre que A représente le "système de coordonnées du monde" qui, je présume, se réfère à la façon dont les emplacements sur la planète sont donnés comme un couple (latitude, longitude) avec un optionnel (altitude). X est la coordonnée "abscisse" , Y est la coordonnée "ordonnée" . Z pointe vers le ciel et représente l'altitude.

Le système de coordonnées téléphoniques est montré dans la figure B est fixe. Son axe Y indique toujours le haut. La matrice de rotation est constamment calculée par le téléphone et permet une cartographie entre les deux. Ai-je donc raison de penser que la matrice de rotation transforme le système de coordonnées de B en C? Ainsi, lorsque vous appelez la méthode SensorManager.getOrientation(..), vous utilisez le tableau values[] Avec des valeurs correspondant à la figure C. Lorsque le téléphone est pointé vers le ciel, la matrice de rotation est une matrice d'identité (l'équivalent mathématique de la matrice de 1) ce qui signifie qu'aucune cartographie n'est nécessaire car l'appareil est aligné avec le système de coordonnées mondial.

D'accord. Je pense que je ferais mieux de m'arrêter maintenant. Comme je l'ai dit auparavant, j'espère que les gens me diront où j'ai foiré ou aidé les gens (ou encore plus confus!)

106
Tim

Vous voudrez peut-être consulter l'article n tour d'écran en mérite un autre . Il explique pourquoi vous avez besoin de la matrice de rotation.

En un mot, les capteurs du téléphone utilisent toujours le même système de coordonnées, même lorsque l'appareil est tourné.

Dans les applications qui ne sont pas verrouillées dans une seule orientation, le système de coordonnées d'écran change lorsque vous faites pivoter l'appareil. Ainsi, lorsque l'appareil est tourné de son mode d'affichage par défaut, le système de coordonnées du capteur n'est plus le même que le système de coordonnées d'écran. La matrice de rotation dans ce cas est utilisée pour transformer A en C (B reste toujours fixe).

Voici un extrait de code pour vous montrer comment il peut être utilisé.

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);

// Register this class as a listener for the accelerometer sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                    SensorManager.SENSOR_DELAY_NORMAL);

//...
// The following code inside a class implementing a SensorEventListener
// ...

float[] inR = new float[16];
float[] I = new float[16];
float[] gravity = new float[3];
float[] geomag = new float[3];
float[] orientVals = new float[3];

double azimuth = 0;
double pitch = 0;
double roll = 0;

public void onSensorChanged(SensorEvent sensorEvent) {
    // If the sensor data is unreliable return
    if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        return;

    // Gets the value of the sensor that has been changed
    switch (sensorEvent.sensor.getType()) {  
        case Sensor.TYPE_ACCELEROMETER:
            gravity = sensorEvent.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomag = sensorEvent.values.clone();
            break;
    }

    // If gravity and geomag have values then find rotation matrix
    if (gravity != null && geomag != null) {

        // checks that the rotation matrix is found
        boolean success = SensorManager.getRotationMatrix(inR, I,
                                                          gravity, geomag);
        if (success) {
            SensorManager.getOrientation(inR, orientVals);
            azimuth = Math.toDegrees(orientVals[0]);
            pitch = Math.toDegrees(orientVals[1]);
            roll = Math.toDegrees(orientVals[2]);
        }
    }
}
26
Levi Blackstone

Le roulis est une fonction de la gravité, un roulis à 90 degrés met toute la gravité dans le registre x.

La hauteur est la même, une hauteur de 90 degrés place toutes les composantes de la gravité dans le registre y.

Le lacet/cap/azimut n'a aucun effet sur la gravité, il est TOUJOURS perpendiculaire à la gravité, donc peu importe la façon dont vous faites face à la gravité sera incommensurable.

C'est pourquoi vous avez besoin d'une boussole pour évaluer, peut-être que cela a du sens?

3
Craig

J'avais ce problème alors j'ai cartographié ce qui se passe dans différentes directions. Si l'appareil est monté en mode paysage, par exemple dans un support de voiture, les "degrés" de la boussole semblent aller de 0 à 275 (dans le sens des aiguilles d'une montre) au-dessus de 269 (entre l'ouest et le nord), il compte en arrière de -90 à 0, puis avance de 0 à 269. 270 devient -90

Toujours en paysage mais avec l'appareil allongé sur le dos mon capteur donne 0-360. et en mode portrait, il fonctionne 0-360 à la fois allongé sur le dos et debout en mode portrait.

J'espère que cela aide quelqu'un

0
hopeless bob

Jetez un œil à ceci: Stackoverflow.com: Q.5202147

Vous semblez avoir tout à fait raison jusqu'à ce que les 3 diagrammes A, B, C. Après cela, vous vous êtes confus.

0
TheCodeArtist