android - ingresar - coordenadas relativas ejemplos
AceleraciĆ³n del sistema de coordenadas del dispositivo en un sistema de coordenadas absoluto (4)
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:
- dispositivo puesto en el lado izquierdo
- dispositivo acostado boca arriba
- dispositivo de pie
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:
- obtener la matriz de rotación (
float[16]
para que pueda ser usada más tarde por la claseandroid.opengl.Matrix
) deSensorManager.getRotationMatrix()
(usando los valores de los sensoresSENSOR.TYPE_GRAVITY
ySENSOR.TYPE_MAGNETIC_FIELD
como parámetros), - usa
android.opengl.Matrix.invertM()
en la matriz de rotación para invertirlo (¡no transponer!), - use el sensor
Sensor.TYPE_LINEAR_ACCELERATION
para obtener el vector de aceleración lineal (en el sistema coord. del dispositivo), - 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.
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.
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 programació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!