2015-04-04 4 views
1

Я создаю приложение компаса для целей тестирования, и оно отлично работает, а изображение стрелки указывает на северный полюс, но оно слишком сильно меняется и делает очень маленькие движения вправо и влево миллисекунды, даже если устройство не движется.Игнорировать небольшие изменения от SensorEventListener (приложение Compass)

Мой вопрос в том, как игнорировать эти небольшие изменения? thank you

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

Если вы можете измерить небольшие изменения. Затем вы можете установить минимальное пороговое значение, если изменение превышает пороговое значение, а затем покажет его. –

+0

Сохраните историю и усредните значения. См. Http://stackoverflow.com/questions/17979238/android-getorientation-azimuth-gets-polluted-when-phone-is-tilted/17981374#17981374 –

ответ

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

+0

mAccelCurrent -> x, y, z показания акселерометра оси означают diff mAccelLast -> Последнее значение mAccelCurrent mAccel -> - значение фильтра, рассчитанное на основе предыдущих значений, и может использоваться как минимальный порог, выше которого что-то срабатывает, как перемещение compass – Kay

+0

Это не помогло, пожалуйста, можете ли вы помочь мне изменить мой код выше с внесенными вами изменениями? я очень по достоинству оценю – 4mahmoud

Смежные вопросы