android - traslacion - extraer la guiñada, la inclinación y la rotación de una matriz de rotación
rotacion de coordenadas cartesianas (3)
Creo que la respuesta de Blender no es correcta, ya que dio una transformación de la matriz de rotación a los ángulos de Euler (zxz extrínseco), y Roll Pitch Yaw es un tipo diferente de ángulos de Euler (zyx extrínseco).
La fórmula de transformación real sería más bien:
yaw=atan2(R(2,1),R(1,1));
pitch=atan2(-R(3,1),sqrt(R(3,2)^2+R(3,3)^2)));
roll=atan2(R(3,2),R(3,3));
Retroalimentación: esta implementación reveló que carece de estabilidad numérica cerca de la singularidad de la representación (bloqueo de cardán). Por lo tanto, en C ++ recomiendo usar la biblioteca Eigen con la siguiente línea de código:
R.eulerAngles(2,1,0).reverse();
(Más detalles here )
Tengo un administrador de sensores que devuelve una rotationMatrix
basada en los dispositivos Magnetómetro y Acelerómetro. También he estado tratando de calcular el lanzamiento y giro del dispositivo del usuario, pero encuentro que el lanzamiento y el giro interfieren entre sí y dan resultados inexactos. ¿Hay una manera de extraer YAW PITCH y ROLL de un dispositivo de la rotationMatrix
matriz?
EDITAR Intentar interpretar la respuesta de Blender a continuación, por lo que estoy agradecido, pero aún no he llegado a ese punto, estoy tratando de obtener el ángulo desde una matriz de rotación como esta:
float R[] = phoneOri.getMatrix();
double rmYaw = Math.atan2(R[4], R[0]);
double rmPitch = Math.acos(-R[8]);
double rmRoll = Math.atan2(R[9], R[10]);
No sé si estoy haciendo referencia a las partes equivocadas de la matriz o no, pero no estoy obteniendo los resultados que pensaría.
Esperaba obtener valores en grados, pero obtengo enteros extraños.
mi matriz viene de mi sensorManager
que se ve así:
public void onSensorChanged(SensorEvent evt) {
int type=evt.sensor.getType();
if(type == Sensor.TYPE_ORIENTATION){
yaw = evt.values[0];
pitch = evt.values[1];
roll = evt.values[2];
}
if (type == Sensor.TYPE_MAGNETIC_FIELD) {
orientation[0]=(orientation[0]*1+evt.values[0])*0.5f;
orientation[1]=(orientation[1]*1+evt.values[1])*0.5f;
orientation[2]=(orientation[2]*1+evt.values[2])*0.5f;
} else if (type == Sensor.TYPE_ACCELEROMETER) {
acceleration[0]=(acceleration[0]*2+evt.values[0])*0.33334f;
acceleration[1]=(acceleration[1]*2+evt.values[1])*0.33334f;
acceleration[2]=(acceleration[2]*2+evt.values[2])*0.33334f;
}
if ((type==Sensor.TYPE_MAGNETIC_FIELD) || (type==Sensor.TYPE_ACCELEROMETER)) {
float newMat[]=new float[16];
SensorManager.getRotationMatrix(newMat, null, acceleration, orientation);
if(displayOri==0||displayOri==2){
SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_X*-1, SensorManager.AXIS_MINUS_Y*-1,newMat);
}else{
SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X,newMat);
}
matrix=newMat;
muestra matriz cuando el dispositivo está boca arriba en la mesa
0.9916188, -0.12448014, -0.03459576, 0.0
0.12525482, 0.9918981, 0.021199778, 0.0
0.031676512,-0.025355382, 0.9991765, 0.0
0.0, 0.0, 0.0, 1
RESPONDER
double rmPitch = Math.toDegrees( Math.acos(R[10]));
Sensor Manager proporciona un SensorManager.getOrientation para obtener los tres ángulos.
Yaw, pitch y roll corresponden a los ángulos de Euler. Puedes convertir una matriz de transformación a los ángulos de Euler con bastante facilidad: