2012-06-06 7 views
1

나는 자연스럽게 방향이 바뀌었을 때 좌표계를 다시 매핑하려고합니다. 전화를 사용할 때 가로로 보일 때처럼 세로로 잡고있는 것처럼 동일한 값을 읽어야합니다.센서 좌표를 다시 매핑

회전이 Surface.ROTATION_90인지 확인하고, 그렇다면 좌표계를 다시 매핑합니다.

나는 그것을 올바르게하는 법을 거의 모르고 약간의 지침을 사용할 수 있다고 인정한다.

그래서, 당신은이 두 가지 방법을 실행해야합니다

SensorManager.getRotationMatrix(inR, I, grav, mag); 
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outR); 

이러한 방법으로 전달하는 데 무엇을 필요이야? 새로운 플로트 배열을 만든 다음 orientationsensor 데이터 만 mag 필드에 전달했습니다. 이는 작동하지 않았습니다. 그래서, 나는 가속도 센서와 자기장 센서를 등록했다. 두 사람의 데이터를 getRotatioMatrix 메소드로 보내면 항상 NullPointerException이됩니다 (JavaDoc에서 일부 인수가 null 일 수 있다고하더라도). 심지어 각 인수에 데이터를 전달하려고 시도했지만 여전히 NullPointerException이 있습니다.

제 질문은 getRotationMatrix 메서드에 전달해야하는 적절한 데이터는 무엇입니까?

답변

0

이것은 내 코드이며 NPE 없이도 작동합니다. 참고, 하나의 Listener 만 있지만 센서 (ACCELEROMETER 및 MAGNETICFIELD)를 수신하려면 등록해야합니다.

private SensorEventListener mOrientationSensorsListener = new SensorEventListener() { 

    private float[] mR = new float[9]; 
    private float[] mRemappedR = new float[9]; 
    private float[] mGeomagneticVector = new float[3]; 
    private float[] mGravityVector = new float[3]; 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     synchronized(this) { 
      if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
       mGravityVector = Util.exponentialSmoothing(event.values, mGravityVector, 0.2f); 
      } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
       mGeomagneticVector = Util.exponentialSmoothing(event.values, mGeomagneticVector, 0.5f); 

       SensorManager.getRotationMatrix(mR, null, mGravityVector, mGeomagneticVector); 
       SensorManager.remapCoordinateSystem(mR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, mRemappedR); 
      } 
     } 
    } 

exponentialSmoothing 방법은 센서 결과 일부 평활화를 수행하고 (알파 값이 1이 전혀 평활화 의미 1 0에서 이동 가능)처럼 보인다 :로서는

public static float[] exponentialSmoothing(float[] input, float[] output, float alpha) { 
    for (int i=0; i<input.length; i++) { 
     output[i] = output[i] + alpha * (input[i] - output[i]); 
    } 
    return output; 
} 

synchronized 비트 - 필자는 이것이 필요하다고 확신하지 못하고 그냥 어딘가에 읽고 추가했다.

6

아주 간단한 방법은 SDK 샘플 AccelerometerPlay에 사용 된 방법입니다.

먼저 당신은 onResume() 예를 들면, 이런 디스플레이를 얻을 :이 도움이 될 것입니다

@Override 
public void onSensorChanged(SensorEvent event) { 
    if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) 
     return; 

    switch (mDisplay.getRotation()) { 
     case Surface.ROTATION_0: 
      mSensorX = event.values[0]; 
      mSensorY = event.values[1]; 
      break; 
     case Surface.ROTATION_90: 
      mSensorX = -event.values[1]; 
      mSensorY = event.values[0]; 
      break; 
     case Surface.ROTATION_180: 
      mSensorX = -event.values[0]; 
      mSensorY = -event.values[1]; 
      break; 
     case Surface.ROTATION_270: 
      mSensorX = event.values[1]; 
      mSensorY = -event.values[0]; 
      break; 
    } 
} 

희망 : onSensorChanged에서 다음

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); 
mDisplay = windowManager.getDefaultDisplay(); 

()이 간단한 코드를 사용할 수 있습니다.