2015-04-04 77 views
1

我創建了一個用於測試目的的指南針應用程序,它工作得很好,箭頭圖像指向北極,但它變化太大,使得左右移動很小的移動即使設備沒有移動,也是毫秒。忽略來自SensorEventListener(羅盤應用程序)的小改動

我的問題是如何忽略這些小的變化?謝謝

public class Compass implements SensorEventListener { 
private static final String TAG = "Compass"; 

private SensorManager sensorManager; 
private Sensor gsensor; 
private Sensor msensor; 
private float[] mGravity = new float[3]; 
private float[] mGeomagnetic = new float[3]; 
private float azimuth = 0f; 
private float currectAzimuth = 0; 

// compass arrow to rotate 
public ImageView arrowView = null; 

public Compass(Context context) { 
    sensorManager = (SensorManager) context 
      .getSystemService(Context.SENSOR_SERVICE); 
    gsensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
    msensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 
} 

public void start() { 
    sensorManager.registerListener(this, gsensor, 
      SensorManager.SENSOR_DELAY_GAME); 
    sensorManager.registerListener(this, msensor, 
      SensorManager.SENSOR_DELAY_GAME); 
} 

public void stop() { 
    sensorManager.unregisterListener(this); 
} 

private void adjustArrow() { 
    if (arrowView == null) { 
     Log.i(TAG, "arrow view is not set"); 
     return; 
    } 

    Log.i(TAG, "will set rotation from " + currectAzimuth + " to " 
      + azimuth); 

    Animation an = new RotateAnimation(-currectAzimuth, -azimuth, 
      Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 
      0.5f); 
    currectAzimuth = azimuth; 

    an.setDuration(500); 
    an.setRepeatCount(0); 
    an.setFillAfter(true); 

    arrowView.startAnimation(an); 
} 

@Override 
public void onSensorChanged(SensorEvent event) { 
    final float alpha = 0.97f; 

    synchronized (this) { 
     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 

      mGravity[0] = alpha * mGravity[0] + (1 - alpha) 
        * event.values[0]; 
      mGravity[1] = alpha * mGravity[1] + (1 - alpha) 
        * event.values[1]; 
      mGravity[2] = alpha * mGravity[2] + (1 - alpha) 
        * event.values[2]; 

      // mGravity = event.values; 

      // Log.e(TAG, Float.toString(mGravity[0])); 
     } 

     if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
      // mGeomagnetic = event.values; 

      mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha) 
        * event.values[0]; 
      mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha) 
        * event.values[1]; 
      mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha) 
        * event.values[2]; 
      // Log.e(TAG, Float.toString(event.values[0])); 

     } 

     float R[] = new float[9]; 
     float I[] = new float[9]; 
     boolean success = SensorManager.getRotationMatrix(R, I, mGravity, 
       mGeomagnetic); 
     if (success) { 
      float orientation[] = new float[3]; 
      SensorManager.getOrientation(R, orientation); 
      // Log.d(TAG, "azimuth (rad): " + azimuth); 
      azimuth = (float) Math.toDegrees(orientation[0]); // orientation 
      azimuth = (azimuth + 360) % 360; 
      // Log.d(TAG, "azimuth (deg): " + azimuth); 
      adjustArrow(); 
     } 
    } 
} 

@Override 
public void onAccuracyChanged(Sensor sensor, int accuracy) { 
} 
+0

如果你可以測量微小的變化。然後,您可以設置一個最小閾值,如果該變化大於閾值,則只顯示它。 – 2015-04-04 13:45:16

+0

保留歷史記錄並取平均值。請參閱http://stackoverflow.com/questions/17979238/android-getorientation-azimuth-gets-polluted-when-phone-is-tilted/17981374#17981374 – 2015-04-05 21:08:51

回答

0

加速度計非常敏感。

onSensorChanged即使在稍有移動的情況下也會被傳感器type_accelerometer觸發。

檢查event.values [0],event.values [1]和event.values [2]值(設置一個閾值,指南針將響應),其實質上是x,y和z co從屬加速度矢量值。

您也可以在加速計上使用濾波器。

這是一個低切濾波器:

public void onSensorChanged(SensorEvent se) { 
    float x = se.values[0]; 
    float y = se.values[1]; 
    float z = se.values[2]; 
    mAccelLast = mAccelCurrent; 
    mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z)); 
    float delta = mAccelCurrent - mAccelLast; 
    mAccel = mAccel * 0.9f + delta; // perform low-cut filter 
} 

然後:

if(mAccel>12||status) 
    { 
    //move compass : 
     float orientation[] = new float[3]; 
     SensorManager.getOrientation(R, orientation); 
     // Log.d(TAG, "azimuth (rad): " + azimuth); 
     azimuth = (float) Math.toDegrees(orientation[0]); // orientation 
     azimuth = (azimuth + 360) % 360; 
     // Log.d(TAG, "azimuth (deg): " + azimuth); 
     adjustArrow(); 
    } 
+0

感謝您的回答,但是什麼是mAccelLast,mAccelCurrent和mAccel? – 4mahmoud 2015-04-04 14:19:19

+0

mAccelCurrent - > x,y,z軸加速度計讀數平均差mAccelLast - > mAccelCurrent的最後一個值mAccel - >是基於先前值計算的濾波器值,可用作最小閾值,羅盤 – Kay 2015-04-04 14:39:29

+0

這沒有奏效,請你能幫我編輯我的代碼,上面有你提出的改變嗎?我很感激這個 – 4mahmoud 2015-04-04 16:24:40