Pracuję z danymi GPS, pobieram wartości co sekundę i wyświetlam aktualną pozycję na mapie. Problem polega na tym, że czasami (szczególnie gdy dokładność jest niska) wartości bardzo się różnią, przez co bieżąca pozycja „przeskakuje” między odległymi punktami na mapie.
Zastanawiałem się nad jakąś dość prostą metodą, aby tego uniknąć. Pierwszym pomysłem było odrzucenie wartości z dokładnością przekraczającą pewien próg, ale myślę, że są inne lepsze sposoby na zrobienie tego. Jak zwykle wykonują to programy?
Odpowiedzi:
Oto prosty filtr Kalmana, którego można użyć w dokładnie takiej sytuacji. Pochodzi z pracy, którą wykonałem na urządzeniach z Androidem.
Ogólna teoria filtru Kalmana dotyczy oszacowań wektorów, z dokładnością oszacowań reprezentowaną przez macierze kowariancji. Jednak w przypadku szacowania lokalizacji na urządzeniach z Androidem ogólna teoria sprowadza się do bardzo prostego przypadku. Dostawcy lokalizacji w systemie Android podają lokalizację jako szerokość i długość geograficzną, wraz z dokładnością określaną jako pojedyncza liczba mierzona w metrach. Oznacza to, że zamiast macierzy kowariancji, dokładność w filtrze Kalmana może być mierzona za pomocą jednej liczby, nawet jeśli lokalizacja w filtrze Kalmana jest mierzona przez dwie liczby. Również fakt, że szerokość, długość i metry są efektywnymi różnymi jednostkami, można zignorować, ponieważ jeśli umieścisz współczynniki skalowania w filtrze Kalmana, aby przekonwertować je wszystkie na te same jednostki,
Kod można by ulepszyć, bo zakłada, że najlepszym oszacowaniem aktualnej lokalizacji jest ostatnia znana lokalizacja, a jeśli ktoś się przemieszcza, powinno być możliwe wykorzystanie czujników Androida do uzyskania lepszego oszacowania. Kod ma jeden wolny parametr Q, wyrażony w metrach na sekundę, który opisuje, jak szybko spada dokładność przy braku jakichkolwiek nowych szacunków lokalizacji. Wyższy parametr Q oznacza, że dokładność spada szybciej. Filtry Kalmana generalnie działają lepiej, gdy dokładność spada nieco szybciej niż można by się spodziewać, więc podczas chodzenia z telefonem z Androidem stwierdzam, że Q = 3 metry na sekundę działa dobrze, mimo że ogólnie chodzę wolniej. Ale jeśli podróżujesz szybkim samochodem, oczywiście należy użyć znacznie większej liczby.
źródło
Q_metres_per_second
odpowiada zmiennejsigma
w sekcji „Powiązane procesy” w tym artykule w Wikipedii.Q_metres_per_second
jest odchyleniem standardowym i jest mierzone w metrach, więc jego jednostkami są metry, a nie metry / sekundy. Odpowiada odchyleniu standardowemu rozkładu po upływie 1 sekundy.To, czego szukasz, nazywa się filtrem Kalmana . Jest często używany do wygładzania danych nawigacyjnych . Niekoniecznie jest to trywialne i jest wiele możliwości dostrojenia, ale jest to bardzo standardowe podejście i działa dobrze. Dostępna jest biblioteka KFilter, która jest implementacją C ++.
Moją następną alternatywą byłoby dopasowanie metodą najmniejszych kwadratów . Filtr Kalmana wygładzi dane biorąc pod uwagę prędkości, podczas gdy metoda dopasowania metodą najmniejszych kwadratów będzie po prostu używać informacji o położeniu. Mimo to jest zdecydowanie łatwiejszy do wdrożenia i zrozumienia. Wygląda na to, że Biblioteka naukowa GNU może mieć taką implementację.
źródło
To może przyjść trochę późno ...
ja to napisałem KalmanLocationManager dla Androida, który otacza dwóch najpopularniejszych dostawców lokalizacji, sieć i GPS, kalman filtruje dane i dostarcza aktualizacje do
LocationListener
(podobnie jak dwóch „prawdziwych” dostawców).Używam go głównie do „interpolacji” między odczytami - na przykład do otrzymywania aktualizacji (przewidywań pozycji) co 100 milisekund (zamiast maksymalnej częstotliwości GPS wynoszącej jedną sekundę), co daje mi lepszą liczbę klatek na sekundę podczas animowania mojej pozycji.
W rzeczywistości używa trzech filtrów Kalmana dla każdego wymiaru: szerokości geograficznej, długości geograficznej i wysokości. W każdym razie są niezależni.
To sprawia, że matematyka macierzowa jest znacznie łatwiejsza: zamiast jednej macierzy przejść stanów 6x6, używam 3 różnych macierzy 2x2. Właściwie w kodzie w ogóle nie używam macierzy. Rozwiązano wszystkie równania i wszystkie wartości są prymitywami (podwójne).
Kod źródłowy działa i jest czynność demonstracyjna. Przepraszam za brak javadoc w niektórych miejscach, nadrobię zaległości.
źródło
Nie należy obliczać prędkości na podstawie zmiany pozycji w czasie. GPS może mieć niedokładne pozycje, ale ma dokładną prędkość (powyżej 5 km / h). Więc użyj prędkości ze znacznika lokalizacji GPS. I dalej nie powinieneś tego robić oczywiście, chociaż działa to w większości przypadków.
Pozycje GPS w stanie dostarczonym są już filtrowane przez Kalmana, prawdopodobnie nie można ich poprawić, w postprocessingu zwykle nie masz tych samych informacji, co chip GPS.
Możesz to wygładzić, ale to również wprowadza błędy.
Tylko upewnij się, że usuwasz pozycje, gdy urządzenie stoi nieruchomo, usuwa to pozycje skoku, których niektóre urządzenia / konfiguracje nie usuwają.
źródło
Zwykle używam akcelerometrów. Nagła zmiana pozycji w krótkim okresie oznacza duże przyspieszenie. Jeśli nie znajduje to odzwierciedlenia w telemetrii akcelerometru, to prawie na pewno jest to spowodowane zmianą w „trzech najlepszych” satelitach używanych do obliczania pozycji (co nazywam teleportacją GPS).
Kiedy zasób jest w stanie spoczynku i skacze z powodu teleportacji GPS, jeśli stopniowo obliczasz środek ciężkości, skutecznie przecinasz coraz większy zestaw pocisków, poprawiając precyzję.
Aby to zrobić, gdy zasób nie jest w spoczynku, musisz oszacować jego prawdopodobną następną pozycję i orientację w oparciu o dane dotyczące prędkości, kursu oraz przyspieszenia liniowego i obrotowego (jeśli masz żyroskopy). Tak mniej więcej robi słynny filtr K. Całość można kupić w sprzęcie za około 150 USD na AHRS zawierającym wszystko oprócz modułu GPS i z gniazdem do podłączenia. Posiada własny procesor i filtrowanie Kalmana na pokładzie; wyniki są stabilne i całkiem dobre. Prowadzenie bezwładnościowe jest wysoce odporne na drgania, ale z czasem ulega dryfowaniu. GPS jest podatny na jitter, ale nie dryfuje z czasem, praktycznie zostały stworzone, aby się wzajemnie kompensować.
źródło
Jedną z metod, która wykorzystuje mniej matematyki / teorii, jest próbkowanie 2, 5, 7 lub 10 punktów danych naraz i określenie tych, które są wartościami odstającymi. Mniej dokładną miarą wartości odstającej niż filtr Kalmana jest użycie następującego algorytmu do obliczenia odległości między punktami wszystkich par i odrzucenia tego, który jest najbardziej oddalony od pozostałych. Zazwyczaj te wartości są zastępowane wartością najbliższą wartości odstającej, którą zastępujesz
Na przykład
Wygładzanie w pięciu punktach próbkowania A, B, C, D, E
ATOTAL = SUMA odległości AB AC AD AE
BTOTAL = SUMA odległości AB BC BD BE
CTOTAL = SUMA odległości AC BC CD CE
DTOTAL = SUMA odległości DA DB DC DE
ETOTAL = SUMA odległości EA EB EC DE
Jeśli BTOTAL jest największy, należy zamienić punkt B na D, jeśli BD = min {AB, BC, BD, BE}
To wygładzanie określa wartości odstające i może być wzmocnione przez użycie środka BD zamiast punktu D do wygładzenia linii pozycyjnej. Twój przebieg może się różnić i istnieją bardziej rygorystyczne matematycznie rozwiązania.
źródło
Jeśli chodzi o dopasowanie metodą najmniejszych kwadratów, oto kilka innych rzeczy do eksperymentowania:
To, że pasuje do najmniejszych kwadratów, nie oznacza, że musi być liniowe. Możesz dopasować krzywą kwadratową do danych metodą najmniejszych kwadratów, wtedy pasowałoby to do scenariusza, w którym użytkownik przyspiesza. (Zauważ, że przez dopasowanie metodą najmniejszych kwadratów mam na myśli użycie współrzędnych jako zmiennej zależnej i czasu jako zmiennej niezależnej).
Możesz także spróbować zważyć punkty danych na podstawie podanej dokładności. Gdy dokładność jest niska, te punkty danych są niższe.
Inną rzeczą, którą możesz chcieć spróbować, jest zamiast wyświetlania pojedynczego punktu, jeśli dokładność jest niska, wyświetl okrąg lub coś wskazującego zakres, w którym użytkownik może opierać się na raportowanej dokładności. (To właśnie robi wbudowana aplikacja Google Maps w telefonie iPhone).
źródło
Możesz także użyć splajnu. Wprowadź wartości, które masz i interpoluj punkty między znanymi punktami. Powiązanie tego z dopasowaniem najmniejszych kwadratów, średnią ruchomą lub filtrem Kalmana (jak wspomniano w innych odpowiedziach) daje możliwość obliczenia punktów pomiędzy „znanymi” punktami.
Możliwość interpolacji wartości między znanymi daje przyjemne płynne przejście i / rozsądne / przybliżenie tego, jakie dane byłyby obecne, gdybyś miał wyższą dokładność. http://en.wikipedia.org/wiki/Spline_interpolation
Różne splajny mają różne cechy. Najczęściej używanymi, które widziałem, są krzywe Akima i Cubic.
Innym algorytmem, który należy wziąć pod uwagę, jest algorytm upraszczania linii Ramera-Douglasa-Peuckera, który jest dość powszechnie stosowany w upraszczaniu danych GPS. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )
źródło
Wracając do filtrów Kalmana ... Znalazłem implementację C dla filtra Kalmana dla danych GPS tutaj: http://github.com/lacker/ikalman Nie wypróbowałem jeszcze tego, ale wydaje się obiecujący.
źródło
Zmapowane do CoffeeScript, jeśli ktoś jest zainteresowany. ** edit -> przepraszam za używanie kręgosłupa, ale masz pomysł.
Nieznacznie zmodyfikowano, aby zaakceptować beacon z atrybutami
źródło
@lat
i@lng
są ustawione. Powinien być+=
raczej niż=
Przekształciłem kod Javy z @Stochastically na Kotlin
źródło
Oto implementacja Javascript implementacji Java @ Stochastically dla każdego, kto jej potrzebuje:
Przykład użycia:
źródło