6

Приложение для дополненной реальности нуждается в компасе, относящемся к просмотру камеры, и есть множество примеров получения направления от сенсомена.Направление компаса различно в зависимости от ориентации телефона

Однако я нахожу, что результирующее значение отличается в зависимости от ориентации телефона - пейзаж повернут вправо примерно на 10 градусов по сравнению с ландшафтом, повернутым влево (разница между ROTATION_0 и ROTATION_180 меньше, но все же отличается). Это различие достаточно, чтобы разрушить любой эффект AR.

Какое-то отношение к калибровке? (Я не уверен, что делаю цифру 8 штук правильно - я пробовал различные способы, которые я нашел на youtube).

Любые идеи, почему есть разница? Я испортил материал матрицы вращения? У меня есть возможность ограничивать приложение к одной ориентации, но она по-прежнему беспокоит меня, что показания компаса еще не очень точно (даже после фильтрации она довольно стабильна)

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();  
     } 
    } 

ответ

10

Попробуйте

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();  
    } 
} 

Вам не нужен оператор switch, похоже, существует много путаницы в отношении getRotationMatrix, remapCoordinateSystem и getOrientation из вопросов stackoverflow.
Я, вероятно, напишу подробное объяснение этого в ближайшем будущем.

+0

Человек! Я искал SO более двух часов, и есть много НЕПРАВИЛЬНЫХ ответов. Твой первый, который действительно работает правильно для меня. Спасибо за это. – BoD

+0

Я скопировал и отредактировал сообщение. Я не понимал, что у Mush есть mGravity = event.values, это должно быть event.values.clone(). То же самое для mGeomagnetic –

+0

'SensorManager.remapCoordinateSystem' - это решение. Благодарю. –

1

Ответ Хоана фактически неверен, поскольку он не учитывает поворот дисплея. This - правильный ответ.