Гладкие данные GPS

Я работаю с данными GPS, получаю значения каждую секунду и отображаю текущее положение на карте. Проблема заключается в том, что иногда (особенно при низкой точности) значения сильно меняются, в результате чего текущая позиция становится «скачкообразной». между отдаленными точками на карте.

Я задавался вопросом о каком-то достаточно простом методе, чтобы избежать этого. В качестве первой идеи я подумал об отбрасывании значений с точностью выше определенного порога, но я думаю, что есть и другие более эффективные способы. Как программы обычно это выполняют?

 heltonbiker06 сент. 2012 г., 15:51
(также, если вы перемещаетесь по основным дорогам, вы можете использовать алгоритм «привязки к дорогам» при условии, что у вас есть хороший [правильный, точный] набор данных дорожной карты. Просто мысль)
 heltonbiker06 сент. 2012 г., 15:45
Я чувствую дурные последствия "шума GPS" при попытке вычислить связанные (производные) значения, такие как скорость и наклон, которые являются очень прерывистыми, особенно для треклогов с высокой частотой дискретизации (поскольку время имеет целочисленное разрешение [одна секунда)).
 ViruMax08 дек. 2014 г., 16:42
Я сталкиваюсь с этой проблемой для лучшей точности также.

Ответы на вопрос(10)

вот еще пара вещей, с которыми можно поэкспериментировать:

Just because it's least squares fit doesn't mean that it has to be linear. You can least-squares-fit a quadratic curve to the data, then this would fit a scenario in which the user is accelerating. (Note that by least squares fit I mean using the coordinates as the dependent variable and time as the independent variable.)

You could also try weighting the data points based on reported accuracy. When the accuracy is low weight those data points lower.

Another thing you might want to try is rather than display a single point, if the accuracy is low display a circle or something indicating the range in which the user could be based on the reported accuracy. (This is what the iPhone's built-in Google Maps application does.)

который может быть использован именно для этой ситуации. Это произошло от какой-то работы, которую я сделал на устройствах Android.

Общая теория фильтров Калмана основана на оценках векторов с точностью оценок, представленных ковариационными матрицами. Однако для оценки местоположения на устройствах Android общая теория сводится к очень простому случаю. Поставщики местоположения Android предоставляют местоположение в виде широты и долготы вместе с точностью, которая указывается в виде единого числа, измеряемого в метрах. Это означает, что вместо ковариационной матрицы точность в фильтре Калмана может быть измерена одним числом, даже если местоположение в фильтре Калмана измеряется двумя числами. Также можно игнорировать тот факт, что широта, долгота и метры фактически являются разными единицами, потому что если вы добавите коэффициенты масштабирования в фильтр Калмана, чтобы преобразовать их все в одни и те же единицы, то эти коэффициенты масштабирования в итоге будут отменены при преобразовании результатов. обратно в оригинальные единицы.

Код может быть улучшен, поскольку он предполагает, что наилучшей оценкой текущего местоположения является последнее известное местоположение, и если кто-то движется, то можно использовать датчики Android для получения более точной оценки. Код имеет единственный свободный параметр Q, выраженный в метрах в секунду, который описывает, насколько быстро уменьшается точность при отсутствии каких-либо новых оценок местоположения. Более высокий параметр Q означает, что точность уменьшается быстрее. Фильтры Калмана, как правило, работают лучше, когда точность падает немного быстрее, чем можно было бы ожидать, поэтому при обходе с телефоном Android я считаю, что Q = 3 метра в секунду работает нормально, хотя я обычно иду медленнее, чем это. Но если вы путешествуете на быстрой машине, очевидно, следует использовать гораздо большее число.

public class KalmanLatLong {
    private final float MinAccuracy = 1;

    private float Q_metres_per_second;    
    private long TimeStamp_milliseconds;
    private double lat;
    private double lng;
    private float variance; // P matrix.  Negative means object uninitialised.  NB: units irrelevant, as long as same units used throughout

    public KalmanLatLong(float Q_metres_per_second) { this.Q_metres_per_second = Q_metres_per_second; variance = -1; }

    public long get_TimeStamp() { return TimeStamp_milliseconds; }
    public double get_lat() { return lat; }
    public double get_lng() { return lng; }
    public float get_accuracy() { return (float)Math.sqrt(variance); }

    public void SetState(double lat, double lng, float accuracy, long TimeStamp_milliseconds) {
        this.lat=lat; this.lng=lng; variance = accuracy * accuracy; this.TimeStamp_milliseconds=TimeStamp_milliseconds;
    }

    /// <summary>
    /// Kalman filter processing for lattitude and longitude
    /// </summary>
    /// <param name="lat_measurement_degrees">new measurement of lattidude</param>
    /// <param name="lng_measurement">new measurement of longitude</param>
    /// <param name="accuracy">measurement of 1 standard deviation error in metres</param>
    /// <param name="TimeStamp_milliseconds">time of measurement</param>
    /// <returns>new state</returns>
    public void Process(double lat_measurement, double lng_measurement, float accuracy, long TimeStamp_milliseconds) {
        if (accuracy < MinAccuracy) accuracy = MinAccuracy;
        if (variance < 0) {
            // if variance < 0, object is unitialised, so initialise with current values
            this.TimeStamp_milliseconds = TimeStamp_milliseconds;
            lat=lat_measurement; lng = lng_measurement; variance = accuracy*accuracy; 
        } else {
            // else apply Kalman filter methodology

            long TimeInc_milliseconds = TimeStamp_milliseconds - this.TimeStamp_milliseconds;
            if (TimeInc_milliseconds > 0) {
                // time has moved on, so the uncertainty in the current position increases
                variance += TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000;
                this.TimeStamp_milliseconds = TimeStamp_milliseconds;
                // TO DO: USE VELOCITY INFORMATION HERE TO GET A BETTER ESTIMATE OF CURRENT POSITION
            }

            // Kalman gain matrix K = Covarariance * Inverse(Covariance + MeasurementVariance)
            // NB: because K is dimensionless, it doesn't matter that variance has different units to lat and lng
            float K = variance / (variance + accuracy * accuracy);
            // apply K
            lat += K * (lat_measurement - lat);
            lng += K * (lng_measurement - lng);
            // new Covarariance  matrix is (IdentityMatrix - K) * Covarariance 
            variance = (1 - K) * variance;
        }
    }
}
 03 сент. 2013 г., 10:22
Не должно быть вычисление дисперсии: дисперсия + = TimeInc_milliseconds * TimeInc_milliseconds * Q_metres_per_second * Q_metres_per_second / 1000000
 12 сент. 2014 г., 10:14
Я попробовал этот подход и код, но в итоге он слишком сильно сократил общее расстояние. Сделано это слишком неточно.
 01 апр. 2015 г., 09:38
@ user2999943 да, используйте код для обработки координат, которые вы получаете из onLocationChanged ().
 14 дек. 2018 г., 14:52
@ Корай, если у вас нет информации о точности, то вы не можете использовать фильтр Калмана. Это совершенно фундаментально для того, что пытается сделать фильтр Калмана.
 10 сент. 2013 г., 08:56
@ Орасио, я знаю, почему ты так думаешь, но нет! Математически, неопределенность здесь моделируется винеровским процессом (см.en.wikipedia.org/wiki/Wiener_process ) и с винеровским процессом дисперсия растет со временем линейно. ПеременнаяQ_metres_per_second соответствует переменнойsigma в разделе «Связанные процессы» в той статье в Википедии.Q_metres_per_second является стандартным отклонением, и его измеряют в метрах, поэтому его измеряют метры, а не метры / секунды. Это соответствует стандартному отклонению распределения по истечении 1 секунды.

лмана для данных GPS здесь:http://github.com/lacker/ikalman Я еще не пробовал, но это выглядит многообещающе.

 19 янв. 2015 г., 13:03
К сожалению, это, похоже, не очень хорошо работает.

которые у вас есть, и интерполируйте точки между вашими известными точками. Связав это с подгонкой по методу наименьших квадратов, скользящим средним или фильтром Калмана (как упоминалось в других ответах), вы сможете рассчитать точки между вашими "известными" точки.

Возможность интерполировать значения между вашими известными дает вам хороший плавный переход и / разумное / приблизительное представление о том, какие данные были бы представлены, если бы у вас была более высокая точность.http://en.wikipedia.org/wiki/Spline_interpolation

Разные сплайны имеют разные характеристики. Наиболее часто используемым видом сплайнов являются Акима и Кубические сплайны.

Другим алгоритмом, который следует рассмотреть, является алгоритм упрощения линии Рамера-Дугласа-Пекера, он довольно часто используется для упрощения данных GPS. (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)

который использует меньше математики / теории, - это выборка 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 для сглаживания позиционной линии. Ваш пробег может варьироваться, и существуют более математически строгие решения.

 Al.16 июл. 2009 г., 03:29
Спасибо, я тоже попробую. Обратите внимание, что я хочу сгладить текущую позицию, так как она отображается и используется для получения некоторых данных. Меня не интересуют прошлые моменты. Моя первоначальная идея заключалась в использовании взвешенных средних, но мне все еще нужно посмотреть, что лучше.
 31 июл. 2009 г., 08:05
Ал, это кажется формой взвешенных средних. Вам нужно будет использовать «прошлое» указывает, если вы хотите сделать любое сглаживание, потому что система должна иметь больше, чем текущая позиция, чтобы знать, где сглаживать тоже. Если ваш GPS получает точки данных один раз в секунду, а ваш пользователь смотрит на экран один раз в пять секунд, вы можете использовать 5 точек данных, не замечая этого! Скользящее среднее будет задерживаться только на один дп.

откий период подразумевает высокое ускорение. Если это не отражено в телеметрии акселерометра, то это почти наверняка связано с изменением «лучшей тройки». спутники, используемые для вычисления местоположения (к которому я отношу телепортацию GPS).

Когда актив находится в состоянии покоя и перемещается из-за телепортации GPS, если вы постепенно вычисляете центроид, вы эффективно пересекаете все больший и больший набор оболочек, повышая точность.

Чтобы сделать это, когда актив не находится в покое, вы должны оценить его вероятную следующую позицию и ориентацию на основе данных о скорости, курсе и линейном и вращательном (если у вас есть гироскопах) ускорении. Это более или менее то, что делает знаменитый K-фильтр. Вы можете получить все это аппаратно примерно за 150 долларов на AHRS, содержащей все, кроме модуля GPS, и с разъемом для подключения. Он имеет свой собственный процессор и фильтрацию Калмана на борту; результаты стабильны и довольно хороши. Инерционное наведение очень устойчиво к джиттеру, но дрейфует со временем. GPS склонен к джиттеру, но не дрейфует со временем, они практически созданы для компенсации друг друга.

может иметь неточные положения, но имеет точную скорость (выше 5 км / ч). Так что используйте скорость из отметки местоположения GPS. И далее вы не должны делать это с курсом, хотя это работает в большинстве случаев.

Позиции GPS в том виде, в котором они были доставлены, уже отфильтрованы по Калману, и вы, вероятно, не сможете их улучшить. Обычно при постобработке у вас не та же информация, что и в чипе GPS.

Вы можете сгладить его, но это также приводит к ошибкам.

Просто убедитесь, что вы удаляете позиции, когда устройство стоит, это удаляет прыжковые позиции, которые не удаляются некоторыми устройствами / конфигурациями.

 09 июл. 2015 г., 12:39
Не могли бы вы дать некоторые ссылки для этого, пожалуйста?
 29 мая 2017 г., 11:34
"Позиции GPS в том виде, в котором они были доставлены, уже отфильтрованы по Калману, вы, вероятно, не сможете улучшить". Если вы можете указать источник, который подтверждает это для современных смартфонов (например), это было бы очень полезно. Я не вижу доказательств этого сам. Даже простая кальмановская фильтрация необработанных местоположений устройства настоятельно подтверждает, что это не так. Необработанные местоположения танцуют хаотично, в то время как отфильтрованные местоположения чаще всего держатся близко к реальному (известному) местоположению.
 28 июл. 2015 г., 22:21
& Quot; прыгать & quot; стоя на месте не единственный источник ошибки. Есть также отражения сигнала (например, от гор), где позиция прыгает вокруг. Мои чипы GPS (например, Garmin Dakota 20, SonyEricsson Neo) не отфильтровали это ... И что действительно шутит, так это значение высоты сигналов GPS, когда они не сочетаются с барометрическим давлением. Эти значения не фильтруются, или я не хочу видеть нефильтрованные значения.
 21 февр. 2017 г., 00:51
@AlexWien GPS вычисляет расстояние от точки за раз до допуска, давая вам сферу с толщиной,shell вокруг спутника Вы где-то в этом объеме оболочки. Пересечение трех из этих объемов оболочки дает вам объем позиции, центром тяжести которого является ваша вычисленная позиция. Если у вас есть набор сообщаемых позиций, и вы знаете, что датчик находится в состоянии покоя, вычисление центроида эффективно пересекает намного больше оболочек, повышая точность. Ошибка в этом случаеreduced.
 09 июл. 2015 г., 14:56
В этих предложениях есть много информации и большой профессиональный опыт. На какое предложение вы хотите ссылаться? для скорости: поиск эффекта Доплера и GPS. внутренний кальман? Это базовые знания GPS, каждая статья или книга о том, как внутренне работает GPS-чип. Smootig-ошибки: когда-либо сглаживание вводит ошибки. стоять на месте? попробуй это.

если кто-то заинтересован. ** изменить - & gt; извините, используя магистраль тоже, но вы поняли идею.

Немного изменен, чтобы принять маяк с атрибутами

{latitude: item.lat,longitude: item.lng,date: new Date(item.effective_at),accuracy: item.gps_accuracy}

MIN_ACCURACY = 1

# mapped from http://stackoverflow.com/questions/1134579/smooth-gps-data

class v.Map.BeaconFilter

  constructor: ->
    _.extend(this, Backbone.Events)

  process: (decay,beacon) ->

    accuracy     = Math.max beacon.accuracy, MIN_ACCURACY

    unless @variance?
      # if variance nil, inititalise some values
      @variance     = accuracy * accuracy
      @timestamp_ms = beacon.date.getTime();
      @lat          = beacon.latitude
      @lng          = beacon.longitude

    else

      @timestamp_ms = beacon.date.getTime() - @timestamp_ms

      if @timestamp_ms > 0
        # time has moved on, so the uncertainty in the current position increases
        @variance += @timestamp_ms * decay * decay / 1000;
        @timestamp_ms = beacon.date.getTime();

      # Kalman gain matrix K = Covarariance * Inverse(Covariance + MeasurementVariance)
      # NB: because K is dimensionless, it doesn't matter that variance has different units to lat and lng
      _k  = @variance / (@variance + accuracy * accuracy)
      @lat = _k * (beacon.latitude  - @lat)
      @lng = _k * (beacon.longitude - @lng)

      @variance = (1 - _k) * @variance

    [@lat,@lng]

Я написал этоKalmanLocationManager для Android, которая объединяет двух наиболее распространенных поставщиков услуг определения местоположения: сеть и GPS, kalman-фильтрует данные и доставляет обновления вLocationListener (как два «реальных» провайдера).

Я использую его в основном для "интерполяции" между показаниями - например, получать обновления (прогнозы положения) каждые 100 миллисекунд (вместо максимальной скорости в секунду), что дает мне лучшую частоту кадров при анимации моей позиции.

На самом деле он использует три фильтра Калмана для каждого измерения: широта, долгота и высота. Во всяком случае, они независимы.

Это значительно упрощает математику: вместо использования одной матрицы перехода состояний 6x6 я использую 3 разные матрицы 2x2. На самом деле в коде я вообще не использую матрицы. Решены все уравнения и все значения являются примитивами (двойной).

Исходный код работает, и есть демонстрационная активность. Извините за отсутствие Javadoc в некоторых местах, я наверстываю упущенное.

 05 мая 2015 г., 18:19
Шипы, которые вы видите и растете с середины (оранжевая линия) выглядят как обновления провайдера сети. Можете ли вы попробовать подготовить как сырые сети, так и обновления gps? Возможно, вам будет лучше без сетевых обновлений, в зависимости от того, чего вы пытаетесь достичь. Кстати, откуда вы получаете эти сырые апельсиновые обновления?
 06 мая 2015 г., 11:30
оранжевые точки - от провайдера GPS, а синие - от Калмана, я составил логи на карте
 22 сент. 2015 г., 07:03
Не могли бы вы прислать мне эти данные в каком-нибудь текстовом формате? Каждое обновление местоположения имеет установленное поле Location.getProvider (). Всего один файл со всеми Location.toString ().
 28 апр. 2015 г., 15:43
Я пытался использовать ваш lib-код, я получил некоторые нежелательные результаты, я не уверен, что я делаю что-то не так ... (Ниже URL-адрес изображения, синий - это отфильтрованные местоположения, путь, оранжевый - необработанные местоположения)app.box.com/s/w3uvaz007glp2utvgznmh8vlggvaiifk

Фильтр Калмана, Он часто используется дляплавные навигационные данные, Это не обязательно тривиально, и вы можете выполнить множество настроек, но это очень стандартный подход, который хорошо работает. EстьБиблиотека KFilter доступны, который является реализацией C ++.

Мой следующий запасной вариант будетнаименьших квадратов, Фильтр Калмана сгладит данные с учетом скоростей, тогда как подход наименьших квадратов будет использовать только информацию о положении. Тем не менее, это определенно проще для реализации и понимания. Похоже, что научная библиотека GNU может иметьреализация этого.

 23 авг. 2014 г., 10:29
@ChrisArguin Добро пожаловать. Дайте мне знать, если результат хороший, пожалуйста.
 Al.16 июл. 2009 г., 01:12
Спасибо, Крис. Да, я читал о Калмане во время поиска, но это, конечно, немного за пределами моего знания математики. Вам известен какой-нибудь пример кода, который легко прочитать (и понять!), Или, что еще лучше, есть какая-то реализация? (C / C ++ / Java)
 Al.16 июл. 2009 г., 01:28
Нет проблем :-) Я пытался искать, но по какой-то причине кажется, что эта вещь Калмана - черная магия. Много теоретических страниц, но мало или совсем нет кода. Спасибо, попробую другие методы.
 21 авг. 2014 г., 11:04
kalman.sourceforge.net/index.php здесь C ++ реализация фильтра Калмана.
 16 июл. 2009 г., 01:24
@Al К сожалению, мое единственное знакомство с фильтрами Калмана - это работа, поэтому у меня есть чудесный элегантный код, который я не могу вам показать.

Ваш ответ на вопрос