2012-06-06 65 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說某些參數可以爲空)。我甚至嘗試將數據傳遞給每個參數,並且仍然有NullPointerException

我的問題是,我需要傳遞給getRotationMatrix方法的正確數據是什麼?

回答

0

這是我的代碼,它沒有NPE。請注意,我只有一個監聽器,但您必須註冊才能聽到兩個傳感器(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方法執行傳感器結果的一些平滑和看起來像(α值可以從0到1,其中1表示沒有平滑在所有):

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

至於​​位 - 我不確定它是否需要,只是在某處閱讀並添加它。

6

我發現一個非常簡單的方法是在SDK示例AccelerometerPlay中使用的方法。

首先,你讓你的顯示器是這樣,例如在的onResume():

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

然後()你可以使用這個簡單的代碼:

@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; 
    } 
} 

希望這會有所幫助。