Geographic Information Systems Asked on December 10, 2021
I am working with a GPS dataset where GPS speed is not available, only the lat/lon
coordinates and timestamp
.
Currently, I calculate point-level speed from rate of distance between two consecutive points (distance/delta_time
). However, the result usually gave large errors due to the errors in GPS.
Are the other means or techniques to estimate the point-point speed?
EDIT
Currently, I calculate the speed in python using the geopy
package, like so:
from geopy.distance import vincenty
A = (Data[i, 0], Data[i, 1])
B = (Data[i + 1, 0], Data[i + 1, 1])
pointSpeed = vincenty(A, B).meters/delta_time[i]
I took a shot at @FSimardGIS 's suggestion for moving average.
Inputs: pandas dataframe df
of the gps data containing timestamp, latitude, longitude columns, sorted by timestamp and with pure index (0 to end).
And a time_interval
in mins, default: 5 mins
import pandas as pd
# main function
def findSpeed(df, time_interval = 5):
computeDistance(df)
df['offset'] = getTimeOffsets(df)
df['dspan'] = df['tspan'] = df['cspeed'] = df['diff'] = None
for N in range(len(df)):
if N == 0: continue
backi = N
totOffset = df.at[N,'offset']
while totOffset <= time_interval*60 :
backi -= 1
totOffset += df.at[backi,'offset']
if backi == 0: break
tspan = df.at[N,'timestamp'] - df.at[backi,'timestamp']
df.at[N,'tspan'] = tspan.seconds
distance = df.at[N,'ll_dist_traveled'] - df.at[backi,'ll_dist_traveled']
df.at[N,'dspan'] = round(distance,3)
if distance == 0:
speed = df.at[N, 'cspeed'] = 0
else:
speed = round(distance / tspan.seconds * 3600,2)
df.at[N, 'cspeed'] = speed
speed_diff = round(df.at[N,'speed'] - speed, 2)
df.at[N,'diff'] = speed_diff
return df
# calling the function
df1 = findSpeed(df, time_interval = 5)
There are some supporting functions I've developed in earlier projects:
computeDistance
: finds distance between consecutive lat-longs and adds it up to a cumulative distance column ll_dist_traveled
getTimeOffsets
: gives a column of time offset between timestamps in seconds
These are used by the program to identify [time_interval] (or lower) time period correspondng to each row and calculate speed from that group of data.
from math import sin, cos, sqrt, atan2, radians
def lat_long_dist(lat1,lon1,lat2,lon2):
# function for calculating ground distance between two lat-long locations
R = 6373.0 # approximate radius of earth in km.
lat1 = radians( float(lat1) )
lon1 = radians( float(lon1) )
lat2 = radians( float(lat2) )
lon2 = radians( float(lon2) )
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = round(R * c, 6)
return distance
def computeDistance(sequencedf):
prevLat = prevLon = 0 # dummy initiation
total_dist = 0
for N in range(len(sequencedf)):
lat = float(sequencedf.at[N,'latitude'])
lon = float(sequencedf.at[N,'longitude'])
if N == 0:
sequencedf.at[N,'ll_dist'] = 0
else:
sequencedf.at[N,'ll_dist'] = lat_long_dist(lat,lon, prevLat,prevLon)
total_dist += sequencedf.at[N,'ll_dist']
sequencedf.at[N,'ll_dist_traveled'] = round(total_dist,6)
prevLat = lat
prevLon = lon
return round(total_dist,6)
# also the original df gets ll_dist and ll_dist_traveled columns added to it
def getTimeOffsets(df, timestamp_col='timestamp'):
timeOffsets = (df[timestamp_col] - df[timestamp_col].shift()).fillna(pd.Timedelta(seconds=0))
return timeOffsets.dt.total_seconds().astype(int)
Feel free to change the lat_long_dist
function to your preferred method (or use a routing tool like OSRM).
Output: same df (table / dataframe), with some middle-step new columns and a 'cspeed' column with calculated speed in km/hr.
I had a gps stream with original speed values from the device. Calculated with different time interval settings and plotted.
As observable, even the original data (in orange) is quite jittery. Moving average helps smoothen it out, but there's a tradeoff with accuracy. I'm still not clear about which time interval value to take. Hope this helps someone!
Answered by Nikhil VJ on December 10, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP