2009-12-10 21 views
8

Estoy tratando de filtrar el ruido del sensor de orientación/brújula en mi teléfono mágico.Android algoritmo de ruido de brújula

Algunas de las lecturas parecen estar a 90-180 grados y hay mucha agitación. He intentado cosas diferentes con un éxito limitado, por lo que me preguntaba si alguien podría recomendar un algoritmo para filtrar este tipo de ruido para obtener un resultado estable.

BR, Mads

Respuesta

14

Necesita filtro de paso bajo. Hay explicación y algoritmo simple en wikipedia

+7

Consulte la excelente publicación de blog de Thom Nichols para ver un ejemplo de cómo implementar un filtro de paso bajo - Parte 1 (http://blog.thomnichols.org/2011/08/smoothing-sensor-data-with-a-low -pass-filter) y parte 2 (http://blog.thomnichols.org/2012/06/smoothing-sensor-data-part-2) –

+0

@JimJeffers Esta implementación es simple y brillante. Se aplicó mucho. Gracias ! – Shlublu

2

¿Qué ha probado? ¿Cuántas lecturas obtienes por segundo?

Sugeriría algo como un promedio de la última X cantidad de lecturas para deshacerse de los "jiggles" y desechar cualquier lectura que sea muy diferente de la dirección actual para detener cualquier "salto" loco de valores. Dependiendo de la cantidad de lecturas que reciba y del promedio que esté haciendo, su aplicación puede perder capacidad de respuesta.

El siguiente enlace puede ser útil. http://www.chem.uoa.gr/applets/appletsmooth/appl_smooth2.html

1

Si obtiene una cantidad significativa de valores completamente erróneos, probablemente no quiera promediarlos. Podría intentar aplicar primero un filtro de mediana: tomar N muestras, calcular la mediana y arrojar algo más que + - algún valor de umbral. Puede aplicar un filtro de suavizado después de eso.

3

Me deshice de la mayor parte del ruido simplemente usando un tiempo de actualización más lento. No estoy seguro de si Android tiene un filtro incorporado para estos, pero parece estabilizarse mucho. Algo así como:

mSensorManager.registerListener( 
    mSensorListener, 
    mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), 
    // SENSOR_DELAY_UI, instead of SENDOR_DELAY_FASTEST (or similar) 
    // seems to iron out a lot of the jitter 
    SensorManager.SENSOR_DELAY_UI 
); 

SensorManager ofertas:

  • SENSOR_DELAY_FASTEST: obtener datos de los sensores lo más rápido posible
  • SENSOR_DELAY_GAME: tasa adecuada para juegos
  • SENSOR_DELAY_NORMAL: tasa (por defecto) adecuadas para la orientación de la pantalla cambios
  • SENSOR_DELAY_UI: tasa adecuada para la interfaz de usuario
0

Si sus lecturas están "90-180 grados apagadas", entonces o necesita calibrar la brújula o su sensor está defectuoso.

Ciertamente, el sensor magnético tiene mucha agitación, pero la "desviación estándar" de dicho ruido es de aproximadamente 4 grados. Puede elegir una variedad de filtros matemáticos (paso bajo, Kalman) y algoritmos (promedio, caída de lecturas espurias) para aplicar a las mediciones que le pueden dar resultados aceptables.

0

¿Está utilizando:

List<Sensor> sens = mySensorManager.getSensorList(Sensor.TYPE_ORIENTATION); 

Es posible que se registra 2 asas de sensores separados que están siendo dirigidas tanto a su método de onSensorChanged. Ahora, en mi método onSensorChanged, envío el valor de orientación al método primario o secundario en función del nombre del proveedor.Así que pruebe este código:

Sensor sen = e.sensor; 
    double bearing = 0; 
    if (sen.getType()==Sensor.TYPE_ORIENTATION) { 
     bearing = e.values[SensorManager.DATA_X]; 
    } 
    if (sen.getVendor().equals(sensorVendors[0])) { 
     myCompassView.setBearing(bearing); 
    } else { 
     myCompassView.setSecondaryBearing(bearing); 
    } 
4

Esto es muy tarde, pero podría ayudar a las personas como yo que llegamos a esta pregunta.

Use el sensor de vector de rotación de tipo. No es necesario usar un filtro de paso bajo o calcular un valor promedio de los últimos valores de x sensor.

Aquí hay algo de código:

private float[] mMatrixR = new float[9]; 
private float[] mMatrixValues = new float[3]; 

@Override 
public void onSensorChanged(SensorEvent event) { 
    switch (event.sensor.getType()) { 
     case Sensor.TYPE_ROTATION_VECTOR: 

      // Get rotation matrix 
      SensorManager.getRotationMatrixFromVector(mMatrixR, event.values); 

      SensorManager.getOrientation(mMatrixR, mMatrixValues); 

      // Use this value in degrees 
      mAzimuth = Math.toDegrees(mMatrixValues[0]); 

    } 

me encontré con los valores muy rápido y sin problemas y el uso de estos en mi aplicación. Utilicé el acelerómetro y el magnetómetro como respaldo en caso de que el vector de tipo rotación no esté presente en el dispositivo, es un sensor basado en software (fusión del sensor) que utiliza el magnetómetro, el acelerómetro y el giroscopio (si está presente).