Problems with MapMatching 0.8.2

Hey there,

we have created a small Java project which takes GPS tracks from a PostGIS database, sends it to the GraphHopper MapMatching v8.2 and imports the matched track back into the database.

When I check the result in QGIS I can see, that the geometry has changed, but it is not matched against the OSM road network (blue is original, orange is the match result)

I suppose we do not use the the map matching class correctly. Here is our code:

public class MapMatcher {
    private static GraphHopperOSM hopper;
    private CarFlagEncoder encoder;
    private AlgorithmOptions opts;
    
    private void MapMatcher() {
        encoder = new CarFlagEncoder();
        hopper = new GraphHopperOSM();
        hopper.setDataReaderFile("./src/main/resources/Dresden.osm.pbf");
        hopper.setGraphHopperLocation("./src/main/resources/carTrack-gh");
        hopper.setEncodingManager(new EncodingManager(encoder));
        hopper.getCHFactoryDecorator().setEnabled(false);
        hopper.importOrLoad();
        
        opts = AlgorithmOptions.start()
                .algorithm(Parameters.Algorithms.DIJKSTRA_BI).traversalMode(hopper.getTraversalMode())
                .weighting(new FastestWeighting(encoder))
                .maxVisitedNodes(1000)
                .hints(new HintsMap().put("weighting", "fastest").put("vehicle", encoder.toString()))
                .build();
    }

    public List<GPXEntry> doMapMatching(List<GPXEntry> gpxUnmatched) {
        List<GPXEntry> gpxMatched = new ArrayList<GPXEntry>();
        
        MapMatching mapMatching = new MapMatching(hopper, opts);
        mapMatching.setMeasurementErrorSigma(50);

        MatchResult mr = null;
        try {
            mr = mapMatching.doWork(gpxUnmatched);
        }
        catch (Exception ex) {
            System.out.println("MapMatching error");
            return null;
        }
        
        List<EdgeMatch> matches = mr.getEdgeMatches();

        // finally transform EdgeMatch list to list of gpxEntries
        for (EdgeMatch edgeMatch : matches) {
            List<GPXExtension> gpxExtensions = edgeMatch.getGpxExtensions();
            // add matched gpx to the list
            for (GPXExtension gpxExtension : gpxExtensions) {
                gpxMatched.add(gpxExtension.getEntry());
            }
        }
        
        return gpxMatched;
    }
}

The track on the screenshot has the following input values:

longitude:13.757166862487793; latitude:51.02519607543945; time:1414499495000
longitude:13.757805824279785; latitude:51.024723052978516; time:1414499500000
longitude:13.758500099182129; latitude:51.02427673339844; time:1414499505000
longitude:13.759222030639648; latitude:51.0238037109375; time:1414499510000
longitude:13.759944915771484; latitude:51.02336120605469; time:1414499515000
longitude:13.760777473449707; latitude:51.02288818359375; time:1414499520000
longitude:13.761638641357422; latitude:51.02244567871094; time:1414499525000
longitude:13.762527465820312; latitude:51.02199935913086; time:1414499530000
longitude:13.763416290283203; latitude:51.021610260009766; time:1414499535000
longitude:13.764277458190918; latitude:51.021305084228516; time:1414499540000
longitude:13.765193939208984; latitude:51.020999908447266; time:1414499545000

I hope that I just made an obvious mistake :slight_smile:

Thx in advance
Felix

It is only hardly visible but in which scale do you see differences?

Can you do a simple route from start to end and see if you get the same differences there? Then it might be a problem that we simplify the OSM data (within 1m boundaries)

So this is scale 1:3000 with a few more tracks. If you simplify OSM data, that’s fine. In the end I just want to compare the matched tracks. So if two cars took the same street the tracks should be identical for the corresponding segments.

It’s obviously not matched, but also different from the input data … so some simplification is happening…
Btw it worked with the previous MM version (except for some errors).

This looks like you are just plotting the junction nodes or some other partial nodes and no data in between. The matching definitely works (see our unit tests and try with the simple UI) so I expect some wrong config, but the code above looks good to me. A bit strange.

Update: can you try to use the path/geometry returned from here:
Path path = mapMatching.calcPath(mr);

Ok, I found my error:

for (EdgeMatch edgeMatch : matches) {
    List<GPXExtension> gpxExtensions = edgeMatch.getGpxExtensions();
    for (GPXExtension gpxExtension : gpxExtensions) {
        // this just gives me an entry from my input(!) which is closest to the tower node of the matching edge
        gpxMatched.add(gpxExtension.getEntry());
    }
} 

So, as you said, I just took junction nodes and only from the input. That’s why they looked so similar to the original tracks.
When I use …

mr = mapMatching.doWork(gpxUnmatched);
Path path = mapMatching.calcPath(mr);
points = path.calcPoints();

… I get what I want … except for the time :wink:

1 Like

Results are looking very good.

I’ve also implemented a time matching between the original data and the matching output, that I will share pretty soon. But it only copies timestamp from matching nodes - so some nodes are still having no time then. But this I can repair in PostGIS - and Java too I guess …

1 Like

By the time, I’ve put my map matching project on GitHub.

I’ve added time and speed interpolation to the matched tracks. It does not work perfectly in all cases, unfortunately (e.g. if a trajectory has been passed twice). Plus, the code is not parallized yet.

Thanks. What do you mean with parallelized?

I mean, process my source data with multiple threads. I got one year of constant GPS tracks of nearly 500 cars which are processed in sequential order at the moment. Nothing directly related to Graphhopper MapMatching. That’s super fast :wink: In the end I’m having around 5 mio. tacks in my DB.

1 Like