Estoy trabajando con datos GPS, obteniendo valores cada segundo y mostrando la posición actual en un mapa. El problema es que a veces (especialmente cuando la precisión es baja) los valores varían mucho, lo que hace que la posición actual "salte" entre puntos distantes en el mapa.
Me preguntaba acerca de algún método lo suficientemente fácil como para evitar esto. Como primera idea, pensé en descartar valores con precisión más allá de cierto umbral, pero creo que hay otras formas mejores de hacerlo. ¿Cuál es la forma habitual en que los programas realizan esto?
Respuestas:
Aquí hay un filtro simple de Kalman que podría usarse exactamente para esta situación. Vino de un trabajo que hice en dispositivos Android.
La teoría general del filtro de Kalman se trata de estimaciones para vectores, con la precisión de las estimaciones representadas por matrices de covarianza. Sin embargo, para estimar la ubicación en dispositivos Android, la teoría general se reduce a un caso muy simple. Los proveedores de ubicación de Android dan la ubicación como latitud y longitud, junto con una precisión que se especifica como un solo número medido en metros. Esto significa que, en lugar de una matriz de covarianza, la precisión en el filtro de Kalman se puede medir con un solo número, aunque la ubicación en el filtro de Kalman se mide con dos números. También se puede ignorar el hecho de que la latitud, la longitud y los metros son efectivamente todas las unidades diferentes, porque si coloca factores de escala en el filtro de Kalman para convertirlos a todos en las mismas unidades,
El código podría mejorarse, ya que supone que la mejor estimación de la ubicación actual es la última ubicación conocida, y si alguien se está moviendo, debería ser posible usar los sensores de Android para producir una mejor estimación. El código tiene un único parámetro libre Q, expresado en metros por segundo, que describe la rapidez con que decae la precisión en ausencia de nuevas estimaciones de ubicación. Un parámetro Q más alto significa que la precisión disminuye más rápido. Los filtros Kalman generalmente funcionan mejor cuando la precisión disminuye un poco más rápido de lo que cabría esperar, por lo que para caminar con un teléfono Android encuentro que Q = 3 metros por segundo funciona bien, aunque generalmente camino más lento que eso. Pero si viaja en un automóvil rápido, obviamente debería usarse un número mucho mayor.
fuente
Q_metres_per_second
corresponde a la variablesigma
en la sección "Procesos relacionados" en ese artículo de Wikipedia.Q_metres_per_second
es una desviación estándar y se mide en metros, por lo que metros y no metros / segundos son sus unidades. Corresponde a la desviación estándar de la distribución después de que haya transcurrido 1 segundo.Lo que estás buscando se llama Filtro Kalman . Se usa con frecuencia para suavizar los datos de navegación . No es necesariamente trivial, y hay muchos ajustes que puede hacer, pero es un enfoque muy estándar y funciona bien. Hay una biblioteca KFilter disponible que es una implementación de C ++.
Mi siguiente alternativa sería el ajuste de mínimos cuadrados . Un filtro de Kalman suavizará los datos teniendo en cuenta las velocidades, mientras que un enfoque de ajuste de mínimos cuadrados solo usará información posicional. Aún así, es definitivamente más sencillo de implementar y comprender. Parece que la Biblioteca Científica GNU puede tener una implementación de esto.
fuente
Esto podría llegar un poco tarde ...
Escribí este KalmanLocationManager para Android, que envuelve los dos proveedores de ubicación más comunes, Red y GPS, kalman-filtra los datos y entrega actualizaciones a
LocationListener
(como los dos proveedores 'reales').Lo uso principalmente para "interpolar" entre lecturas, para recibir actualizaciones (predicciones de posición) cada 100 milis por ejemplo (en lugar de la velocidad máxima de gps de un segundo), lo que me da una mejor velocidad de cuadros al animar mi posición.
En realidad, utiliza tres filtros kalman, en cada dimensión: latitud, longitud y altitud. Son independientes, de todos modos.
Esto hace que las matemáticas de la matriz sean mucho más fáciles: en lugar de usar una matriz de transición de estado de 6x6, uso 3 matrices diferentes de 2x2. En realidad en el código, no uso matrices en absoluto. Resolvió todas las ecuaciones y todos los valores son primitivos (doble).
El código fuente está funcionando y hay una actividad de demostración. Perdón por la falta de javadoc en algunos lugares, me pondré al día.
fuente
No debe calcular la velocidad a partir del cambio de posición por tiempo. El GPS puede tener posiciones inexactas, pero tiene una velocidad precisa (superior a 5 km / h). Así que usa la velocidad del sello de ubicación GPS. Y además, no debes hacer eso con el curso, aunque funciona la mayoría de las veces.
Las posiciones de GPS, tal como se entregan, ya están filtradas por Kalman, probablemente no pueda mejorar, en el procesamiento posterior generalmente no tiene la misma información que el chip GPS.
Puede suavizarlo, pero esto también introduce errores.
Solo asegúrese de eliminar las posiciones cuando el dispositivo se detiene, esto elimina las posiciones de salto, que algunos dispositivos / Configuraciones no eliminan.
fuente
Usualmente uso los acelerómetros. Un cambio repentino de posición en un período corto implica una alta aceleración. Si esto no se refleja en la telemetría del acelerómetro, es casi seguro que se debe a un cambio en los "tres mejores" satélites utilizados para calcular la posición (a lo que me refiero como teletransportación GPS).
Cuando un activo está en reposo y saltando debido al teletransporte GPS, si calcula progresivamente el centroide, efectivamente está intersectando un conjunto de conchas cada vez más grande, mejorando la precisión.
Para hacer esto cuando el activo no está en reposo, debe estimar su probable próxima posición y orientación en función de la velocidad, el rumbo y los datos de aceleración lineal y rotacional (si tiene giroscopios). Esto es más o menos lo que hace el famoso filtro K. Puede obtener todo en hardware por alrededor de $ 150 en un AHRS que contiene todo menos el módulo GPS, y con un conector para conectar uno. Tiene su propia CPU y Kalman filtrado a bordo; Los resultados son estables y bastante buenos. La guía de inercia es altamente resistente a la fluctuación pero se desplaza con el tiempo. El GPS es propenso a las fluctuaciones, pero no cambia con el tiempo, prácticamente se hicieron para compensarse entre sí.
fuente
Un método que usa menos matemática / teoría es muestrear 2, 5, 7 o 10 puntos de datos a la vez y determinar los valores atípicos. Una medida menos precisa de un valor atípico que un filtro de Kalman es utilizar el siguiente algoritmo para tomar todas las distancias entre pares entre puntos y tirar el que está más alejado de los demás. Por lo general, esos valores se reemplazan con el valor más cercano al valor periférico que está reemplazando
Por ejemplo
Suavizado en cinco puntos de muestra A, B, C, D, E
ATOTAL = SUMA de distancias AB AC AD AE
BTOTAL = SUMA de distancias AB BC BD BE
CTOTAL = SUMA de distancias AC BC CD CE
DTOTAL = SUMA de distancias DA DB DC DE
ETOTAL = SUMA de distancias EA EB EC DE
Si BTOTAL es mayor, reemplazaría el punto B con D si BD = min {AB, BC, BD, BE}
Este suavizado determina valores atípicos y puede aumentarse utilizando el punto medio de BD en lugar del punto D para suavizar la línea posicional. Su kilometraje puede variar y existen soluciones matemáticamente más rigurosas.
fuente
En cuanto al ajuste de mínimos cuadrados, aquí hay un par de otras cosas para experimentar:
El hecho de que su ajuste sea de mínimos cuadrados no significa que tenga que ser lineal. Puede ajustar por mínimos cuadrados una curva cuadrática a los datos, entonces esto se ajustaría a un escenario en el que el usuario está acelerando. (Tenga en cuenta que por ajuste de mínimos cuadrados me refiero a usar las coordenadas como la variable dependiente y el tiempo como la variable independiente).
También puede intentar ponderar los puntos de datos según la precisión informada. Cuando la precisión es baja, esos puntos de datos son más bajos.
Otra cosa que quizás desee probar es en lugar de mostrar un solo punto, si la precisión es baja, muestre un círculo o algo que indique el rango en el que el usuario podría basarse en la precisión informada. (Esto es lo que hace la aplicación Google Maps integrada del iPhone).
fuente
También puedes usar una spline. Ingrese los valores que tiene e interpole puntos entre sus puntos conocidos. Al vincular esto con un ajuste de mínimos cuadrados, un promedio móvil o un filtro kalman (como se menciona en otras respuestas) le da la capacidad de calcular los puntos entre sus puntos "conocidos".
Ser capaz de interpolar los valores entre sus conocimientos le proporciona una transición suave y agradable y una aproximación / razonable / de qué datos estarían presentes si tuviera una mayor fidelidad. http://en.wikipedia.org/wiki/Spline_interpolation
Diferentes splines tienen diferentes características. Los que he visto más comúnmente utilizados son Akima y splines cúbicos.
Otro algoritmo a considerar es el algoritmo de simplificación de línea Ramer-Douglas-Peucker, que se usa con bastante frecuencia en la simplificación de datos GPS. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )
fuente
Volviendo a los filtros Kalman ... Encontré una implementación en C para un filtro Kalman para datos GPS aquí: http://github.com/lacker/ikalman No lo he probado todavía, pero parece prometedor.
fuente
Asignado a CoffeeScript si alguien está interesado. ** editar -> perdón por usar backbone también, pero entiendes la idea.
Modificado ligeramente para aceptar una baliza con attribs
fuente
@lat
y@lng
se configuran. Debería ser+=
más que=
He transformado el código Java de @Stochastically a Kotlin
fuente
Aquí hay una implementación de Javascript de la implementación Java de @ Stochastically para cualquiera que lo necesite:
Ejemplo de uso:
fuente