Curbside right and turning circles


I’m forcing curbside right on a street that ends in a turning circle but GH response is that it cannot find connection. The street is a two way street, so vehicle could go to the end and use turning point to get out of that street. My question is, during the import or load do you consider turning points from OMS as places where is possible to make U-turns? If not how can I handle this situation?

Thank you in advance,

Do you have a link to that route (on GraphHopper allows u-turns at all junctions and dead-ends, too. For example here: Driving Directions - GraphHopper Maps

Did you set the u_turn_costs parameter to a finite value in your profile? If not they will be forbidden which would explain the problem you are describing.

Hi easbar,

I think I did not set U_TURN_COSTS to a finite value. Default is infinite? Is that it? Can you explain what should I type here to force curbside right and to set a finit u_turn_cost, please?
“speed”: [
“if”: “road_class == MOTORWAY”,
“multiply_by”: 0.8
“priority”: [
“if”: “road_environment == TUNNEL”,
“multiply_by”: 0.0
“if”: “max_weight < 3”,
“multiply_by”: 0.0

Also if I’m using java, should I put something on the hints map to have finite u_turn_costs?
I was trying with this:

List<String> snapPreventions = new ArrayList<String>(6);
List<String> curbsides = new ArrayList<String>();
GHRequest req = new GHRequest(latFrom, lonFrom, latTo, lonTo);//.
req.putHint(Routing.FORCE_CURBSIDE, false);
req.putHint(Routing.U_TURN_COSTS, 1);
GHResponse rsp = hopper.route(req);

Thank you for your help


Turn costs are not set in the custom model (yet). You need to set this up in your profile. So in config.yml you would do for example:

  - name: car
    vehicle: car
    turn_costs: true
    u_turn_costs: 60 #in seconds
    weighting: custom
    custom_model_file: my_model.json

in Java:

new CustomProfile("car").putHint(Routing.U_TURN_COSTS, 40).setCustomModel(...);

If you setup the u-turn costs for the profile you do not need to set the u-turn costs for each request. But unless you use CH/speed mode you can change them on a per-request basis.

Hi easbar,

Thank you so much for your help. I manage to make it work. Still, I have one question. When you say “all junctions and dead-ends” you mean only the ones where OSM allows to make a u-turn, like this:

Or is any junction, even if information from OSM forbids the u-turn?

No, if a u-turn is forbidden explicitly (e.g. by the restriction=no_u_turn relation tag) there won’t be a u-turn at this junction.

Thank you for all your help easbar.

Sorry easbar, but I was trying out and I came into an example where the path tells me to make a u turn where is not possible to do it.

At this junction is not possible to make a u-turn.

I’m coming in the direction of the arrow on the image bellow.

Also the direction given by GH don’t seem correct:

Distance: 458.7992296360908 and time: 101092
(0,Rua Mouzinho da Silveira,226.0795480812837,27129)
(2,Rua Alexandre Herculano,80.274,4816) 
(7,Rua Alexandre Herculano,109.579,6575) 
(3,Rua Alexandre Herculano,42.866681554807066,2572)
(4,,0.0,0) (38.72164558115734, -9.15147490378864)

How can I turn sharp right ((3,Rua Alexandre Herculano,42.866681554807066,2572)) if there is no way I can turn right on this street? The only thing possible to do at this junction is to turn left. Not make u-turn (right or left) not make any turn sharp right nor left.

Can you help me please?

Thank you in advance.

This is indeed unexpected. There is a no_u_turn restriction at this junction, but it is somehow ignored: Relation: 7871507 | OpenStreetMap

My previous answer was not accurate. GraphHopper does parse the restriction=no_u_turn relations, but they do not take precedence over the global u-turn costs you set in the profile. So basically they are ignored, which I now think is a bug (see no_u_turn is ignored · Issue #2570 · graphhopper/graphhopper · GitHub).

To workaround this for now you could try replacing these lines in DefaultTurnCostProvider:

        double tCost = 0;
        if (edgeFrom == edgeTo) {
            // note that the u-turn costs overwrite any turn costs set in TurnCostStorage
            tCost = uTurnCosts;
        } else {
            if (turnCostEnc != null)
                tCost = turnCostStorage.get(turnCostEnc, edgeFrom, nodeVia, edgeTo);
        return tCost;

by the following lines:

    double storedTurnCost = turnCostEnc == null ? 0 : turnCostStorage.get(turnCostEnc, edgeFrom, nodeVia, edgeTo);
    if (edgeFrom == edgeTo && storedTurnCost == 0) 
          return uTurnCosts;
    return storedTurnCosts;

(but if you use CH you need to run the import again)

Hi easbar,

I followed your sugestion and instead of making a u-turn on the street that it was doing previously, it still does on a place where also is not allowed to do that.

Since it seems is not possible to solve this, is that a way to allow u-turns only on dead-ends?

Thank you in adavance.

You mean it no longer does a u-turn at the junction that had restriction=no_u_turn and now it does a u-turn at another junction that has restriction=no_u_turn? That seems very strange. Which junction is it?

Allowing u-turns only at dead ends is possible but needs some programming and thought I think. You would have to either remove the global u-turn costs and add u-turn costs for all dead ends explicitly, or replace the simple u-turn check we currently do (edgeFrom == edgeTo) with something that checks whether the given node is a dead-end.

Hi easbar,

Is right in the next junction. It doesn’t make a u-turn in the first junction but it makes in the next one where is also forbidden. I tried this in a couple on streets to check if the behavior has the same and it is. Do you want me to sent the exact examples?

Do you have this information on the node? Can you tell me how I recognize a node that is a dead end?

Is right in the next junction. It doesn’t make a u-turn in the first junction but it makes in the next one where is also forbidden. I tried this in a couple on streets to check if the behavior has the same and it is. Do you want me to sent the exact examples?

Yes, I’m afraid without any example I cannot tell what the problem is.

Do you have this information on the node? Can you tell me how I recognize a node that is a dead end?

A dead-end would be a node that has only one edge. So you can do something like this:

// reuse this for each junction
EdgeExplorer explorer = graph.createEdgeExplorer();
EdgeIterator iter = explorer.setBaseNode(node);
int count = 0;
while ( 
if (count == 1)
   // this node is a dead end

Hi easbar,

With the change you suggested in DefaultTurnCostProvider the path is:

Distance: 631.6836163724382 and time: 111466
(0,Rua Mouzinho da Silveira,226.0795480812837,27129) (38.72264052206826, -9.15029732577064)
(2,Rua Alexandre Herculano,276.2953867363474,16578) (38.7223916, -9.1500762)
(3,Rua Alexandre Herculano,129.30868155480707,7759) (38.7209899, -9.1527059)
(4,,0.0,0) (38.72164558115734, -9.15147490378864)

The 3rd instruction is a turn sharp right (should be left at least, not right) is in a place where I cannot turn:

Without the change the suggested path is:

Distance: 458.7996163724382 and time: 101092
(0,Rua Mouzinho da Silveira,226.0795480812837,27129) (38.72264052206826, -9.15029732577064)
(2,Rua Alexandre Herculano,189.85338673634737,11391) (38.7223916, -9.1500762)
(3,Rua Alexandre Herculano,42.866681554807066,2572) (38.721428, -9.1518828)
(4,,0.0,0) (38.72164558115734, -9.15147490378864)

My u turn costs are set to 30.

Do you have anymore ideas of how to workaround this?

Thank you,

This looks like another bug to me. There is an only_right_turn restriction for this other junction: Relation: 5964521 | OpenStreetMap which means there should be no u-turns. But apparently we do not set turn restrictions for u-turns at all: graphhopper/ at e2d844309ac47395298e57b5aaa3e4086573a081 · graphhopper/graphhopper · GitHub

I opened another issue for this: only_right_turn does not prevent u-turns · Issue #2578 · graphhopper/graphhopper · GitHub

You could probably try removing the edgeId != edgeIdFrom check from the code I linked above. But right now I’m not sure if this requires further thought. The next step here would be adding some (or adjusting some of the existing) unit tests that make sure the turn costs are correctly parsed from OSM. Contributions are always welcome of course :slight_smile:

The other thing you could still try is what we discussed above: Disable the global u-turn costs and only apply them at dead-end streets, but this requires some programming as well.

Thank you for your feedback.

I’ll try to do some tests with your suggestions.


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.