proyectos - Acelerómetro 3D calcular la orientación
proyectos con acelerometro arduino (5)
La respuesta correcta es:
Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;
Fuente: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf (página 10, Eqn. 25 y 26)
La respuesta de uesp es incorrecta. Parece una aproximación aceptable hasta que cabeceo y balanceo van por encima de 45 grados.
Puedo estar asumiendo una convención de orientación diferente, pero incluso si intercambia ejes e invierte valores de manera consistente, los cálculos de uesp nunca serán equivalentes.
Tengo valores de acelerómetro para los 3 ejes (generalmente cuando solo la gravedad contiene datos entre -1.0 y 1.0):
float Rx;
float Ry;
float Rz;
Hago cálculos soma, luego obtengo los ángulos para cada eje.
float R = sqrt(pow(Rx,2)+pow(Ry,2)+pow(Rz,2));
float Arx = acos(Rx/R)*180/M_PI;
float Ary = acos(Ry/R)*180/M_PI;
float Arz = acos(Rz/R)*180/M_PI;
Luego establezco los valores para los ángulos de caja en OpenGL
rquad = Arx;
yquad = Ary;
Que gira mi caja:
glRotatef(yquad,1.0f,0.0f,0.0f);
glRotatef(rquad,0.0f,1.0f,0.0f);
Funciona en el hemisferio. Me gustaría usar la esfera completa y sé que tengo que usar el valor de Arz para hacerlo funcionar, pero no sé cómo puedo usar eso para esta rotación. ¿Usted me podría ayudar?
Actualización: la respuesta final está en mi caso:
rquad = -atan2(Rx/R, Rz/R)*180/M_PI;
yquad = -atan2(Ry/R, Rz/R)*180/M_PI;
Para el roll
, he encontrado que puedes usar arctan(y/sqrt(X*X)+(z*z))
esto dará rol -90/90
que es el estándar de aviación sin dar el problema del tono
Probé la solución recomendada (matteo), y aunque parecía funcionar bien al principio, noté que cuando el tono se acerca a 90 grados (comenzando a alrededor de 70 grados, pero no necesariamente a través de diferentes teléfonos), el sonido repentinamente aumenta. Cuando el tono está en 90, la tirada que debería estar alrededor de 0 ahora es de más de 100 y sigue aumentando a 180. Estoy intentando pensar en una forma de prevenir matemáticamente esto, si restrinjo el rollo a + 90 / -90 se comporta normalmente pero no obtengo el rango que quiero (+ 180 / -180): Math.atan2 (y, Math.sqrt ((x x) + (z z))) * (180 / Math.PI))
Si bien la respuesta de Matteo es correcta, no proporciona la solución completa y completa: las fórmulas son correctas:
Roll = atan2(Y, Z) * 180/M_PI;
Pitch = atan2(-X, sqrt(Y*Y + Z*Z)) * 180/M_PI;
Sin embargo, cuando el tono es + 90 / -90 grados y el eje X está verticalmente apuntando hacia arriba / abajo, la salida normalizada del acelerómetro ideal debería ser:
accX = -1 / accX = 1
accY = 0
accZ = 0
Lo que significa un roll angle of 0 degrees
; correcto. Pero en la práctica, la salida del acelerómetro es ruidosa y obtendría algo más cerca de:
accX = -1 / accX = 1
accY = 0.003
accZ = 0.004
Esto puede parecer pequeño pero causará que el ángulo de balanceo sea ~ 30 dregrees, lo que no es correcto.
El instinto obvio sería filtrar los últimos dígitos, pero esto afectaría la precisión, que no siempre es aceptable.
El compromiso, que está muy bien explicado en la nota de la aplicación de referencia, es incluir un porcentaje muy pequeño de la lectura del eje X del acelerómetro en la fórmula para rodar:
Roll = atan2( Y, sign* sqrt(Z*Z+ miu*X*X));
sign = 1 if accZ>0, -1 otherwise
miu = 0.001
El error introducido de esta manera es dramáticamente más pequeño que el caso anterior: 2-3 grados cuando se mide el balanceo en las mismas condiciones explicadas anteriormente.
Utilizo los siguientes cálculos para convertir nuestras lecturas de acelerómetro en valores de balanceo y cabeceo:
Roll = atan2( sqrt(Y*Y + X*X), Z) * 180/M_PI;
Pitch = atan2( sqrt(X*X + Z*Z), Y) * 180/M_PI;
Es posible que necesite intercambiar los valores X / Y / Z o traducir el giro / inclinación dependiendo de cómo estén definidos sus acelerómetros. Para usarlos en la pantalla, es una simple cuestión de:
glRotatef (Pitch, 0.0f, 0.0f, 1.0f);
glRotatef (Roll, 1.0f, 0.0f, 0.0f);