6

Moja aplikacja rozszerzonej rzeczywistości wymaga widoku kompasu z widoku kamery, a jest wiele przykładów na uzyskanie wskazówki od sensormanager.Kierunek kompasu różni się w zależności od orientacji telefonu.

Jednak znajduję wynikową wartość różną w zależności od orientacji telefonu - krajobraz obrócony w prawo to około 10 stopni różny od krajobrazu obróconego w lewo (różnica między ROTATION_0 i ROTATION_180 jest mniejsza, ale wciąż inna). Ta różnica wystarczy, aby zepsuć efekt AR.

Czy ma to coś wspólnego z kalibracją? (Nie jestem przekonany, że poprawnie wykonuję figurę 8 razy - próbowałem różnych sposobów, które znalazłem na youtube).

Jakieś pomysły, dlaczego istnieje różnica? Czy zawiodłem na materiałach macierzy obrotowej? Mam możliwość ograniczenia aplikacji do pojedynczej orientacji, ale nadal mnie martwi, że odczyt kompasu nadal nie jest bardzo dokładny (choć po przefiltrowaniu jest dość stabilna)

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

Odpowiedz

10

Spróbuj

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

Nie potrzebujesz instrukcji switch, wydaje się, że istnieje wiele nieporozumień dotyczących getRotationMatrix, remapCoordinateSystem i getOrientation z pytań stackoverflow.
Prawdopodobnie napiszę szczegółowe wyjaśnienie tych problemów w najbliższej przyszłości.

+0

Mężczyzna! Szukałem SO przez ponad 2 godziny i jest wiele NIEPRAWIDŁOWYCH odpowiedzi. Twój jest pierwszy, który działa właściwie dla mnie. Dzięki za to. – BoD

+0

Skopiowałem i edytowałem wpis. Nie zdawałem sobie sprawy, że Mush miał mGravity = event.values, powinno to być event.values.clone(). To samo dla mGeomagnetycznego –

+0

'SensorManager.remapCoordinateSystem' jest rozwiązaniem. Dzięki. –

1

Odpowiedź Hoana jest w rzeczywistości niepoprawna, ponieważ nie uwzględnia rotacji ekranu. This to poprawna odpowiedź.