0
votes

I'm using a Kalman filter to track the position of a vehicle and for my measurement, I have a GPX file (WGS84 Format) containing information about the latitude, longitude, elevation and the timestamp of each point given by GPS. Using this data, I computed the distance between GPS points (Using Geodesic distance and Vincenty formula) and, since the timestamp information is known, the time difference between the points can be used to calculate the time delta. Since, we now have the distance and the time delta between the points, we can calculate the velocity (= distance between points/time delta) which could then be also used as a measurement input to the Kalman.

However, I have read that this is only the average velocity and not the instantaneous velocity at any given point. In order to obtain the instantaneous velocity, it is suggested that one must take the running average and some implementations directly compute the velocity considering the difference in time between the current time at the point with the first initial point. I'm a bit confused as to which method I need to use to implement this in python.

  1. Firstly, is this method used in my implementation correct to calculate velocity? (I also read about doppler shifts that can be used but sadly, I only collect the GPS data through a running app (Strava) on my iPhone)

  2. How can the instantaneous velocity at every GPS point be calculated from my implementation?( Is the bearing information also necessary?)

  3. What would be the error from this computed velocity? (Since the error in position itself from an iPhone can be about 10 metres, error from distance measurement about 1mm and considering that I want the focus to be on as much accuracy as possible)

Current Implementation

import gpxpy
import pandas as pd
import numpy as np
from geopy.distance import vincenty, geodesic
import matplotlib.pyplot as plt

"Import GPS Data"
with open('my_run_001.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,
     } for p in segment.points])

"Compute delta between timestamps"
times = pd.Series([p.time for p in segment.points], name='time')
dt = np.diff(times.values) / np.timedelta64(1, 's')

"Find distance between points using Vincenty and Geodesic methods"
vx = []
for i in range(len(coords.lat)-1):
        if(i<=2425):
            vincenty_distance = vincenty([coords.lat[i], coords.lon[i]],[coords.lat[i+1], coords.lon[i+1]]).meters
            vx.append(vincenty_distance)
print(vx)

vy = []
for i in range(len(coords.lat)-1):
        if(i<=2425):
            geodesic_distance = geodesic([coords.lat[i], coords.lon[i]],[coords.lat[i+1], coords.lon[i+1]]).meters
            vy.append(geodesic_distance)
print(vy)

"Compute and plot velocity"
velocity = vx/dt
time = [i for i in range(len(dt))]
plt.plot(velocity,time)
plt.xlabel('time')
plt.ylabel('velocity')
plt.title('Plot of Velocity vs Time')
plt.show()

Reference for GPX Data: https://github.com/stevenvandorpe/testdata/blob/master/gps_coordinates/gpx/my_run_001.gpx

1

1 Answers

0
votes

interesting topic out here.

If you are planning to use standalone GPS location output for calculating velocity of an object, be ready for some uncertainty of the results. As I am sure you know, there are certain propagation delays in the whole process, so there are several information you need to pay attention on.

1. Basically, taking the distance and time, and then calculating velocity based on those deltas is right approach, but as you've told, that is the average velocity between two gps measurements, since gps has some propagation delay in its nature.

2. Like we've told, this kind of calculation gives us average velocity in function of delta time and distance, and by nature, we cant change that. What we can do is affect the frequency of sampling the gps signal, and by that increase or decrease real time accuracy of our system.

SUGGESTION: If you wish a bit more accurate real time velocity data, I suggest you involving gyroscope sensor of your phone and processing it's output. Collecting first delta (average) speed from GPS and then detect gyro changes will be interesting way to continue with your idea.

3. Lets say you are walking (or superspeed running :)) with your device. At one moment, device is sending request for GPS location but due some issues (perhaps bad satellite connection) you got response with data with 10 seconds delay. For purpose of the example lets consider you are walking on absolutely straight line on absolutely flat part of surface :) After 1 minute from last request received you are sending another request for gps location, and you receive the data which told you you've walked 300m on north from your previous measurement, with 2 secs delay. If you measure it from send request to send another request you would get your speed was 300/70 = 4.28 m/s (quite impressive speed), but what's one of actual possible scenarions: - You didnt walked 300m, you walked 270 m (gps error) - Time between two measures (received) is around 62s - You were even faster with 270/62 = 4.84 m/s

With phone it is tricky you cant measure when did you actually sent request in ether or when in ms you got the response, and those things are quite possible when you are manipulating sensors on hardware-proximity layer. Therefore you will certainly loose some accuracy.