2011-04-07 16 views
8

Actualmente, estoy intentando rotar 3D Cube utilizando los valores del sensor de orientación, usando el método getRotation(). Algunos comportamientos inesperados se observan cuando el dispositivo Android se gira por encima de algunos límites. Por ejemplo, si hago que el dispositivo se "ponga de pie", el valor del "rollo" simplemente se vuelve loco.Comportamiento extraño con el sensor de orientación de Android

También estoy experimentando el fenómeno similar al llamado bloqueo de gimbal. La única diferencia es que estoy experimentando el mismo problema incluso antes de aplicar los valores del sensor a la rotación 3D. Cuando trato de cambiar el valor de 'pitch' girando el dispositivo solo alrededor del eje 'pitch', el valor 'yaw' también cambia de acuerdo con la rotación del pitch. Me parece completamente irrazonable.

¿Alguien podría ayudarme? Estoy atrapado en este problema por un mes.

Respuesta

15

Este es un problema común con la guiñada, cabeceo y balanceo. No puedes deshacerte de él mientras uses guiñada, cabeceo y balanceo (ángulos de Euler). This video explica por qué.

Yo uso matrices de rotación en lugar de ángulos de Euler en mi aplicación de detección de movimiento. Para una introducción a las matrices de rotación que recomiendo:

Direction Cosine Matrix IMU: Theory

matrices de rotación funcionan a las mil maravillas.

Quaternions son también muy populares y se dice que son los más estables.

[Esta respuesta fue copiado de here.]

+0

Gracias por su respuesta :) Su solución parece vale la pena probar. Entonces, ¿puedo usar la matriz de rotación obtenida directamente de la API de Android? Lamentablemente no tengo conocimiento de cómo funciona 3D, por lo que no puedo determinar si se necesita alguna manipulación en la matriz de rotación "pura" o no. –

+1

Depende de cómo hagas tu rotación. Nunca he usado Android. Si usa OpenGL para la rotación (y supongo que sí), puede que tenga que agregar un par de ceros y uno, vea 41:58 en el video de youtube. Pero aparte de eso, la matriz de rotación "pura" es suficiente. ¡Buena suerte! – Ali

+0

¿Puedes dar un ejemplo de cómo usas la matriz de rotación sin ángulos euler? Parece que no puedo entenderlo ^^ –

1

El uso de cuaterniones para calcular RPR no hará mucho para solucionar cualquier problema. El problema del bloqueo de cardán (que cerca del tono de +/- 90 puede guiar la orientación y el balanceo, en realidad gira en el polo norte) para volverse loco bajo ligeros cambios/ruido en el cuaternión subyacente).

Sin embargo, si usa los valores de Yaw Pitch and Roll para realizar una rotación de un objeto 3D, no debe exhibir ningún comportamiento extraño cerca de la posición de bloqueo del cardán. Es solo que una amibuidad en el guiñada y el balanceo surgen y las grandes variaciones en guiñada y balanceo no implican que la orientación real se esté volviendo loca, solo que la orientación es insensible a grandes cambios en el giro de guiñada cerca del tono de 90.

PERO, también tenga en cuenta que los teléfonos y navegadores para HTML5 no implementan apropiadamente yaw, pitch and roll según las convenciones para Android. Aquí es un buen blog para referencia:

http://www.sensorplatforms.com/understanding-orientation-conventions-mobile-platforms/

+0

para evitar el bloqueo cardánico, no utilice el ángulo del eje matemático. Las rotaciones de Euler son correctas siempre que evite las implementaciones de ángulo de eje. – Tcll

0

Aquí está un ejemplo básico, esto devolverá el vector de gravedad. Tenga en cuenta que puede cambiar el tipo de sensor y la velocidad de muestreo, más detalles here

SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 

sensorManager.registerListener(new SensorEventListener() { 
    @Override 
    public void onSensorChanged(SensorEvent event) { 

     float x = event.values[0]; 
     float y = event.values[1]; 
     float z = event.values[2]; 
     double total = Math.sqrt(x * x + y * y + z * z); 

    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 
    } 

}, sensor, SensorManager.SENSOR_DELAY_FASTEST); 
Cuestiones relacionadas