Introducción a la orientación del teléfono Android, incluida la brújula

He estado tratando de entender los sensores de orientación de Android por un tiempo. Creí haberlo entendido Entonces me di cuenta de que no. Ahora creo (espero) que tengo una mejor sensación de nuevo, pero todavía no estoy al 100%. Trataré de explicar mi comprensión parcial y espero que la gente pueda corregirme si me equivoco en partes o rellenar espacios en blanco.

Me imagino que estoy parado en 0 grados de longitud (meridiano principal) y 0 grados de latitud (ecuador). Esta ubicación es en realidad en el mar frente a la costa de África, pero tengan paciencia conmigo. Sostengo mi teléfono frente a mi cara para que la parte inferior del teléfono apunte a mis pies; Estoy mirando hacia el norte (mirando hacia Greenwich), por lo tanto, el lado derecho del teléfono apunta al este hacia África. En esta orientación (con referencia al diagtwig a continuación), tengo el eje X apuntando hacia el este, el eje Z apunta hacia el sur y el eje Y apunta hacia el cielo.

Ahora los sensores en el teléfono le permiten calcular la orientación (no la ubicación) del dispositivo en esta situación. Esta parte siempre me ha confundido, probablemente porque quería entender cómo funcionaba algo antes de aceptar que simplemente funcionaba. Parece que el teléfono funciona su orientación mediante una combinación de dos técnicas diferentes.

Antes de llegar a eso, imagina estar de pie en ese pedazo de tierra imaginaria a 0 grados de latitud y longitud en la dirección mencionada anteriormente. Imagine también que tiene los ojos vendados y que sus zapatos están fijos en una rotonda del patio de recreo. Si alguien te empuja por la espalda caerás hacia adelante (hacia el norte) y pondrás ambas manos para romper tu caída. De manera similar, si alguien te empuja el hombro izquierdo, caerás sobre tu mano derecha. Su oído interno tiene “sensores gravitacionales” (clip de youtube) que le permiten detectar si está cayendo hacia adelante / atrás, o cayendo a la izquierda / derecha o cayendo (¡o hacia arriba!). Por lo tanto, los humanos pueden detectar alineación y rotación alrededor de los mismos ejes X y Z que el teléfono.

Ahora imagina que alguien ahora te gira 90 grados en la rotonda para que estés mirando hacia el este. Estás girando alrededor del eje Y. Este eje es diferente porque no podemos detectarlo biológicamente. Sabemos que tenemos una cierta cantidad de ángulo, pero no sabemos la dirección en relación con el polo norte magnético del planeta. En cambio, necesitamos usar una herramienta externa … una brújula magnética. Esto nos permite determinar en qué dirección nos enfrentamos. Lo mismo es cierto con nuestro teléfono.

Ahora el teléfono también tiene un acelerómetro de 3 ejes. No tengo idea de cómo funcionan realmente, pero la forma en que lo visualizo es imaginar la gravedad como una “lluvia” constante y uniforme que cae del cielo e imaginar los ejes en la figura anterior como tubos que pueden detectar la cantidad de lluvia que fluye. Cuando el teléfono esté en posición vertical toda la lluvia fluirá a través del Y ‘tube’. Si el teléfono gira gradualmente para que su pantalla mire hacia el cielo, la cantidad de lluvia que fluye a través de Y disminuirá a cero, mientras que el volumen a través de Z boostá constantemente hasta que la cantidad máxima de lluvia fluya. De manera similar, si volcamos el teléfono hacia un lado, el tubo X eventualmente recogerá la cantidad máxima de lluvia. Por lo tanto, dependiendo de la orientación del teléfono al medir la cantidad de lluvia que fluye a través de los 3 tubos, puede calcular la orientación.

El teléfono también tiene una brújula electrónica que se comporta como una brújula normal: su “aguja virtual” apunta hacia el norte magnético. Android combina la información de estos dos sensores para que siempre que se SensorEvent un SensorEvent de TYPE_ORIENTATION la matriz de values[3] tenga
valores [0]: Azimut – (la brújula al este del norte magnético)
valores [1]: Paso, rotación alrededor del eje x (es el teléfono inclinado hacia adelante o hacia atrás)
valores [2]: rodar, girar alrededor del eje y (el teléfono se inclina sobre su lado izquierdo o derecho)

Así que creo (es decir, no sé) que la razón por la que Android da el acimut (brújula) en lugar de la lectura del tercer acelerómetro es que el rumbo de la brújula es más útil. No estoy seguro de por qué desaprobaron este tipo de sensor ya que ahora parece que necesita registrar un oyente con el sistema para SensorEvent de tipo TYPE_MAGNETIC_FIELD . La matriz de value[] del evento value[] debe pasarse al método SensorManger.getRotationMatrix(..) para obtener una matriz de rotación (ver a continuación) que luego se pasa al método SensorManager.getOrientation(..) . ¿Alguien sabe por qué el equipo de Android Sensor.TYPE_ORIENTATION ? ¿Es una cosa de eficiencia? Eso es lo que está implícito en uno de los comentarios a una pregunta similar , pero aún necesita registrar un tipo diferente de oyente en el ejemplo de desarrollo / samples / Compass / src / com / example / android / compass / CompassActivity.java .

Ahora me gustaría hablar sobre la matriz de rotación. (Aquí es donde no estoy seguro) Así que arriba tenemos las tres cifras de la documentación de Android, las llamaremos A, B y C.

A = Figura del método SensorManger.getRotationMatrix (..) y representa el sistema de coordenadas del mundo

B = Sistema de coordenadas utilizado por la API SensorEvent.

C = Figura del método SensorManager.getOrientation (..)

Así que mi comprensión es que A representa el “sistema de coordenadas del mundo”, que presumo se refiere a la forma en que las ubicaciones en el planeta se dan como una (latitud, longitud) pareja con una altitud (opcional). X es la coordenada “estelar” , Y es la coordenada “norte” . Z apunta al cielo y representa la altitud.

El sistema de coordenadas del teléfono que se muestra en la figura B es fijo. Su eje Y siempre señala la parte superior. La matriz de rotación se calcula constantemente por el teléfono y permite el mapeo entre los dos. Entonces, ¿tengo razón al pensar que la matriz de rotación transforma el sistema de coordenadas de B a C? Entonces cuando llamas al SensorManager.getOrientation(..) usas el conjunto de values[] con valores que corresponden a la figura C. Cuando el teléfono apunta al cielo, la matriz de rotación es la matriz de identidad (el equivalente matemático de matriz de 1) que significa que no es necesario mapear ya que el dispositivo está alineado con el sistema de coordenadas del mundo.

De acuerdo. Creo que será mejor que me detenga ahora. Como dije antes, espero que la gente me diga dónde arruiné o ayudé a las personas (o confundí a las personas aún más).

Es posible que desee comprobar el artículo Una pantalla a su vez se merece otro artículo. Explica por qué necesita la matriz de rotación.

En pocas palabras, los sensores del teléfono siempre usan el mismo sistema de coordenadas, incluso cuando se gira el dispositivo.

En aplicaciones que no están bloqueadas en una sola orientación, el sistema de coordenadas de la pantalla cambia cuando gira el dispositivo. Por lo tanto, cuando se gira el dispositivo desde su modo de vista predeterminado, el sistema de coordenadas del sensor ya no es el mismo que el sistema de coordenadas de la pantalla. La matriz de rotación en este caso se usa para transformar de A a C (B siempre permanece fijo).

Aquí hay un fragmento de código para mostrarle cómo se puede usar.

 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]); } } } 

El rollo es una función de la gravedad, un rollo de 90 grados pone toda la gravedad en el registro x.

El tono es el mismo, un lanzamiento de 90 grados pone todo el componente de la gravedad en el registro y.

Yaw / Heading / Azimuth no tiene ningún efecto sobre la gravedad, SIEMPRE está en ángulo recto con la gravedad, por lo tanto, no importa en qué dirección te encuentres, la gravedad será indestructible.

Es por eso que necesita una brújula para evaluar, ¿quizás tiene sentido?

Eche un vistazo a esto : Stackoverflow.com: Q.5202147

Usted parece estar en su mayoría en lo cierto hasta los 3 diagtwigs A, B, C. Después de eso te has confundido.

Estaba teniendo este problema, así que planifiqué lo que sucede en diferentes direcciones. Si el dispositivo está montado en modo horizontal, por ejemplo, en un montura de automóvil, los “grados” de la brújula parecen ir de 0-275 (en sentido horario) por encima de 269 (entre el oeste y el norte) cuenta hacia atrás desde -90 a 0, luego delanteros de 0 a 269. 270 se convierte en -90

Todavía en el paisaje, pero con el dispositivo acostado sobre mi espalda, mi sensor da 0-360. y en modo vertical, ejecuta 0-360, ambos boca arriba y de pie en retrato.

Espero que ayude a alguien