Algoritmo de ruido de compás de Android

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

Algunas de las lecturas parecen ser de 90-180 grados y hay un montón de jiggle. He intentado cosas diferentes con éxito limitado, así que me preguntaba si alguien podría recomendar un algoritmo para filtrar este tipo de ruido para obtener una salida estable.

BR, Mads

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

Me deshice de la mayor parte del ruido con solo usar un tiempo de actualización más lento. No estoy seguro de si Android tiene un filtro incorporado para estos, pero se parece a stabalize mucho. Algo 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 ofrece:

  • SENSOR_DELAY_FASTEST : obtenga los datos del sensor lo más rápido posible
  • SENSOR_DELAY_GAME : tasa adecuada para juegos
  • SENSOR_DELAY_NORMAL : tasa (predeterminada) adecuada para los cambios de orientación de la pantalla
  • SENSOR_DELAY_UI : tasa adecuada para la interfaz de usuario

Esto es muy tarde, pero podría ayudar a gente como yo que llegó a esta pregunta.

Utilice el sensor de vector de tipo de rotación. No es necesario utilizar un filtro de paso bajo o calcular un valor medio de los últimos valores del sensor x.

He aquí un 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]); } 

He encontrado los valores muy rápido y suave y utilizarlos en mi aplicación. Utilicé el acelerómetro y el magnetómetro como respaldo en caso de que el vector de tipo de rotación no esté presente en el dispositivo, es un sensor basado en software (fusión del sensor) que utiliza el magnetómetro, acelerómetro y girocompás (si está presente).

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

Yo sugeriría algo a lo largo de las líneas de un promedio de la última X número de lecturas para deshacerse de los "jiggles" y tirar todas las lecturas que son salvajemente diferentes de la dirección actual para detener cualquier loco "saltar" de los valores. Dependiendo de cuántas lecturas obtengas y de la cantidad de promedio que estás haciendo, es posible que tu aplicación pierda la capacidad de respuesta.

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

Si obtiene un número significativo de valores completamente erróneos, es probable que no quiera simplemente promediarlos. Podría intentar aplicar un filtro mediano primero – tomar N muestras, calcular la mediana y tirar algo más de + – algún valor umbral. Después puede aplicar un filtro de suavizado.

Si sus lecturas están "90-180 grados apagado", entonces usted necesita calibrar su compás, o su sensor es defectuoso.

Ciertamente, el sensor magnético tiene una gran cantidad de jiggle, pero la "desviación estándar" de dicho ruido es de unos 4 grados de distancia. Puede elegir una variedad de filtros matemáticos (paso bajo, Kalman) y algoritmos (promediar, leer lecturas falsas) para aplicar a las mediciones que pueden dar resultados aceptables.

Estas usando:

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

Es posible que esté registrando dos controladores de sensor independientes que están siendo dirigidos al método onSensorChanged. Ahora, en mi método onSensorChanged, estoy enviando el valor del rodamiento al método principal o secundario basado en el 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); } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.