I am writing some code to obtain the road centerline data from OSM based on GPS data for a given path that was driven. I am using OSMNX to interface with the OSM data but get strange results when using nearest_edges to match the GPS data from my path to the OSM data.
Here is the input path (with data spacing < 1m apart): enter image description here
And here is the path after matching using nearest_edges: enter image description here
Here is the code I am using to generate these results:
#!/usr/bin/python3
import osmnx as ox
import csv
import utm
from shapely.geometry import Point
import os
import simplekml
# get data from file
path = "C:\\Users\\nj5wdf\\OneDrive - Aptiv\\Projects\\Prodrive\\Curvature_Python\\tests\\"
filename = "map_provider_test_data.csv"
filename = os.path.join(path, filename)
with open(filename, 'r') as file:
# create csv reader object
data = list(csv.reader(file))
lat = []
lon = []
for row in data:
lat.append(float(row[0]))
lon.append(float(row[1]))
buffer = 0.002
north_lat = max(lat) + buffer
south_lat = min(lat) - buffer
east_lon = max(lon) + buffer
west_lon = min(lon) - buffer
# generate graph of all road networks within the bounding box
graph = ox.graph_from_bbox(
north_lat, south_lat, east_lon, west_lon,
network_type="drive",
simplify=True,
truncate_by_edge=True,
clean_periphery=True)
# convert input lat / lon to UTM
x = []
y = []
for _lat, _lon in zip(lat, lon):
_y, _x, _, _ = utm.from_latlon(_lat, _lon)
x.append(_x)
y.append(_y)
# get nearest edges
nodes, streets = ox.graph_to_gdfs(graph)
graph_proj = ox.project_graph(graph)
nearest = ox.nearest_edges(graph_proj, lon, lat)
# remove redundant edges from result
last_near = nearest[0]
reduced_nearest = []
for near in nearest:
if (near not in reduced_nearest) and (near[1] != last_near[0]):
reduced_nearest.append(near)
last_near = near
# get centerline points from nearest edges
centerline_points = []
for edge in reduced_nearest:
street_gdf = streets.loc[edge]['geometry']
lat_list = list(street_gdf.xy[1])
lon_list = list(street_gdf.xy[0])
[centerline_points.append(Point(_lat, _lon)) for _lat, _lon in zip(lat_list, lon_list)]
# instantiate simpleKml
kml = simplekml.Kml()
coords = zip(lon_list, lat_list)
# plot line
ls = kml.newlinestring(name="matched")
ls.coords = coords
ls.style.linestyle.width = 2
ls.style.linestyle.color = simplekml.Color.red
ls.altitudemode = simplekml.AltitudeMode.relativetoground
# save points to file
output_filename = "tests/map_provider_matched.kml"
kml.save(output_filename)
Here is the test data I am using: test_data
Any ideas for how i can get better performance? I've tried using a different nearest neighbor function, but that performed even worse that ox.nearest_edges.