Conseguir vector de dirección en Android

¿Cómo puedo obtener un vector de dirección que representa la dirección de la parte posterior del dispositivo está apuntando en relación con las coordenadas de tierra?

Por ejemplo, si se coloca sobre un escritorio (la pantalla hacia arriba) debe leer [0,0, -1] y si se mantiene verticalmente hacia el norte debería leer [1,0,0], etc.

Sé cómo calcularlo desde el rumbo, el tono y el rollo, siempre que sean relativos a las coordenadas de tierra. Para ser claro aquí no estoy buscando la velocidad angular, sino el ángulo actual de corriente en relación con el plano tangente a la tierra. Así que si el dispositivo se mantiene vertical y mirando hacia el norte, el ángulo "alfa" debe leer 0 o 360, el ángulo "beta" debe leer 90, y "gamma" debe decir 0. No puedo averiguar cómo obtener estos valores ya sea.

He estado leyendo el API todo el día y todavía no puedo encontrar cómo conseguir cualquiera de estas cosas.

public void onSensorChanged(SensorEvent event) { // ? } 

Gracias por cualquier información.

SensorManager.getRotationMatrix() hace lo que se describe a continuación, escrito antes de que SensorManager.getRotationMatrix() esto. Voy a dejar la explicación añadida porque si desea corregir la diferencia entre el norte magnético y el norte verdadero que todavía lo necesita.

El algoritmo aproximado es obtener la matriz de rotación, multiplicar el vector [0,0,-1] por ella y luego ajustarlo a su sistema de coordenadas. ¿Por qué? Los documentos Android proporcionan los sistemas de coordenadas para los dispositivos y el mundo

dispositivomundo

Nota [0,0,-1] en las coordenadas del dispositivo Android apunta perpendicularmente hacia atrás lejos de la pantalla. Si multiplica la matriz de rotación R por este vector, obtendrá [0,0,-1] en coords mundiales cuando el dispositivo esté sobre la mesa hacia arriba como desee. Cuando está mirando hacia el norte, obtendrá [0,-1,0] , lo que indica que ha elegido un sistema de coordenadas en el que y se intercambian con respecto al sistema Android, pero eso es simplemente un cambio de convenciones.

Nota R * [0,0,-1]^T es sólo la tercera columna de R negado. De esto obtengo el pseudocódigo:

 getRotationMatrix(R); Let v = first three elements of third column of R. swap v[0] and v[1] 

Esto debería conseguir lo que quieres.

Información adicional sobre lo que getRotationMatrix() está haciendo sigue.


Usted necesita los datos del acelerómetro para establecer la dirección "hacia abajo" y los datos del magnetómetro para determinar la dirección "norte". Tendrás que suponer que los acelerómetros están detectando sólo la gravedad (el dispositivo está parado o se mueve a una velocidad constante). Entonces es necesario proyectar el vector del magnetómetro sobre el plano perpendicular al vector de gravedad (porque el campo magnético no es generalmente tangente a la superficie de la tierra). Esto le da dos ejes. El tercero es ortogonal, por lo que se puede calcular por producto cruzado. Esto le da los vectores de coordenadas de tierra en el sistema del dispositivo. Parece que quieres el inverso: coordenadas del dispositivo en coordenadas de tierra. Para ello basta con construir la matriz de cosenos de dirección e invertir.

Añadiré que la discusión anterior supone que el vector del magnetómetro apunta al norte. Creo que (de la ciencia de la escuela secundaria) es en realidad hacia el sur magnético, pero no tienen ningún dispositivo a mano, así que no puede probarlo. Por supuesto, el norte / sur magnético es diferente de la verdad de cero a 180 grados, dependiendo de dónde se encuentre en la tierra. Puede recuperar coordenadas GPS y calcular un desplazamiento real.

Si no está familiarizado con las matemáticas necesarias para hacer esto, puedo explicar más, pero tendrá que ser más tarde.

Leer esta página: http://developer.android.com/reference/android/hardware/Sensor.html

En API 8 y superiores, hay sensores "virtuales" que se generan combinando las entradas de todos los sensores disponibles y filtros apropiados. El sensor "TYPE_ORIENTATION" le ofrece la orientación máxima de su dispositivo, pero esta interfaz está obsoleta debido a estados fallidos en ciertas orientaciones. El nuevo sensor es TYPE_ROTATION_VECTOR (API 9 y superior) que le da a su dispositivo orientación como un cuaternión. Este es realmente el mejor sensor a utilizar, pero la matemática detrás de él es un poco pesada.

De lo contrario, lo que haces es llamar a SensorManager.getRotationMatrix (), pasando los últimos datos de gravedad y magnetómetro. Esto devolverá una matriz de rotación que podría usarse para convertir un vector de coordenadas de dispositivo a coordenadas mundiales o viceversa (solo transponga la matriz para invertirla).

La función getOrientation () puede darle título, tono y rollo, pero estos tienen los mismos estados de fallo que el sensor TYPE_ORIENTATION.

 Examples: Device flat on a table, top facing north: 1 0 0 0 1 0 0 0 1 Tilted up 30 degrees (rotated about X axis) 1 0 0 0 0.86 -0.5 0 0.5 0.86 Device vertical (rotated about X axis), facing north: 1 0 0 0 0 -1 0 1 0 Device flat on a table, top facing west: 0 -1 0 1 0 0 0 0 1 Device rotated about its Y axis, onto its left side, top facing north: 0 0 -1 0 1 0 1 0 0 

He aquí algunos ejemplos de código que puede ser útil:

 public void onSensorChanged(SensorEvent event) { long now = event.timestamp; // ns switch( event.sensor.getType() ) { case Sensor.TYPE_ACCELEROMETER: gData[0] = event.values[0]; gData[1] = event.values[1]; gData[2] = event.values[2]; break; case Sensor.TYPE_MAGNETIC_FIELD: mData[0] = event.values[0]; mData[1] = event.values[1]; mData[2] = event.values[2]; haveData = true; break; } if( haveData ) { double dt = (now - last_time) * .000000001; SensorManager.getRotationMatrix(R1, Imat, gData, mData); getOrientation(R1, orientation); pfdView.newOrientation(orientation[2], (float)dt); Log.d(TAG, "yaw: " + (int)(orientation[0]*DEG)); Log.d(TAG, "pitch: " + (int)(orientation[1]*DEG)); Log.d(TAG, "roll: " + (int)(orientation[2]*DEG)); acft.compass = orientation[0]; last_time = now; } } 
  • Aceleración del sistema de coordenadas del dispositivo en sistema de coordenadas absoluto
  • Cómo acceder a las filas y columnas de Vector <Mat> Imágenes en Open cv para Android?
  • No se pueden incluir encabezados de C ++ como vector en Android NDK
  • Selector de Android Drawable con VectorDrawables srcCompat
  • Cambiar fillColor de vector en android programaticamente
  • Vector Drawable como el logotipo de la aplicación
  • Nueve parches versus gráficos vectoriales
  • ¿Dónde puedo ir para las imágenes de Android Market? Una imagen vacía de la tableta que puedo pegar mi aplicación en ejecución en un gráfico promocional sería perfecto
  • Java: Tamaño de un vector en bytes
  • EditText drwableLeft no funciona con vectores
  • Biblioteca de Android sobre el recurso de reemplazo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.