Snaps GPX traces to the road using the GraphHopper routing engine.
Read more about the map matching problem at Wikipedia.
Currently this project is under development but produces already good results for various use cases. Let us know how it works for you!
See the demo in action (black is GPS track, green is matched result):
Apache License 2.0
Our web forum is here.
Java 8 and Maven >=3.3 are required. For the 'core' module Java 7 is sufficient.
Build:
mvn package -DskipTests
Then you need to import an OSM map for the area you want to do map-matching on, e.g. the provided sample data:
java -jar matching-web/target/graphhopper-map-matching-web-0.11-SNAPSHOT.jar import map-data/leipzig_germany.osm.pbf
OpenStreetMap data in pbf or xml format are available from here.
The optional parameter --vehicle
defines the routing profile like car
, bike
, motorcycle
or foot
.
You can also provide a comma separated list. For all supported values see the variables in the FlagEncoderFactory of GraphHopper.
Before re-importing, you need to delete the graph-cache
directory, which is created by the import.
Now you can match GPX traces against the map:
java -jar matching-web/target/graphhopper-map-matching-web-0.11-SNAPSHOT.jar match matching-core/src/test/resources/*.gpx
Start via:
java -jar matching-web/target/graphhopper-map-matching-web-0.11-SNAPSHOT.jar server config.yml
Access the simple UI via localhost:8989.
You can post GPX files and get back snapped results as GPX or as compatible GraphHopper JSON. An example curl request is:
curl -XPOST -H "Content-Type: application/gpx+xml" -d @matching-core/src/test/resources/test1.gpx "localhost:8989/match?vehicle=car&type=json"
Determine the bounding box of one or more GPX files:
java -jar matching-web/target/graphhopper-map-matching-web-0.11-SNAPSHOT.jar getbounds matching-core/src/test/resources/*.gpx
Have a look at MapMatchingResource.java
to see how the web service is implemented on top
of library functions to get an idea how to use map matching in your own project.
Use this Maven dependency:
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-map-matching-core</artifactId>
<version>0.11-SNAPSHOT</version>
</dependency>
Note that the edge and node IDs from GraphHopper will change for different PBF files, like when updating the OSM data.
The map matching algorithm mainly follows the approach described in
Newson, Paul, and John Krumm. "Hidden Markov map matching through noise and sparseness." Proceedings of the 17th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems. ACM, 2009.
This algorithm works as follows. For each input GPS position, a number of map matching candidates within a certain radius around the GPS position is computed. The Viterbi algorithm as provided by the hmm-lib is then used to compute the most likely sequence of map matching candidates. Thereby, the distances between GPS positions and map matching candidates as well as the routing distances between consecutive map matching candidates are taken into account. The GraphHopper routing engine is used to find candidates and to compute routing distances.
Before GraphHopper 0.8, this faster but more heuristic approach was used.