Calcular la matriz de rotación usando el campo magnético

En obtener el valor de la matriz de rotación que contiene public static boolean getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic) Aquí, ¿cómo puedo calcular el float[] gravity? Encontré una muestra de código donde calcula el orientation usando ambos Accelerometer y Magnetic field

boolean success = SensorManager.getRotationMatrix(
   matrixR,
   matrixI,
   valuesAccelerometer,
   valuesMagneticField);

if(success){
SensorManager.getOrientation(matrixR, matrixValues);

double azimuth = Math.toDegrees(matrixValues[0]);
double pitch = Math.toDegrees(matrixValues[1]);
double roll = Math.toDegrees(matrixValues[2]);

readingAzimuth.setText("Azimuth: " + String.valueOf(azimuth));
readingPitch.setText("Pitch: " + String.valueOf(pitch));
 readingRoll.setText("Roll: "+String.valueOf(roll));
}

Mi pregunta es:

  • ¿El valor de orientación es el valor de la matriz de rotación?
  • Si no, ¿cómo puedo implementar este código para obtener el valor de la matriz de rotación usando magnético? ¿campo?

Para obtener la matriz de rotación, uso este código.

 public void onSensorChanged(SensorEvent sensorEvent) {
    if (timestamp != 0) {
        final double dT = (sensorEvent.timestamp - timestamp) * NS2S;
            double magneticX = sensorEvent.values[0];
            double magneticY = sensorEvent.values[1];
            double magneticZ = sensorEvent.values[2];
                        double omegaMagnitude =Math.sqrt(magneticX*magneticX + magneticY*magneticY + magneticZ*magneticZ);

                        if (omegaMagnitude > EPSILON) {
                            magneticX /= omegaMagnitude;
                            magneticY /= omegaMagnitude;
                            magneticZ /= omegaMagnitude;
        }
                        double thetaOverTwo = omegaMagnitude * dT / 2.0f;
                        double sinThetaOverTwo =Math.sin(thetaOverTwo);
                        double cosThetaOverTwo = Math.cos(thetaOverTwo);
                        deltaRotationVector[0] = (double) (sinThetaOverTwo * magneticX);
                        deltaRotationVector[1] = (double) (sinThetaOverTwo * magneticY);
                        deltaRotationVector[2] = (double) (sinThetaOverTwo * magneticZ);
                        deltaRotationVector[3] = cosThetaOverTwo;


    }
     double[] deltaRotationMatrix = new double[9];
     SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
}

Pero el problema es este getRotationMatrixFromVector dice indefinido para sensor. ¿Alguna idea?

preguntado el 22 de mayo de 12 a las 09:05

2 Respuestas

La orientación no es una matriz de rotación, ya que solo proporciona ángulos relacionados con el norte magnético. Puedes obtener el matriz de rotación (Direction Cosine Matrix) que te ayudará a transformar las coordenadas del marco de tu dispositivo al marco de la Tierra de esta manera:

MCD de Wikipedia

con

azimut = acimut (radianes)

tono = paso (radianes)

rodar = rollo (radianes)

contestado el 22 de mayo de 12 a las 10:05

Gracias. Mire mi segundo código donde estoy tratando de obtener los 2 valores de la matriz de rotación. ¿Es la forma correcta de obtener esos valores? MBMJ

Puede ser. Hice eso hace mucho tiempo, calcular la matriz de rotación de un vector no me dio buenos resultados (aunque tal vez hice algo mal). Todo lo que sé es que la solución que te di funciona perfectamente (todavía la uso) y es simple de implementar. - Peter Griffin

encuentro la matriz de rotación usando esto if(success){ SensorManager.getOrientation(matrixR, matrixValues);//code here to display the matrix value donde matrixR es la matriz de rotación y dame el resultado. Pero no entiendo, ¿está usando un sistema de coordenadas real? - MBMJ

Sé que este es un hilo antiguo, pero en caso de que ayude, para Android, creo que la matriz de rotación de 3x3 en realidad está dada por una variación de la respuesta aprobada. Para ser específicos, en Android la matriz de rotación es

     (cosφ cosψ - sinφ sinψ sinθ) sinφ cosθ ( cosφ sinψ + sinφ cosψ sinθ) -(senφ cosψ + cosφ sinψ sinθ) cosφ cosθ (-sinφ sinψ + cosφ cosψ sinθ) -sinψ cosθ -sinθ cosφ cosθ

sin que importe

    φ = acimut θ = cabeceo ψ = balanceo

que corresponde a la matriz de rotación de Android 3x3 R[0] a R[8] (matrixR en la pregunta) a través de

    R[0] R[1] R[2] R[3] R[4] R[5] R[6] R[7] R[8]

Respondido 03 Abr '13, 19:04

No funciona. Lo probé, pero desafortunadamente causa distorsiones de perspectiva si se usa con el sensor de orientación (obsoleto). - Alejandro Pacha

@AlexanderPacha Creo que has entendido mal algo. Estas son las fórmulas que Android usa internamente, y todo lo que hacen es especificar una matriz de rotación 3D. La única pregunta es, si usa las funciones de Android (no obsoletas) para calcular la versión de Android de acimut, cabeceo y balanceo, ¿son estas la fórmula correcta para calcular la matriz de rotación de Android R[0]...R[8]. La perspectiva no tiene nada que ver con esto. Todavía creo que estas son las fórmulas correctas. - Estocásticamente

No hay ningún sensor no obsoleto que devuelva acimut, cabeceo y balanceo (desarrollador.android.com/reference/android/hardware/…). ¿Para qué sensor usó estas fórmulas y de dónde las tiene? - Alejandro Pacha

@AlexanderPacha Con las lecturas de Sensor.TYPE_MAGNETIC_FIELD y Sensor.TYPE_GRAVITY or Sensor.TYPE_ACCELEROMETER, llama SensorManager.getRotationMatrix(…) para obtener la matriz de rotación. Esta llamada te da la R[0]…R[8] como se describe en mi respuesta aquí. También hay una llamada de Android SensorManager.getOrientation(…) que toma esa matriz de rotación R[0]…R[8] para darle acimut, cabeceo y balanceo. - Estocásticamente

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.