How can I make GH consider the right side of the road?

Hi,
I’m using GH framework routing engine and it worked great for me until a task emerged to route monitoring complexes, that monitor only the right side of the street. By default GH builds a route like this for smaller streets

https://graphhopper.com/maps/?point=55.73065%2C37.563833&point=55.731224%2C37.565099&locale=ru-RU&elevation=true&profile=car&use_miles=false&selected_detail=max_weight&layer=Omniscale

while I need it like this, like with bigger streets (motorways or how exactly they are qualified?)

https://graphhopper.com/maps/?point=55.729669%2C37.565684&point=55.730107%2C37.566687&locale=ru-RU&elevation=true&profile=car&use_miles=false&selected_detail=max_weight&layer=Omniscale

it would work for me ok, if I could make GH treat all streets in this task like in second example. Is it possible in some way?

Thanks in advance!

Hiya, within your setup you need to force curbside.
I’m on mobile so cannot share specific code.

This can be applied per route/point if you know your requirement before hand. I’ve only ever done between short routes of two.
You can also set turn costs to all vehicles to be unable to do uturns on a dime, so your example #2, they are then required to find a junction to complete a uturn.

Check in github for some use examples. Sorry can’t be more help at the moment.

2 Likes

Thanks a lot, Gregws!
It worked for me fine, though it was not that straightforward for a novice to find that I need
hopper.setEncodingManager(EncodingManager.create(“car|turn_costs=true”));
and then delete graphhopper folder contents, took some digging, still lacks documentation a bit ))

One more question: if, for some reason, I need to work with a profile with turn restrictions (i.e. edge-based), and a profile without them simultaneously, is it possible with one GraphHopper instance and one preparation set, or should I use two different instances & two folders with independent data sets?

1 Like

Yes, this is totally possible, and even intended. You can just add two profiles for the same vehicle, one with and one without turn restrictions.

I’m glad you figured out what you wanted to do. Please also feel free to send a PR if you think the documentation can be improved somewhere.

1 Like

Can’t get it work yet, need more help, sorry
First, I create an EncodingManager
hopper.setEncodingManager(EncodingManager.create(“car|turn_costs=true”));

then I’m trying to set up two profiles
hopper.setProfiles(new Profile(“car1”).setVehicle(“car”).setWeighting(“shortest”).setTurnCosts(false));
hopper.setProfiles(new Profile(“car2”).setVehicle(“car”).setWeighting(“shortest”).setTurnCosts(true));

then preparation (with clean folder, of course)
hopper.getCHPreparationHandler().setCHProfiles(new CHProfile(“car1”));
hopper.getCHPreparationHandler().setCHProfiles(new CHProfile(“car2”));
hopper.importOrLoad();

but if I call hopper.route() with .setProfile(“car1”) it gives me
The requested profile ‘car1’ does not exist.
Available profiles: [car2]]

setProfiles sets the profiles from scratch, so setProfile(... "car2"... overwrites your “car1” profile again. Same with CHProfiles.

1 Like

Oh, silly me :(( Thanks a lot for your patience, now it works ok.

I think a link to this page

from some basic framework/profile pages may be nice?

Glad you got it to work. Sorry I wasn’t able to help more, I was quite restricted and cant be bothered typing code from my phone :frowning:

Here is my implementation for multiple CH profiles;

graphHopper.setProfiles(Arrays.asList(
                    new CustomProfile("couriervan").setCustomModel(new CustomModel(getCourierModel())).setVehicle("car").setTurnCosts(true).putHint("u_turn_costs", 3),
                    new CustomProfile("couriervan2").setCustomModel(new CustomModel(getCourierModel())).setVehicle("car")
                ));
                
                ArrayList<CHProfile> chProfiles = new ArrayList();
                chProfiles.add(new CHProfile("couriervan"));
                chProfiles.add(new CHProfile("couriervan2"));

                graphHopper.getCHPreparationHandler().setCHProfiles(chProfiles);

Where

public static CustomModel getCourierModel(){
        
        CustomModel model = new CustomModel();
        
        model.addToPriority(If("road_class == SERVICE", MULTIPLY, 1.0));
        model.addToPriority(If("road_access == PRIVATE", MULTIPLY, 1.0));
        
        return model;
    }

My request is completed when my user clicks on a point, it works out the path to the next point and displays the distance;

List<String> CURBSIDES = new ArrayList<>(Arrays.asList("left", "left"));
GHRequest shortRequest = new GHRequest().setProfile("couriervan").setCurbsides(CURBSIDES).putHint(Parameters.Routing.FORCE_CURBSIDE, false);
1 Like

Thanks again! You folks really help a lot! However, real-world testing revealed one more problem: sometimes I get points that are on the left side of the one-way street (while I’m applying .setCurbsides(Arrays.asList(“right”, “right”))). Of course, I get Impossible curbside constraint: ‘curbside=right’ at point 0 … To avoid it, I need some pre-check if this curbside is really applicable, is there any nice way to do it except for parsing res.getErrors()?

Oh yes indeed the profiles.md page currently does not mention turn restrictions. I fixed this here: https://github.com/graphhopper/graphhopper/commit/e98be3b800e932654e2e02f55adec6058fd7c610

You can set force_curbside=false in which case GraphHopper will ignore the curbside setting in case it is impossible.

1 Like

And if I need not just to ignore it, but take some special actions in such case, like storing these points for further use with specially equipped cars?..

I’m afraid then your only option is to catch the error response. Or you add your own endpoint that does just the curbside check and returns true/false depending on whether it is possible or not.

Powered by Discourse