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.
- Convertir Vec4i a Java openCV
- Usando el vector android Dibujos en el accidente antes de Lollipop
- VectorDrawable - ¿está disponible de alguna manera para versiones pre-Lollipop de Android?
- La imagen VectorDrawable se pixeliza
- ¿Cómo se exportan los elementos extraíbles del vector XML de Android a otro formato?
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.
- Dirección de aceleración lineal para realizar un seguimiento del movimiento hacia arriba y hacia abajo del teléfono
- Error de soporte del vector de Android
- Aplicación generador de trayecto para android
- ¿Son útiles las imágenes vectoriales para Android?
- XmlPullParserException: vector de etiqueta desplegable no válido
- ¿Por qué mi escala vectorial no es como se espera?
- Cómo crear dibujos vectoriales para Android?
- ¿Cómo configurar el tamaño del vector dibujable dentro de un botón en Android?
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
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; } }