How to fully disable response simplification?

I work for for wecity - a mobile app which rewards sustainable mobility - and I’m using the map-matching tool for the creation of maps which show the “safety” (/cyclability) rating of various OSM edges, as evaluated from the feedbacks uploaded by the app users along with the GPS traces of their bike commutes.

A rough explanation of the process leading to the maps:

    • I receive sets of “raw” GPS points (subject to error, thus in general not laying on any OSM edge), each of them representing a trip performed by a user, and the corresponding value from 1 to 5 representing the overall safety rating of the trip as evaluated by the user.
    • I use a python script (which sends a map-match request to my locally hosted graphhopper) to convert such trips into sequences of edges (each edge is intended as an unordered set of two points) that actually lay on the OSM graph, and store the sequences into a postgis database along with their safety ratings and a few other attributes.
    • I use spatial queries for grouping the records by edge, and compute an average rating for every unique edge within a set of map-matched trips (such set is selected filtering the whole map-matched trips database with conditions on the trip bounding box - e.g. the trip is contained within a given city administrative boundary - and/or on other trip features - e.g. datetime).

Nonetheless, my first attempt at plotting the map highlighted a relevant issue: in some regions of the map I had many overlapping edges, with different rating values. Since graphhopper should return a sequence of edges “picked up” from a set of edges (the graph) which does not change between the subsequent map-matching processes, I thought that two map-matched trips that overlap on some part should contain the same points for regarding the road stretch on which they do overlap.

After being partially illuminated by this topic, I added &wayPointMaxDistance=0.0 to my request. This significantly reduced the problem. From what I understand the final map-matched path (in terms of list of points) is simplified before being returned as the map-matching result: I guess such simplification is applied by removing some of the points as long as their removal does not change (beyond a certain threshold, which I did set to 0.0) the shape of the total path.

Still, my trick didn’t fix all cases. I noticed that some nodes are still being skipped by my map-matching response:

E.g. in the map-matched trip (red line, yellow points) reported above some nodes (their approx location marked with ?) – that must be present in the grapphopper graph as they’re shared between multiple edges – are skipped. I guess this is because their removal does not change the shape of the final polyline, as the path is perfectly straight in the proximity of such nodes.

Still, for a successful and unambiguous visualization I would need to obtain the full node list at every match, and zeroing the threshold is clearly not enough.
Since I don’t use graphhopper from a java environment I can’t reproduce some of the suggestions from the topic I mentioned, so I’m wondering if there’s a way to fully disable the simplification (response simplification only, I don’t care about graphhopper graph being less detailed than the OSM graph) by changing some lines in the core. Does anybody knows where response simplification is applied?

I think here: https://github.com/graphhopper/graphhopper/blob/14bd13a78bd494173109016b58c05759d9cc680d/web-bundle/src/main/java/com/graphhopper/resources/MapMatchingResource.java#L138

But since you set wayPointMaxDistance to 0 it should already be disabled? Maybe use a debugger to find out what is going on. And isn’t the parameter called way_point_max_distance not wayPointMaxDistance?

Which GH version do you use?

2 Likes

We also simplify on import and the default is 1m:

graphhopper:
  ...
  routing.way_point_max_distance: 1

I’m really embarrassed to admit that this was the problem, I don’t know why I thought it was performing any better when I did set an inexistent parameter to 0.0
Thank you so much!

4.0

Thank you for the hint. From what I understand this other simplification is applied when the osm.pbf file is converted into the graph that graphhopper employs for the routing, leading to a graphhopper graph which is geometrically “less precise” (but lighter) than the original OSM graph. Am I right?

No worries, I’m glad we figured out the issue.

Yes, during import the geometry of the road is simplified, but some the points you marked in your screenshot won’t be affected because they are junctions between different roads.

As you may have guessed I managed to disable the simplification. Nonetheless, the results were not quite as expected. I wanted to disable the simplification in order to allow a “cleaner” grouping of the resulting edges (better explained in my first post).

After disabling the simplification my map-matched trips database contained approx. 6 000 000 lines (one line for each edge that was crossed in one of the map-matched trips) - that’s reasonable, it resulted in 4 500 000 lines before - but after the grouping (by normalized geometry) it only reduced to 2 600 000 unique edges, while when the simplification was allowed the unique edges resulted to be only 100 000. Things are significantly worse this way.

Therefore, I plotted the map-matched nodes from 10 trips that overlap in some parts in order to check if the map- matching process returned the same nodes when suggesting the same path. This is what I obtained (I suggest to use the link, the popups help understanding the map content which is hard to explain with a static image):

Simplification disabled:

Simplification allowed:

As an example, I’ll refer to the small stretch of cycleway highlighted in the images above. Such path is crossed by three trips, of ids 3, 5 and 8. It is a relatively isolated path, so it is sure enough that all the three map-matched trips should point to the very same osm way. Disabling the simplification adds one additional point to every one of these trips, but the additional points do not coincide.

Therefore I’m confused. Having disabled the simplification, shouldn’t I obtain all the nodes that are present on the path in the three cases? I.e. should’t three trips result in the very same nodes on that part?

Thank you,
Pietro