2012-09-04 2 views
0

Android에서 카메라 방향을 찾으려고합니다. 나는 초상화에서 완벽하게 작동하는 코드를 가지고있다. (천천히 원을 그리며 1 초 간격으로 업데이트를 시도하여 테스트한다.) 그러나 프리 랜드에서 전혀 작동하지 않는다. 숫자는 무작위로 변하는 것처럼 보인다. 또한 초상화에서 풍경으로 전환 한 후에도 완전히 파멸합니다. 여기 내 코드가가로 모드 또는 방향 반전 후 센서에서 방향을 얻지 못합니다.

public void onSensorChanged(SensorEvent event) { 

    switch (event.sensor.getType()) { 
    case Sensor.TYPE_ACCELEROMETER: 
     accelerometerValues = event.values.clone(); 

     break; 
    case Sensor.TYPE_MAGNETIC_FIELD: 
     geomagneticMatrix = event.values.clone(); 
     break; 
    default: 
     break; 
    } 

    if (geomagneticMatrix != null && accelerometerValues != null) { 

     float[] R = new float[16]; 
     float[] I = new float[16]; 
     float[] outR = new float[16]; 

     //Get the rotation matrix, then remap it from camera surface to world coordinates 
     SensorManager.getRotationMatrix(R, I, accelerometerValues, geomagneticMatrix); 
     SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR); 
     float values[] = new float[4]; 
     SensorManager.getOrientation(outR,values); 
     float direction = normalizeDegrees((float) Math.toDegrees(values[0])); 
     float pitch = normalizeDegrees((float) Math.toDegrees(values[1])); 
     float roll = normalizeDegrees((float) Math.toDegrees(values[2])); 

     if((int)direction != (int)lastDirection){ 
      lastDirection = direction; 
      for(CompassListener listener: listeners){ 
       listener.onDirectionChanged(lastDirection, pitch, roll); 
      } 
     } 
    } 
} 

내가 뭘 잘못하고있어? 나는 이것을 100 % 이해하지 못한다고 나는 자유롭게 인정한다. 나는 또한 Google이 오리엔테이션 센서를 더 이상 사용하지 않는 이유를 알지 못합니다. 이는 일반적인 욕망처럼 보입니다.

답변

1

세로에서 가로로 변경하면 가속도계 축이 변경되는 것을 고려 했습니까? Y 축과 마찬가지로 Z 축이됩니다. 이것은 이상한 행동의 한 원인 일 수 있습니다.

+0

나는 그것을 생각해 보았습니다. 여기에는 y 축과 x 축 전환이 있습니다 (z는 항상 화면을 통해 나옵니다). 그러나 그것은 정확하게 움직이는 것처럼 보이지 않습니다. 나는 3을 모두 화면에 버렸고 그 중 아무도 제대로 움직이지 않았습니다. 선회 후 1 초 간격으로 미친듯한 샘플을 점프하는 경우에도 방향은 180도, 320도, 280도, 220도, 180도, 300도, 200 시가 될 때 읽을 수 있습니다. –

0

나는 그것을 해결 한 것처럼 보였거나, 적어도 문제가 무엇인지를 알 수있는 지점까지 개선했다. 나는 단일 센서 읽기를 제공하는 대신에 마지막 읽기를 기억하고 델타를 적용하는 필터를 넣었습니다. 각각의 새 센서 포인트는 최대 5도까지 추가 할 수 있습니다. 이것은 기묘한 홉을 완전히 걸러 내고 값으로 수렴하도록합니다. 나는 가끔씩 이상한 점프를 보지만, 필자는보다 정교한 필터가 필요할 것이라고 생각한다. 새 코드 :

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

    switch (event.sensor.getType()) { 
    case Sensor.TYPE_ACCELEROMETER: 
     accelerometerValues = event.values.clone(); 

     break; 
    case Sensor.TYPE_MAGNETIC_FIELD: 
     geomagneticMatrix = event.values.clone(); 
     break; 
    } 

    if (geomagneticMatrix != null && accelerometerValues != null) { 

     float[] R = new float[16]; 
     float[] I = new float[16]; 
     float[] outR = new float[16]; 

     //Get the rotation matrix, then remap it from camera surface to world coordinates 
     SensorManager.getRotationMatrix(R, I, accelerometerValues, geomagneticMatrix); 
     SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR); 
     float values[] = new float[4]; 
     SensorManager.getOrientation(outR,values); 

     int direction = filterChange(normalizeDegrees(Math.toDegrees(values[0]))); 
     int pitch = normalizeDegrees(Math.toDegrees(values[1])); 
     int roll = normalizeDegrees(Math.toDegrees(values[2])); 
     if((int)direction != (int)lastDirection){ 
      lastDirection = (int)direction; 
      lastPitch = (int)pitch; 
      lastRoll = (int)roll; 
      for(CompassListener listener: listeners){ 
       listener.onDirectionChanged(lastDirection, pitch, roll); 
      } 
     } 
    } 
} 

//Normalize a degree from 0 to 360 instead of -180 to 180 
private int normalizeDegrees(double rads){ 
    return (int)((rads+360)%360); 
} 

//We want to ignore large bumps in individual readings. So we're going to cap the number of degrees we can change per report 
private int filterChange(int newDir){ 
    int change = newDir - lastDirection; 
    int circularChange = newDir-(lastDirection+360); 
    int smallestChange; 
    if(Math.abs(change) < Math.abs(circularChange)){ 
     smallestChange = change; 
    } 
    else{ 
     smallestChange = circularChange; 
    } 
    smallestChange = Math.max(Math.min(change,5),-5); 
    return lastDirection+smallestChange; 
} 
+0

빠른 설명 - 3과 -3의 값은 바운스 보호 기능을 제공하는 것처럼 보입니다. –

관련 문제