Определение параметра фильтра Калмана для оценки положения транспортного средства в Python

Я относительно новичок в концепциях фильтра Калмана, и я хотел бы использовать его для оценки и отслеживания точности положения транспортного средства с помощью измерений GPS (в качестве первого шага). Однако я не уверен в предположениях и значениях параметров, которые рассматривал, и хотел бы узнать от других пользователей, двигаюсь ли я в правильном направлении. Спасибо!!

Я рассмотрел стандартную модель движения: постоянная скорость (при условии, что ускорение не влияет на оценку положения этого транспортного средства), и поэтому мои состояния состоят только из положения и скорости.
????????+1 = ???????? + ????˙???? Δ????
????˙????+1 = ????˙????

Таким образом, матрица перехода состояния будет (учитывая 2D-позиционирование (x, y) с координатами широты и долготы):

A = [[1.0, 0.0, Δ????, 0.0],
     [0.0, 1.0, 0.0, Δ????],
     [0.0, 0.0, 1.0, 0.0],
     [0.0, 0.0, 0.0, 1.0]]

Поскольку у нас есть только данные измерения положения, мы можем соответственно записать матрицу измерений как:

H = [[1.0, 0.0, 0.0, 0.0],
     [0.0, 1.0, 0.0, 0.0]]

Начальные условия:
Для начального начального состояния транспортного средства x0 я принял все нули для позиции и скорости (я читал пару реализаций, где они ввели ненулевое значение для позиция (обычно устанавливается на 100, но я не уверен в причине этого)

Для начальной неопределенности P0 я принял единичную матрицу с диагоналями, равными 100, поскольку мы не уверены в начальном положении и скорости. Следует ли установить это значение выше? Что именно это означает, когда начальное положение и скорость точно известны по отношению к модели? Это мировые координаты или просто какая-то произвольная позиция?

Временной шаг ( Δ???? ):
Поскольку GPS обновляется с частотой 1 Гц или каждую 1 секунду, я соответственно предположил то же самое для временного шага фильтра.

Значения шума:
Шум процесса: я только что принял единичную матрицу для шума процесса модели. Но в других реализациях также предполагается, что шум процесса равен нулю. Значит ли это, что нет случайных колебаний состояний системы?

Шум измерения: поскольку GPS является рассматриваемым измерением, стандартное отклонение показаний GPS составляет приблизительно 6 метров и считается шумом измерения для системы.

Измерение:
я использую файл GPX, экспортированный из приложения (Strava), который дает позиционирование по широте и долготе. Должен ли он быть преобразован в метры или я могу напрямую использовать данные позиционирования из файла GPX?

Пожалуйста, дайте мне знать, верны ли приведенные выше предположения и реализации :)

ОБНОВЛЕНИЕ

Я напрямую рассматривал данные широты и долготы, предоставленные GPS, как входные данные измерений для Калмана, не преобразовывая их сначала в декартовы значения. В приведенной ниже реализации кода данные теперь сначала преобразуются в UTM, а затем передаются в качестве входных данных измерения. Как предложил Кани, я проверю преобразование вычислений, данное для широты и долготы, и разницу, полученную между двумя методами.

import gpxpy
import pandas as pd
import numpy as np
import utm
import matplotlib.pyplot as plt

with open('test3.gpx') as fh:
    gpx_file = gpxpy.parse(fh)
segment = gpx_file.tracks[0].segments[0]
coords = pd.DataFrame([
    {'lat': p.latitude,
     'lon': p.longitude,
     'ele': p.elevation,
     'time': p.time} for p in segment.points])
coords.head(3)
plt.plot(coords.lon[::18], coords.lat[::18],'ro')
plt.show()
#plt.plot(coords.lon, coords.lat)

def lat_log_posx_posy(coords):

     px, py = [], []
     for i in range(len(coords.lat)):
         dx = utm.from_latlon(coords.lat[i], coords.lon[i])
         px.append(dx[0])
         py.append(dx[1])
     return px, py

def kalman_xy(x, P, measurement, R,
              Q = np.array(np.eye(4))):

    return kalman(x, P, measurement, R, Q,
                  F=np.array([[1.0, 0.0, 1.0, 0.0],
                              [0.0, 1.0, 0.0, 1.0],
                              [0.0, 0.0, 1.0, 0.0],
                              [0.0, 0.0, 0.0, 1.0]]),
                  H=np.array([[1.0, 0.0, 0.0, 0.0],
                              [0.0, 1.0, 0.0, 0.0]]))

def kalman(x, P, measurement, R, Q, F, H):

    y = np.array(measurement).T - np.dot(H,x)
    S = H.dot(P).dot(H.T) + R  # residual convariance
    K = np.dot((P.dot(H.T)), np.linalg.pinv(S))
    x = x + K.dot(y)
    I = np.array(np.eye(F.shape[0]))  # identity matrix
    P = np.dot((I - np.dot(K,H)),P)

    # PREDICT x, P
    x = np.dot(F,x)
    P = F.dot(P).dot(F.T) + Q

    return x, P

def demo_kalman_xy():

    px, py = lat_log_posx_posy(coords)
    plt.plot(px[::18], py[::18], 'ro')
    plt.show()

    x = np.array([px[0], py[0], 0.01, 0.01]).T
    P = np.array(np.eye(4))*1000 # initial uncertainty
    result = []
    R = 0.01**2
    for meas in zip(px, py):
        x, P = kalman_xy(x, P, meas, R)
        result.append((x[:2]).tolist())
    kalman_x, kalman_y = zip(*result)
    plt.plot(px[::18], py[::18], 'ro')
    plt.plot(kalman_x, kalman_y, 'g-')
    plt.show()

demo_kalman_xy()

person surajr    schedule 23.08.2019    source источник
comment
вы должны быть в состоянии получить более точную оценку шума вашего измерения от устройства GPS. как правило, он будет видеть избыточные спутники и сообщать об этом с помощью предложений NMEA, например. подробности см. в сообщении GST. Я не использую страву, поэтому не могу сказать, предоставляет ли она ее в удобном формате, но она, безусловно, доступна для приложений для Android.   -  person Sam Mason    schedule 29.08.2019
comment
Спасибо за комментарий, Сэм :) Проверим в разделе экспорта приложения, предоставит ли Strava эту информацию. Есть ли у вас предложения для других приложений, которые можно использовать для записи данных GPS, которые также предоставляют эту информацию?   -  person surajr    schedule 29.08.2019


Ответы (2)


Для фильтра Калмана, как и для любой другой задачи, связанной с физикой, важна единица измерения. Если вы используете скорость в метрах в секунду, позиция не должна указывать широту/долготу. Вы должны перевести их в метры.

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

Для очень коротких расстояний вы можете аппроксимировать относительное положение в метрах, используя следующие уравнения, где r — это радиус земли:

  • distance along latitude = r * deg_to_rad(latitude - base latitude)
  • distance along longitude = 2 * r * asin(cos(base latitude)) * sin(pi / 180 / 2)) * deg_to_rad(longitude - base longitude)

Однако это сложно по двум основным причинам.

  1. Это справедливо только для коротких расстояний.
  2. Радиус Земли изменяется с широтой.
person Kani    schedule 28.08.2019
comment
Кани спасибо за ответ! Я реализовал код, который учитывает данные GPS lat Long и преобразует их в UTM, а затем передает их в качестве входных данных фильтру Калмана. Я обновил этот код на свой вопрос. Я проверю ваш метод позже сегодня и сообщу вам позже о результатах. Поскольку данные учитываются для коротких расстояний (данные записаны на расстоянии ‹10 км), все должно быть в порядке, но будет подтверждено расчетами. - person surajr; 29.08.2019

Настройка Q - матрицы ковариации шума процесса, R - матрицы ковариации шума измерений и P - матрицы ковариации ошибок зависит от того, что вы пытаетесь отслеживать, и его условий, и это довольно сложно. Особенно ковариационная матрица ошибок (P).

Я предлагаю вам взглянуть на блокнот jupyter, созданный создателем библиотеки filterpy, чтобы объяснить, как правильно реализовать фильтры Калмана.

person No_Fun    schedule 17.12.2020