Я работаю с данными GPS, получаю значения каждую секунду и отображаю текущее положение на карте. Проблема в том, что иногда (особенно при низкой точности) значения сильно меняются, что делает текущую позицию «прыгать» между удаленными точками на карте.
Я задавался вопросом о каком-то достаточно простом способе избежать этого. В качестве первой идеи я подумал об отбрасывании значений с точностью выше определенного порога, но я думаю, что есть и другие более эффективные способы. Как обычно программы выполняют это?
Ответы:
Вот простой фильтр Калмана, который можно использовать именно для этой ситуации. Это произошло из-за работы, которую я сделал на устройствах Android.
Общая теория фильтров Калмана - все об оценках для векторов, с точностью оценок, представленных ковариационными матрицами. Однако для оценки местоположения на устройствах Android общая теория сводится к очень простому случаю. Поставщики местоположения Android предоставляют местоположение в виде широты и долготы вместе с точностью, которая указывается в виде единого числа, измеряемого в метрах. Это означает, что вместо ковариационной матрицы точность в фильтре Калмана может измеряться одним числом, даже если местоположение в фильтре Калмана измеряется двумя числами. Также можно игнорировать тот факт, что широта, долгота и метры фактически являются разными единицами, потому что если вы добавите масштабные коэффициенты в фильтр Калмана, чтобы преобразовать их все в одинаковые единицы,
Код можно улучшить, поскольку он предполагает, что наилучшая оценка текущего местоположения - это последнее известное местоположение, и если кто-то движется, то можно использовать датчики Android для получения более точной оценки. Код имеет единственный свободный параметр Q, выраженный в метрах в секунду, который описывает, насколько быстро уменьшается точность при отсутствии каких-либо новых оценок местоположения. Более высокий параметр Q означает, что точность уменьшается быстрее. Фильтры Калмана, как правило, работают лучше, когда точность снижается немного быстрее, чем можно было бы ожидать, поэтому при обходе с телефоном Android я обнаружил, что Q = 3 метра в секунду работает нормально, хотя обычно я иду медленнее. Но если вы путешествуете на быстрой машине, очевидно, следует использовать гораздо большее число.
источник
Q_metres_per_second
соответствует переменнойsigma
в разделе «Связанные процессы» в той статье Википедии.Q_metres_per_second
является стандартным отклонением и измеряется в метрах, поэтому его единицы - это метры, а не метры / секунды. Это соответствует стандартному отклонению распределения по истечении 1 секунды.То, что вы ищете, называется фильтром Калмана . Он часто используется для сглаживания навигационных данных . Это не обязательно тривиально, и вы можете выполнить множество настроек, но это очень стандартный подход, который хорошо работает. Там есть библиотека KFilter доступен , которая является реализацией C ++.
Мой следующий запасной вариант будет соответствовать наименьших квадратов . Фильтр Калмана сгладит данные с учетом скоростей, тогда как подход наименьших квадратов будет просто использовать информацию о положении. Тем не менее, это определенно проще для реализации и понимания. Похоже, что научная библиотека GNU может иметь такую реализацию.
источник
Это может прийти немного поздно ...
Я написал этот KalmanLocationManager для Android, который объединяет двух наиболее распространенных провайдеров определения местоположения: сеть и GPS, kalman-фильтр данных и доставляет обновления
LocationListener
(как два «настоящих» провайдера).Я использую его в основном для «интерполяции» между показаниями - например, для получения обновлений (прогнозов положения) каждые 100 миллисекунд (вместо максимальной скорости GPS в одну секунду), что дает мне лучшую частоту кадров при анимации моей позиции.
На самом деле он использует три фильтра Калмана для каждого измерения: широта, долгота и высота. Во всяком случае, они независимы.
Это значительно упрощает математику: вместо использования одной матрицы перехода состояний 6x6 я использую 3 разные матрицы 2x2. На самом деле в коде я вообще не использую матрицы. Решены все уравнения и все значения являются примитивами (двойной).
Исходный код работает, и есть демонстрационная активность. Извините за отсутствие javadoc в некоторых местах, я догоню.
источник
Вы не должны рассчитывать скорость от изменения положения за раз. GPS может иметь неточные положения, но имеет точную скорость (выше 5 км / ч). Так что используйте скорость из отметки местоположения GPS. И далее вы не должны делать это с курсом, хотя это работает в большинстве случаев.
Полученные позиции GPS уже отфильтрованы по Калману, и вы, вероятно, не сможете их улучшить. Обычно при постобработке у вас не та же информация, что и у чипа GPS.
Вы можете сгладить его, но это также приводит к ошибкам.
Просто убедитесь, что вы удаляете позиции, когда устройство стоит на месте, это удаляет прыжковые позиции, которые некоторые устройства / конфигурации не удаляют.
источник
Я обычно использую акселерометры. Внезапное изменение положения за короткий период подразумевает высокое ускорение. Если это не отражается в телеметрии акселерометра, то это почти наверняка связано с изменением «лучших трех» спутников, используемых для вычисления местоположения (которое я называю GPS-телепортацией).
Когда актив находится в состоянии покоя и перемещается из-за телепортации GPS, если вы постепенно вычисляете центроид, вы эффективно пересекаете все больший и больший набор оболочек, повышая точность.
Чтобы сделать это, когда актив не находится в состоянии покоя, вы должны оценить его вероятную следующую позицию и ориентацию на основе данных скорости, курса и линейного и вращательного (если у вас есть гироскопы) ускорения. Это более или менее то, что делает знаменитый K-фильтр. Вы можете получить все это аппаратно примерно за 150 долларов на AHRS, содержащей все, кроме модуля GPS, и с разъемом для подключения. Он имеет свой собственный процессор и фильтрацию Калмана на борту; результаты стабильны и довольно хороши. Инерционное наведение очень устойчиво к джиттеру, но дрейфует со временем. GPS склонен к джиттеру, но не дрейфует со временем, они практически созданы для компенсации друг друга.
источник
Один метод, который использует меньше математики / теории, - это выборка 2, 5, 7 или 10 точек данных за раз и определение тех, которые являются выбросами. Менее точный показатель выброса, чем фильтр Калмана, заключается в использовании следующего алгоритма для определения всех парных расстояний между точками и выброса одного, наиболее удаленного от остальных. Обычно эти значения заменяются значением, ближайшим к исходному значению, которое вы заменяете.
Например
Сглаживание в пяти точках выборки A, B, C, D, E
ATOTAL = СУММА расстояний AB AC AD AE
BTOTAL = СУММА расстояний AB BC BD BE
CTOTAL = СУММА расстояний AC BC CD CE
DTOTAL = СУММА расстояний DA DB DC DE
ETOTAL = СУММА расстояний EA EB EC DE
Если BTOTAL является наибольшим, вы заменили бы точку B на D, если BD = min {AB, BC, BD, BE}
Это сглаживание определяет выбросы и может быть увеличено путем использования средней точки BD вместо точки D для сглаживания позиционной линии. Ваш пробег может варьироваться, и существуют более математически строгие решения.
источник
Что касается наименьших квадратов, вот еще пара вещей, с которыми можно поэкспериментировать:
То, что он подходит по методу наименьших квадратов, не означает, что он должен быть линейным. Вы можете подгонять квадратичную кривую к данным методом наименьших квадратов, тогда это будет соответствовать сценарию, в котором пользователь ускоряется. (Обратите внимание, что под наименьшими квадратами я имею в виду использование координат в качестве зависимой переменной и время в качестве независимой переменной.)
Вы также можете попробовать взвешивать точки данных на основе сообщенной точности. Когда точность низкая, эти данные снижаются.
Еще одна вещь, которую вы, возможно, захотите попробовать, - это не отображать одну точку, а, если точность низкая, отобразить кружок или что-то, указывающее диапазон, в котором пользователь может основываться на сообщенной точности. (Это то, что делает встроенное приложение Google Maps для iPhone.)
источник
Вы также можете использовать сплайн. Введите значения, которые у вас есть, и интерполируйте точки между вашими известными точками. Связав это с подгонкой по методу наименьших квадратов, скользящим средним или фильтром Калмана (как уже упоминалось в других ответах), вы сможете рассчитать точки между вашими «известными» точками.
Возможность интерполировать значения между вашими известными дает вам хороший плавный переход и / разумное / приблизительное представление о том, какие данные были бы представлены, если бы у вас была более высокая точность. http://en.wikipedia.org/wiki/Spline_interpolation
Разные сплайны имеют разные характеристики. Наиболее часто используемые сплайны - Акима и Кубические сплайны.
Другим алгоритмом, который следует рассмотреть, является алгоритм упрощения линии Рамера-Дугласа-Пекера, он довольно часто используется для упрощения данных GPS. ( http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm )
источник
Возвращаясь к фильтрам Калмана ... Я нашел реализацию C для фильтра Калмана для данных GPS здесь: http://github.com/lacker/ikalman Я еще не пробовал, но это выглядит многообещающе.
источник
Отображается на CoffeeScript, если кто-то заинтересован. ** редактировать -> извините, используя магистраль тоже, но вы поняли идею.
Немного изменен, чтобы принять маяк с атрибутами
источник
@lat
и@lng
установлены. Должно быть,+=
а не=
Я преобразовал код Java из @Stochastically в Kotlin
источник
Вот реализация Javascript Java-реализации @ Stochastically для тех, кто в ней нуждается:
Пример использования:
источник