Aceleración del sistema de coordenadas del dispositivo en un sistema de coordenadas absoluto

Desde mi dispositivo Android puedo leer una matriz de valores de aceleración lineal (en el sistema de coordenadas del dispositivo) y una matriz de valores de orientación absoluta (en el sistema de coordenadas de la Tierra). Lo que necesito es obtener los valores de aceleración lineal en la última coord. sistema.

¿Cómo puedo convertirlos?

EDITAR después de la respuesta de Ali en comentario:

Está bien, entonces si entiendo correctamente, cuando mido la aceleración lineal, la posición del teléfono no importa, porque las lecturas se dan en el sistema de coordenadas de la Tierra. ¿derecho?

Pero acabo de hacer una prueba donde puse el teléfono en diferentes posiciones y obtuve aceleración en diferentes ejes. Hay 3 pares de imágenes: las primeras muestran cómo puse el dispositivo (lo siento por mi Paint “habilidad maestra”) y las segundas muestran las lecturas de los datos proporcionados por el acc lineal. sensor:

  1. dispositivo puesto en el lado izquierdo

primera posiciónprimeras lecturas

  1. dispositivo acostado boca arriba

segunda posiciónsegundas lecturas

  1. dispositivo de pie

enter image description hereenter image description here

Y ahora, ¿por qué en el tercer caso la aceleración ocurre a lo largo del eje Z (no Y) ya que la posición del dispositivo no importa?

¡Finalmente logré resolverlo! Entonces, para obtener el vector de aceleración en el sistema de coordenadas de la Tierra, necesitas:

  1. obtener la matriz de rotación ( float[16] para que pueda ser usada más tarde por la clase android.opengl.Matrix ) de SensorManager.getRotationMatrix() (usando los valores de los sensores SENSOR.TYPE_GRAVITY y SENSOR.TYPE_MAGNETIC_FIELD como parámetros),
  2. usa android.opengl.Matrix.invertM() en la matriz de rotación para invertirlo (¡no transponer!),
  3. use el sensor Sensor.TYPE_LINEAR_ACCELERATION para obtener el vector de aceleración lineal (en el sistema coord. del dispositivo),
  4. utilice android.opengl.Matrix.multiplyMV() para multiplicar la matriz de rotación por vector de aceleración lineal.

¡Y ahí lo tienes! Espero ahorrar un tiempo precioso para otros.

Gracias por Edward Falk y Ali por consejos.

Según la respuesta de @ alex, aquí está el fragmento de código:

 private float[] gravityValues = null; private float[] magneticValues = null; @Override public void onSensorChanged(SensorEvent event) { if ((gravityValues != null) && (magneticValues != null) && (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)) { float[] deviceRelativeAcceleration = new float[4]; deviceRelativeAcceleration[0] = event.values[0]; deviceRelativeAcceleration[1] = event.values[1]; deviceRelativeAcceleration[2] = event.values[2]; deviceRelativeAcceleration[3] = 0; // Change the device relative acceleration values to earth relative values // X axis -> East // Y axis -> North Pole // Z axis -> Sky float[] R = new float[16], I = new float[16], earthAcc = new float[16]; SensorManager.getRotationMatrix(R, I, gravityValues, magneticValues); float[] inv = new float[16]; android.opengl.Matrix.invertM(inv, 0, R, 0); android.opengl.Matrix.multiplyMV(earthAcc, 0, inv, 0, deviceRelativeAcceleration, 0); Log.d("Acceleration", "Values: (" + earthAcc[0] + ", " + earthAcc[1] + ", " + earthAcc[2] + ")"); } else if (event.sensor.getType() == Sensor.TYPE_GRAVITY) { gravityValues = event.values; } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { magneticValues = event.values; } } 

De acuerdo con la documentación , obtienes la aceleración lineal en el sistema de coordenadas del teléfono.

Puede transformar cualquier vector del sistema de coordenadas del teléfono al sistema de coordenadas de la Tierra al multiplicarlo con la matriz de rotación . Puede obtener la matriz de rotación de getRotationMatrix () .

(Tal vez ya hay una función haciendo esta multiplicación para ti, pero yo no hago la progtwigción de Android y no estoy familiarizado con su API).

Un buen tutorial sobre la matriz de rotación es el manuscrito Direction Cosine Matrix IMU: Theory . ¡Buena suerte!

Está bien, antes que nada, si estás tratando de hacer una navegación inercial real en Android, tienes tu trabajo hecho para ti. El pequeño y barato sensor utilizado en los teléfonos inteligentes no es lo suficientemente preciso. Sin embargo, se ha realizado un trabajo interesante en la navegación intertial en distancias pequeñas, como dentro de un edificio. Probablemente haya documentos sobre el tema que pueda desenterrar. Google “Motion Interface Developers Conference” y es posible que encuentres algo útil: es una conferencia que Invensense hizo hace un par de meses.

En segundo lugar, no, la aceleración lineal está en las coordenadas del dispositivo, no en las coordenadas mundiales. Tendrá que convertirse usted mismo, lo que significa que debe conocer la orientación 3-d del dispositivo.

Lo que quiere hacer es usar una versión de Android que admita los sensores virtuales TYPE_GRAVITY y TYPE_LINEAR_ACCELERATION. Necesitará un dispositivo con giroscopios para obtener lecturas razonablemente precisas y precisas.

Internamente, el sistema combina giroscopios, acelerómetros y magnetómetros para obtener valores reales para la orientación del dispositivo. Esto divide efectivamente el dispositivo acelerómetro en sus componentes de gravedad y aceleración.

Entonces, lo que quiere hacer es configurar detectores de sensores para TYPE_GRAVITY, TYPE_LINEAR_ACCELERATION y TYPE_MAGNETOMETER. Use los datos de gravedad y magnetómetro como entradas para SensorManager. getRotationMatrix () para obtener la matriz de rotación que transformará las coordenadas del mundo en coordenadas del dispositivo o viceversa. En este caso, querrás la parte “versa”. Es decir, convierta la entrada de aceleración lineal en coordenadas mundiales multiplicándolas por la transposición de la matriz de orientación.