Sharing in case it's helpful my step-by-step for using pgMapMatch. I have almost no knowledge of SQL so I'm including instructions for setting up the postgres database as well. I am using Ubuntu 22.
- Set up a postgres database. Run the following in a terminal:
- Install pgrouting extension for postgres:
sudo apt install postgresql-14-pgrouting
- Change to default user "postgres":
sudo -u postgres -i
- Create a new postgres database:
createdb database-name
- Connect to the database:
psql database-name
- Add postgis extension:
CREATE EXTENSION postgis;
- Add pgrouting extension:
CREATE EXTENSION pgRouting;
Note: I had to uninstall postgres and reinstall it to allow me to install a compatible version of postgis. If this applies, do this before step 1:
sudo apt-get --purge remove postgresql postgresql-*
sudo apt update
sudo apt install postgresql
sudo apt install postgresql-14-postgis-3
- Create Python environment. Since the fix to
mapmatcher.py for newer scipy versions, requiring scipy=1.8 may not be necessary.
conda create -n pgmapmatch -c conda-forge python=3 "scipy=1.8" pandas gpxpy psycopg2 sqlalchemy docopt
- Save street network file to postgis database. Using the sample data provided as a shapefile and working in Python:
from sqlalchemy import create_engine
import geopandas as gpd
engine = create_engine("postgresql+psycopg2://postgres:postgres@localhost:5432/database-name")
sf_streets = gpd.read_file("sf_streets.shp") # sample data
sf_streets.columns = sf_streets.columns.str.lower() # postgres doesn't like uppercase?
sf_streets.to_postgis("sf_streets", engine, if_exists = 'replace') # save to postgis database
- Run pgMapMatch. I was not able to get my trace data to work as a postgis database, so I am running with individual gpx files. See note at the bottom for creating gpx files from shapefiles.
- Copy
config_template.py to config.py
- Update database connection info in
config.py, it will look something like this if using a local database:
pgInfo = {'db': 'database-name',
'schema': 'public', # schema with GPS traces and streets table
'user': 'postgres',
'host': 'localhost',
'requirePassword': False # Prompt for password? Normally, False for localhost
}
- Add current folder to PATH to import pgMapMatch as a package:
export PYTHONPATH=.
- In Python (same as the sample code in the README):
import pgMapMatch
streets_table = 'sf_streets' # the name of your Postgres table with streets
mm = pgMapMatch.mapMatcher(streets_table)
your_gpx_filename = 'pgMapMatch/testdata/testtrace_36.gpx'
mm.matchGPXTrace(your_gpx_filename)
print(mm.bestRoute)
Best route output: [107059, 107060, 87737, 107056, 107057, 108203, 113936, 125564, 107060, 87796, 107055, 107056, 87725, 125408, 37189, 37188, 87797, 87796, 87795, 39950, 39951]
Note: to create gpx files from shapefile data or a csv with lat long (with timestamps, required for the package), do something like below, which is based on the example in the gpxpy docs:
import gpxpy
import geopandas as gpd
import datetime
data = gpd.read_file("your_trace_data.shp")
def save_gpx(gdf, trip_id):
gpx = gpxpy.gpx.GPX()
# Create first track in our GPX:
gpx_track = gpxpy.gpx.GPXTrack()
gpx.tracks.append(gpx_track)
# Create first segment in our GPX track:
gpx_segment = gpxpy.gpx.GPXTrackSegment()
gpx_track.segments.append(gpx_segment)
# Create points:
for i, row in gdf.iterrows():
lat = row['latitude']
lon = row['longitude']
ts = datetime.datetime.fromtimestamp(row['ts']) # 'ts' is the timestamp column in ISO 8601 format
gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(lat, lon, time=ts))
# save to file
with open("{}.gpx".format(trip_id), "w") as f:
f.write(gpx.to_xml())
for trip_id, group in data.groupby('trip_id'):
save_gpx(group, trip_id)
Sharing in case it's helpful my step-by-step for using pgMapMatch. I have almost no knowledge of SQL so I'm including instructions for setting up the postgres database as well. I am using Ubuntu 22.
sudo apt install postgresql-14-pgroutingsudo -u postgres -icreatedb database-namepsql database-nameCREATE EXTENSION postgis;CREATE EXTENSION pgRouting;Note: I had to uninstall postgres and reinstall it to allow me to install a compatible version of postgis. If this applies, do this before step 1:
sudo apt-get --purge remove postgresql postgresql-*sudo apt updatesudo apt install postgresqlsudo apt install postgresql-14-postgis-3mapmatcher.pyfor newer scipy versions, requiring scipy=1.8 may not be necessary.conda create -n pgmapmatch -c conda-forge python=3 "scipy=1.8" pandas gpxpy psycopg2 sqlalchemy docoptconfig_template.pytoconfig.pyconfig.py, it will look something like this if using a local database:export PYTHONPATH=.Best route output:
[107059, 107060, 87737, 107056, 107057, 108203, 113936, 125564, 107060, 87796, 107055, 107056, 87725, 125408, 37189, 37188, 87797, 87796, 87795, 39950, 39951]Note: to create gpx files from shapefile data or a csv with lat long (with timestamps, required for the package), do something like below, which is based on the example in the gpxpy docs: