6

Mi aplicación de realidad aumentada necesita el rumbo de la brújula de la vista de la cámara, y hay muchos ejemplos de cómo obtener la dirección del administrador del sensor.La dirección de la brújula es diferente dependiendo de la orientación del teléfono

Sin embargo el valor resultante es diferente dependiendo de la orientación del teléfono: el paisaje girado a la derecha es aproximadamente 10 grados diferente al paisaje girado a la izquierda (la diferencia entre ROTATION_0 y ROTATION_180 es menor, pero aún diferente). Esta diferencia es suficiente para arruinar cualquier efecto AR.

¿Tiene algo que ver con la calibración? (No estoy convencido de que estoy haciendo la figura de 8 correctamente, he intentado de varias maneras que encontré en youtube).

¿Alguna idea de por qué hay una diferencia? ¿Me he equivocado en las cosas de la matriz de rotación? Tengo la opción de restringir la aplicación a una sola orientación, pero todavía me preocupa que la lectura de la brújula todavía no es muy preciso (a pesar de que después de la filtración es bastante estable)

public void onSensorChanged(SensorEvent event) { 
     if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) { 
      return; 
     } 

     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) mGravity = event.values; 
     if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic = event.values; 

     if (mGravity != null && mGeomagnetic != null) { 

      float[] rotationMatrixA = mRotationMatrixA; 
      if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) { 

       float[] rotationMatrixB = mRotationMatrixB; 

       Display display = getWindowManager().getDefaultDisplay(); 
       int deviceRot = display.getRotation(); 

       switch (deviceRot) 
       { 
       // portrait - normal 
       case Surface.ROTATION_0: SensorManager.remapCoordinateSystem(rotationMatrixA, 
         SensorManager.AXIS_X, SensorManager.AXIS_Z, 
         rotationMatrixB); 
       break; 
       // rotated left (landscape - keys to bottom) 
       case Surface.ROTATION_90: SensorManager.remapCoordinateSystem(rotationMatrixA, 
         SensorManager.AXIS_Z, SensorManager.AXIS_MINUS_X, 
         rotationMatrixB); 
       break; 
       // upside down 
       case Surface.ROTATION_180: SensorManager.remapCoordinateSystem(rotationMatrixA, 
         SensorManager.AXIS_X, SensorManager.AXIS_Z, 
         rotationMatrixB); 
       break; 
       // rotated right 
       case Surface.ROTATION_270: SensorManager.remapCoordinateSystem(rotationMatrixA, 
         SensorManager.AXIS_MINUS_Z, SensorManager.AXIS_X, 
         rotationMatrixB); 
       break; 

       default: break; 
       } 

       float[] dv = new float[3]; 
       SensorManager.getOrientation(rotationMatrixB, dv); 
       // add to smoothing filter 
       fd.AddLatest((double)dv[0]); 
      } 
      mDraw.invalidate();  
     } 
    } 

Respuesta

10

probar este

public void onSensorChanged(SensorEvent event) { 
    if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) { 
     return; 
    } 

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) mGravity = event.values.clone(); 
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic = event.values.clone(); 

    if (mGravity != null && mGeomagnetic != null) { 

     float[] rotationMatrixA = mRotationMatrixA; 
     if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) { 

      float[] rotationMatrixB = mRotationMatrixB; 
      SensorManager.remapCoordinateSystem(rotationMatrixA, 
        SensorManager.AXIS_X, SensorManager.AXIS_Z, 
        rotationMatrixB); 
      float[] dv = new float[3]; 
      SensorManager.getOrientation(rotationMatrixB, dv); 
      // add to smoothing filter 
      fd.AddLatest((double)dv[0]); 
     } 
     mDraw.invalidate();  
    } 
} 

No necesita la instrucción de cambio, parece haber mucha confusión con respecto a getRotationMatrix, remapCoordinateSystem y getOrientation de las preguntas de stackoverflow.
Probablemente escribiré una explicación detallada de estos en el futuro cercano.

+0

Hombre! He estado buscando SO durante más de 2 horas, y hay muchas respuestas INCORRECTAS. La tuya es la primera que realmente funciona correctamente para mí. Gracias por esto. – BoD

+0

He copiado y editado la publicación. No me di cuenta de que Mush tenía mGravity = event.values, debería ser event.values.clone(). Lo mismo para mGeomagnetic –

+0

'SensorManager.remapCoordinateSystem' es la solución. Gracias. –

1

La respuesta de Hoan es realmente incorrecta porque no tiene en cuenta la rotación de la pantalla. This es la respuesta correcta.

Cuestiones relacionadas