Don’t hesitate to contact us:
Forum: discuss.graphhopper.com
Email: support@graphhopper.com
The upcoming version 1.0 of the GraphHopper routing engine has a new customizable routing feature.
Disclaimer: We updated the format for custom models. See the updated blog post with several examples.
To install GraphHopper with this feature on your own server download the JDK, the routing server, the configuration file and the OpenStreetMap data:
# if you have no JDK installed get it from: https://adoptopenjdk.net/
wget https://oss.sonatype.org/content/groups/public/com/graphhopper/graphhopper-web/1.0/graphhopper-web-1.0.jar
wget https://raw.githubusercontent.com/graphhopper/graphhopper/1.0/config-example.yml
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
Now edit the downloaded config-example.yml and add the following car profile, please note that indentation is important in YAML:
graphhopper:
...
profiles:
- name: car
vehicle: car
weighting: custom
custom_model_file: empty
# also add the configuration:
routing.ch.disabling_allowed: true
Then you can start the java server:
java -Ddw.graphhopper.datareader.file=berlin-latest.osm.pbf -jar graphhopper-web-1.0.jar server config-example.yml
which should give you a similar log output:
...
io.dropwizard.server.ServerFactory - Starting GraphHopperApplication
...
c.g.reader.osm.GraphHopperOSM - version 1.0|2020-05-01T21:00:45Z (5,15,4,3,5,6)
c.g.reader.osm.GraphHopperOSM - start creating graph from berlin-latest.osm.pbf
...
c.g.routing.ch.CHPreparationHandler - 1/1 calling CH prepare.doWork for profile 'car' NODE_BASED
...
c.g.reader.osm.GraphHopperOSM - flushing graph CH|car|RAM_STORE|2D|no_turn_cost|5,15,4,3,5, details:edges:133 725...
...
org.eclipse.jetty.server.Server - Started @23477ms
When you start the server the first time it will take a bit longer as it creates the road network (the part after “start creating graph”) and helper files (the part of CHPreparationHandler) inside the graph-cache
folder.
Now open the GraphHopper Maps demo UI that is available on your local machine: http://localhost:8989/maps/?point=52.48947%2C13.346329&point=52.565917%2C13.450699&profile=car
Click on the small “flex” button near the “Search” button and a text input will open. Include the following:
priority:
road_class: { primary: 0.5 }
to e.g. avoid primary roads (see below for “prefer”). The route will be evaluated on-the-fly and the query speed is already perfect for most real world scenarios.
Increasing the priority of primary roads works a bit different: decrease the priority of “all other roads”, which can be done using the so called “catch-all” key and set the priority of primary to 1.0:
priority:
road_class: { primary: 1.0, "*": 0.5 }
To learn more about the possibilities read the documentation. Also you’ll notice that when you place the cursor in the text input on e.g. “road_class
” it will list all available values like motorway or footpath, or place it on “priority
” this will list all available so called “encoded values” like road_class
, but also road_environment
(bridge, tunnel, …). By default several useful “encoded values” are already available. For example click on the top right button and select “Omniscale Dev” and “Local MVT” then you can hover your mouse and see the “encoded values” road_environment, road_class and max_speed on the left panel for every road segment:
You can add more encoded values like surface
or toll
when you add the following in the config-example.yml:
graph.encoded_values: surface,toll,max_width,max_weight,max_height,hazmat,toll,track_type
To make them available in the graph you have to:
graph-cache
andThis procedure is always required when you want to make changes to the graph itself, so more or less every time you edit the config-example.yml or when you want to update the OSM data.
To have a fast response also for longer routes like across Europe you put the customization in a YAML (or JSON) file and provide this at import time. I.e. create a local file profile1.yml with the following content:
priority:
road_class: { primary: 0.5 }
In the config-example.yml file replace:
custom_model_file: empty
with
custom_model_file: profile1.yml
Now again remove the graph-cache
folder and restart the server again.
When you now open the UI the default vehicle profile will already avoid the primary road_class without the need to specify this in the request. But the big difference is the query speed. You won’t notice this for the Berlin example, still you try a larger area, e.g. download a OSM pbf file for a bigger area (and remove the graph-cache to force a re-import) and try this again.
Technically we enabled a Contraction Hierarchy (CH) preparation for the custom car profile, this is called the speed mode, see the profiles_ch
section in config-example.yml. This step introduces shortcut edges and uses a special query to significantly improve query speed for long routes. The downside is that currently you cannot further customize a “CH prepared profile” per-request.
To get faster response times and still being able to customize the profile per-request you can enable the hybrid mode which uses the landmark (LM) preparation under the hood:
graphhopper: ... profiles_lm: - profile: car
To make this change available you again need to remove graph-cache and restart the server.
Get a more sophisticated profile in this truck example file.
Let’s add a bike profile and highly prefer roads that are part of the official bike network. To do this first add the bike flag encoder and also change the profiles section:
graphhopper:
...
graph.flag_encoders: car,bike
profiles:
- name: car
vehicle: car
weighting: custom
custom_model_file: empty
- name: bike
vehicle: bike
weighting: custom
custom_model_file: empty
Remove the graph-cache
folder and restart the server again. You’ll now see also bike
in the logs:
c.g.reader.osm.GraphHopperOSM - using CH|car,bike|RAM_STORE|2D|no_turn_cost
When the server is ready you’ll again being able to open the previous link: http://localhost:8989/maps/?point=52.48947%2C13.346329&point=52.565917%2C13.450699&profile=car
The only tiny difference is that a bike icon is additionally displayed. Click on it. You’ll get an error which reads:
Cannot find CH preparation for the requested profile: 'bike' You can try disabling CH using ch.disable=true available CH profiles: [car]
This error tells us that we cannot use speed mode for our new bike profile yet. We have two options: 1) We can keep using the profile using the hybrid mode and further adjust it to our needs and 2) we can enable speed mode once we are fully satisfied with our settings. Let’s see how this works.
Disable the speed mode (CH) in the request, i.e. append a special parameter to the URL which will be forwarded to the routing server: http://localhost:8989/maps/?point=52.48947%2C13.346329&point=52.565917%2C13.450699&profile=bike&ch.disable=true
This is sufficient to try out the custom weighting with bike. Click again on the “flex” icon near the “Search” button and enter the following text:
priority:
bike_network: { other: 0.4 }
When you click again on the button in the top right corner and select “TF Cycle” some nice bike maps will appear. The blue, purple or red marked roads are official recommended routes from different bike networks. And with the steps above we avoid all roads that are not part of this network. You can reduce the number to e.g. 0.1 and see that the route will “snap” to these official bike network even if that means a huge detour:
Get a more sophisticated “cargo bike” profile in this example file.
Now we can enable the speed mode also for bike. To do that we only have to add “bike” to the profiles_ch section in the config-example.yml:
graphhopper:
...
profiles_ch:
- profile: car
- profile: bike
Then once again remove the graph-cache
folder and restart the server again. You’ll now notice the following two entries in the logs:
c.g.routing.ch.CHPreparationHandler - 1/2 calling CH prepare.doWork for profile 'car' NODE_BASED
c.g.routing.ch.CHPreparationHandler - 2/2 calling CH prepare.doWork for profile 'bike' NODE_BASED
Which means that it will use a bit more RAM (and space on disk) but also take a bit longer. After that you’ll be able to click on the bike icon:
http://localhost:8989/maps/?point=52.48947%2C13.346329&point=52.565917%2C13.450699 or follow this link to get the bike icon pre-selected. Now with this additional “CH preparation” also the bike profile responds fast even for long-distance routes.
If you have questions or feedback for this tutorial, you can comment in this topic.