Trying to understand turn cost docs

Hey all,

I’m trying to enable turn costs in my graphhopper index (to see if it makes my routing times more realistic) and I’m a little confused by the docs. I’m happy to submit patches with better language if someone can help me understand it better.

What’s the difference between and in config.yml? as described in

My other confusion is with config-example.yml, this whole section is confusing me

To enable turn-costs in speed mode (contraction hierarchies) edge-based graph traversal and a more elaborate

pre-processing is required. Using this option you can either turn off the edge-based pre-processing (choose ‘off’),

use edge-based pre-processing for all encoders/vehicles with turn_costs=true (choose ‘edge_or_node’) or use node-based

pre-processing for all encoders/vehicles and additional edge-based pre-processing for all encoders/vehicles with

turn_costs=true (choose ‘edge_and_node’). off

question: why doesn’t it mention like the docs do?
question: am I supposed to set this to true or on or something else?
question: how is relatd to



there is an error in the docs: It should read instead of The options are: off, edge_or_node and edge_and_node, just as it is described in config-example.yml. I will fix this.

Can you understand what they mean by reading (only) config-example.yml? If not feel free to suggest a better description of the parameters.

Btw these configuration options will be changed soon. See this issue which also might help understanding the current state:

Btw ‘enabling turn costs’ currently only means two things:

  • turn restrictions (like ‘left only’ or ‘no right turn’) from OSM will be respected
  • u-turns will either be forbidden or there will be a time penalty whenever a route takes a u-turn. note that without turn restrictions there would not be any u-turns anyway

So currently using turn costs does not necessarily lead to more realistic routing times (except the fact that the routes no longer involve forbidden turns). This is something that will hopefully be improved in the future (its mostly a matter of modeling the turn costs and the refactoring needed for this).

Thanks so much for the rapid reply.

From config-example.yml, the description doesn’t help me understand why I’d pick edge_or_node or edge_and_node / what the difference is. Could you update that too?


Does this help?

Yes that helps a lot, thank you.

Still have a few questions after this

  • how do I switch my routing from CH/node to edge-based? Is that a query-time option?
  • it seems like most people probably want edge_or_node? when would I not?
  • is there a benefit to edge+turn_costs over CH/node+turn_costs?

Yes there is a query time option: turn_costs=true/false.

Using edge_and_node allows you to choose between edge- and node-based routing on each request. Choosing between the two can be useful, because edge-based allows including turn costs, while node-based is faster.

node+turn_costs is not possible (that is the whole reason why there is edge-based)

So if I want to always care about turn_costs, I should do edge_or_node, yes?


1 Like

Hey esabar,

Thanks so much for all your rapid replies.

Given the other thread about build times, it seems like building node_or_edge+CH for planet.osm is … impractical. I’m at about 48 hours and the graph still has 40 million nodes to go.

If I want to build a global routing index that does take into account turn costs and have it finish in some reasonable amount of time, it seems like I need to try building an index without contraction hierarchies, is that right? Would I want hybrid mode? I’m a little confused by the config-example docs again for this.

At the end of the day what I really care about is getting a routing graph that has reasonably accurate routing times. As a case study, I’m looking at what GH hosted routes for this route (6 min):

whereas my index does this

I was hoping that perhaps turn costs would help influence it to a more realistic driving time, but maybe I’m wrong.


See this discussion for differences between open source and hosted version:

The example you are showing does not include a turn restriction, you can try adding an intermediate stop and you will see that the result will be the same route you get locally, but with another estimated time of arrival.

If you want to try the effects of turn restrictions you do not need to build an index at all. Just disable speed or hybrid mode and you can still perform route calculations (they will just be much slower). And yes using hybrid mode would be a compromise between getting the full speed of Contraction Hierarchies and a faster index building time.

Powered by Discourse