Estou trabalhando com dados de GPS, obtendo valores a cada segundo e exibindo a posição atual em um mapa. O problema é que, às vezes (especialmente quando a precisão é baixa), os valores variam muito, fazendo com que a posição atual "salte" entre pontos distantes no mapa.
Eu estava pensando sobre algum método fácil o suficiente para evitar isso. Como primeira idéia, pensei em descartar valores com precisão além de determinado limite, mas acho que existem outras maneiras melhores de fazer isso. Qual é a maneira usual pelos programas executarem isso?
Respostas:
Aqui está um filtro Kalman simples que pode ser usado exatamente nessa situação. Veio de algum trabalho que fiz em dispositivos Android.
A teoria geral dos filtros de Kalman trata de estimativas para vetores, com a precisão das estimativas representadas por matrizes de covariância. No entanto, para estimar a localização em dispositivos Android, a teoria geral se reduz a um caso muito simples. Os fornecedores de localização Android fornecem a localização como latitude e longitude, juntamente com uma precisão especificada como um número único medido em metros. Isso significa que, em vez de uma matriz de covariância, a precisão no filtro Kalman pode ser medida por um único número, mesmo que a localização no filtro Kalman seja medida por dois números. Além disso, o fato de latitude, longitude e metros serem efetivamente todas as unidades diferentes pode ser ignorado, porque se você colocar fatores de escala no filtro Kalman para convertê-los em unidades iguais,
O código pode ser aprimorado, pois assume que a melhor estimativa da localização atual é a última localização conhecida e, se alguém estiver em movimento, deve ser possível usar os sensores do Android para produzir uma estimativa melhor. O código possui um único parâmetro livre Q, expresso em metros por segundo, que descreve a rapidez com que a precisão diminui na ausência de novas estimativas de localização. Um parâmetro Q mais alto significa que a precisão diminui mais rapidamente. Os filtros Kalman geralmente funcionam melhor quando a precisão diminui um pouco mais rapidamente do que se poderia esperar, então, para andar com um telefone Android, acho que Q = 3 metros por segundo funciona bem, mesmo que eu geralmente ande mais devagar do que isso. Mas se estiver viajando em um carro veloz, obviamente deverá ser usado um número muito maior.
fonte
Q_metres_per_second
corresponde à variávelsigma
na seção "Processos relacionados" nesse artigo da Wikipedia.Q_metres_per_second
é um desvio padrão e é medido em metros; portanto, metros e não metros / segundos são suas unidades. Corresponde ao desvio padrão da distribuição após 1 segundo.O que você está procurando é chamado de Filtro Kalman . É frequentemente usado para suavizar dados de navegação . Não é necessariamente trivial, e você pode fazer muitos ajustes, mas é uma abordagem muito padrão e funciona bem. Existe uma biblioteca KFilter disponível, que é uma implementação em C ++.
Meu próximo substituto seria o mínimo de quadrados . Um filtro Kalman suavizará os dados, levando em consideração as velocidades, enquanto uma abordagem de ajuste de mínimos quadrados usará apenas informações posicionais. Ainda assim, é definitivamente mais simples de implementar e entender. Parece que a Biblioteca Científica GNU pode ter uma implementação disso.
fonte
Isso pode chegar um pouco tarde ...
Eu escrevi este KalmanLocationManager para Android, que agrupa os dois provedores de localização mais comuns, Rede e GPS, kalman filtra os dados e fornece atualizações para um
LocationListener
(como os dois provedores 'reais').Eu o uso principalmente para "interpolar" entre leituras - para receber atualizações (previsões de posição) a cada 100 milis por exemplo (em vez da taxa máxima de gps de um segundo), o que me proporciona uma melhor taxa de quadros ao animar minha posição.
Na verdade, ele usa três filtros kalman, para cada dimensão: latitude, longitude e altitude. Eles são independentes, de qualquer maneira.
Isso facilita muito a matemática da matriz: em vez de usar uma matriz de transição de estado 6x6, eu uso 3 matrizes 2x2 diferentes. Na verdade, no código, não uso matrizes. Resolvidas todas as equações e todos os valores são primitivos (duplo).
O código fonte está funcionando e há uma atividade de demonstração. Desculpem a falta de javadoc em alguns lugares, eu vou me atualizar.
fonte
Você não deve calcular a velocidade a partir da mudança de posição por vez. O GPS pode ter posições imprecisas, mas possui velocidade precisa (acima de 5 km / h). Portanto, use a velocidade do carimbo de localização GPS. Além disso, você não deve fazer isso com naturalidade, embora funcione na maioria das vezes.
As posições de GPS, como entregues, já são filtradas por Kalman, você provavelmente não pode melhorar; no pós-processamento, geralmente você não tem as mesmas informações como o chip de GPS.
Você pode suavizá-lo, mas isso também apresenta erros.
Apenas certifique-se de remover as posições quando o dispositivo está parado, isso remove as posições de salto, que alguns dispositivos / configurações não removem.
fonte
Eu costumo usar os acelerômetros. Uma mudança repentina de posição em um curto período implica em alta aceleração. Se isso não se reflete na telemetria do acelerômetro, é quase certamente devido a uma alteração nos "três melhores" satélites usados para calcular a posição (à qual me refiro como teleporte por GPS).
Quando um ativo está parado e pulando devido ao teleporte por GPS, se você computar progressivamente o centróide, estará efetivamente cruzando um conjunto cada vez maior de cartuchos, melhorando a precisão.
Para fazer isso quando o ativo não estiver em repouso, você deve estimar sua provável próxima posição e orientação com base na velocidade, rumo e dados de aceleração linear e rotacional (se você tiver giroscópios). É mais ou menos o que o famoso filtro K faz. Você pode adquirir tudo em hardware por cerca de US $ 150 em um AHRS contendo tudo, menos o módulo GPS, e com um conector para conectar um. Possui sua própria CPU e filtragem de Kalman a bordo; os resultados são estáveis e muito bons. A orientação inercial é altamente resistente ao jitter, mas oscila com o tempo. O GPS é propenso a tremores, mas não varia com o tempo, eles foram feitos praticamente para compensar um ao outro.
fonte
Um método que utiliza menos matemática / teoria é amostrar 2, 5, 7 ou 10 pontos de dados de cada vez e determinar aqueles que são discrepantes. Uma medida menos precisa de um valor externo que um filtro Kalman é usar o algoritmo a seguir para obter todas as distâncias entre pares entre pontos e eliminar o que estiver mais distante dos outros. Normalmente esses valores são substituídos pelo valor mais próximo do valor externo que você está substituindo
Por exemplo
Suavização em cinco pontos de amostra A, B, C, D, E
ATOTAL = SOMA de distâncias AB AC AD AE
BTOTAL = SOMA de distâncias AB BC BD BE
CTOTAL = SOMA de distâncias AC BC CD CE
DTOTAL = SOMA de distâncias DA DB DC DE
ETOTAL = SOMA de distâncias EA EB EC DE
Se BTOTAL for maior, você substituirá o ponto B por D se BD = min {AB, BC, BD, BE}
Essa suavização determina discrepantes e pode ser aumentada usando o ponto médio do BD em vez do ponto D para suavizar a linha posicional. Sua milhagem pode variar e existem soluções matematicamente mais rigorosas.
fonte
Quanto ao mínimo de quadrados, aqui estão algumas outras coisas para experimentar:
Só porque o tamanho dos mínimos quadrados não significa que ele precisa ser linear. Você pode ajustar ao quadrado uma curva quadrática com os mínimos quadrados, então isso ajustaria um cenário no qual o usuário está acelerando. (Observe que por mínimos quadrados cabe, quero dizer, usar as coordenadas como variável dependente e o tempo como variável independente.)
Você também pode tentar ponderar os pontos de dados com base na precisão relatada. Quando a precisão é baixa, esses pontos de dados são mais baixos.
Outra coisa que você pode querer tentar é, em vez de exibir um único ponto, se a precisão for baixa exibir um círculo ou algo que indique o intervalo no qual o usuário pode se basear na precisão relatada. (É isso que o aplicativo Google Maps interno do iPhone faz.)
fonte
Você também pode usar um spline. Alimente os valores que você possui e interpole pontos entre os pontos conhecidos. Vincular isso com um ajuste de mínimos quadrados, média móvel ou filtro kalman (como mencionado em outras respostas) permite calcular os pontos entre os pontos "conhecidos".
Ser capaz de interpolar os valores entre seus conhecidos fornece uma transição suave e agradável / uma aproximação / razoável de quais dados estariam presentes se você tivesse uma fidelidade mais alta. http://en.wikipedia.org/wiki/Spline_interpolation
Splines diferentes têm características diferentes. Os que eu já vi mais comumente usados são os splines Akima e Cubic.
Outro algoritmo a considerar é o algoritmo de simplificação de linha de Ramer-Douglas-Peucker, que é bastante usado na simplificação de dados de GPS. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )
fonte
Voltando aos Filtros Kalman ... Encontrei uma implementação C para um filtro Kalman para dados de GPS aqui: http://github.com/lacker/ikalman Ainda não testei, mas parece promissor.
fonte
Mapeado para CoffeeScript, se alguém estiver interessado. ** editar -> desculpe também por usar o backbone, mas você entendeu.
Modificado ligeiramente para aceitar um farol com atributos
fonte
@lat
e@lng
está definido. Deve ser+=
, em vez de=
Transformei o código Java de @Stochastically em Kotlin
fonte
Aqui está uma implementação Javascript da implementação Java do @ Stochastically para qualquer pessoa que precise:
Exemplo de uso:
fonte