Avoiding road classes and environments

Hello! I’m trying to calculate shortest path for different vehicle types but avoiding some road classes and environments (eg motorways, toll roads, etc). I’m running an instance of GH locally but the API doesn’t seem to actually avoid the different keywords I’m passing. I saw on a different thread that this feature is only available in the commercial version (but that comment was quite old). Could anyone confirm if that is still the case?

On a related issue, is it possible to avoid road classes and environments when calculating isodistances? I couldn’t find this option when checking the docs. If this is not possible, I’m assuming the only solution to calculate isodistances whilst avoiding motorways, tolls, etc is to write my own version of it using the routing API?

Many thanks! Diego

Hiya, using Graphhopper V1.0

Try the following to exclude road classes;

        // Exclude footways, stairs  from profile
        CustomModel model = new CustomModel();
        HashMap map = new HashMap();
        map.put("footway", 0);
        map.put("steps", 0);
        map.put("service", 1.0);
        model.getPriority().put("road_class", map);

Then as you set the profiles;

graphHopper = new GraphHopperOSM().setGraphHopperLocation(locationGrapphopperFiles)
...........................
...........................
.setProfiles(Arrays.asList(
                    new Profile("foot").setVehicle("foot").setWeighting("fastest"),
                    new Profile("bike").setVehicle("bike").setWeighting("fastest"),
                    new Profile("bike2").setVehicle("bike2").setWeighting("fastest"),
                    new Profile("car").setVehicle("car").setWeighting("fastest"),
                    new CustomProfile("name_of_your_profile").setCustomModel(model).setVehicle("foot").setWeighting("custom")))

So the footway is set to 0 which disables it and service 1.0 to enable it.

To enable private access for private roads;
EncodingManager encodingManager = EncodingManager.create(FlagEncoderFactory.FOOT + "|block_private=false,

Ask any other questions you have.

Hi @Gregws! Thank you very much for your answer. Have it working now… apart from avoiding toll roads. Can’t see tolls being any under a custom model (and I believe the example yml in the repo have toll inside “priority” but that doesn’t seem to be correct…) Many thanks!!

Glad you have it working.
I haven’t experimented with toll roads sorry as there are only 3 in my country.

Tolls are identified as tags. https://wiki.openstreetmap.org/wiki/Key:toll

Add into priority;
toll:
no: 1

HashMap tollHashMap = new HashMap();
tollHashMap.put("no", 1);

model.getPriority().put("toll", tollHashMap);

Please note that I haven’t tested it, unsure if you have to add “*”: 0.1 as the documentation shows

Examples;
Not avoiding tolls

Avoiding toll roads
image

Note that “no: 0” results in weird results

1 Like

Hi again @Gregws! Thank you very much for taking the time to reply! Unfortunately, I’ve already tried what you suggested but it doesn’t like it Error: Cannot find encoded value 'toll' specified in 'priority'. Available: roundabout,road_class,road_class_link,road_environment,max_speed,road_access I read through the code in the repo and I can’t quite see any reference to tolls in the custom models so wondering if that’s not really possible.

I’m able to replicate the behaviour you are describing using flex and the maps service, but I’m trying to do everything programmatically against the Routing API (as I need to calculate shortest distance for a large number of locations, but also using some customisation like no tolls, no motorways, etc). Not very successfully so far unfortunately (and using &avoid=toll in the request doesn’t seem to do the trick. Would you happen to know if I could use flex programmatically against Routing API?

Many, many thanks again!

It seemed logical since its under priority in flex!
Just a guess but try road_environment instead of toll, and set to 0.

tollHashMap.put(“toll”, 0);

model.getPriority().put(“road_enviroment”, tollHashMap);

Indicated on an earlier version blog post, perhaps it hasn’t changed?

On my phone so can’t test, can do more tests tomorrow

1 Like

Sadly I also tried that but it didn’t like it either Error: Cannot find enum toll in [other, road, ferry, tunnel, bridge, ford, shuttle_train] Reading through the code, tolls don’t seem to be in any of the custom profiles so might not be possible :frowning: Thanks for your very kind help @Gregws!!

Might have to add it in there yourself.

I’ll have a play tomorrow as I wouldn’t mind learning how myself

1 Like

You add toll to the graph.encoded_values in the config.yml (reimport required after that!) and then you can use it how @Gregws said in the first post via toll: no (without road_environment)

1 Like

Thank you so much for all the help, really appreciate it!! I’m almost there I believe. Now, I’m trying to write some tests to double check the paths I’m getting are correct. I’m not spinning the API, just querying the JAR and I would like to get the details of the path (e.g road class, road environment, etc). I’ve got here

GraphHopper hopper = new GraphHopperOSM().forServer();
hopper.setDataReaderFile(osmFile);
hopper.init(new GraphHopperConfig().putObject("graph.encoded_values", "road_class,road_class_link,road_environment,max_speed,road_access,toll"));
hopper.setGraphHopperLocation(graphFolder);
hopper.setEncodingManager(EncodingManager.create("car"));

hopper.setProfiles(new Profile("car").setVehicle("car").setWeighting("shortest"));
hopper.importOrLoad();

GHRequest req = new GHRequest(latFrom, lonFrom, latTo, lonTo).setProfile(profile);
GHResponse rsp = hopper.route(req);
ResponsePath path = rsp.getBest();

But the path details (the place I was assuming I would find all those details) seems empty in both GHRequest and ResponsePath. Am I missing something in the config to get those bits populated?

Thanks so much again!!

You need to specify this in the request (like details=road_class), see the docs.

Yep, the API is fine, just found out how to do it using Java

GHRequest req = new GHRequest(latFrom, lonFrom, latTo, lonTo)
    .setProfile(profile)
    .setPathDetails(Arrays.asList("road_class", "road_environment"));

The bit I’m struggling to get working in Java (fine when querying the API) is to get details about toll roads. I thought this would do but it doesn’t like it :frowning:

GraphHopper hopper = new GraphHopperOSM().forServer();
        hopper.setDataReaderFile(osmFile);
        hopper.init(new GraphHopperConfig().putObject("graph.encoded_values", "road_class, ...,toll"));
// then
GHRequest req = new GHRequest(latFrom, lonFrom, latTo, lonTo)
                    .setProfile(profile)
                    .setPathDetails(Arrays.asList("road_class", "road_environment", "toll"));

Getting You requested the details [road_class, road_environment, toll] but we could only find [road_class, road_environment] so I’m assuming the way I do GraphHopperConfig()... is not quite correct. Any clue why that might not be working? Thanks so much!

This looks ok. Did you call hopper.importOrLoad() after hopper.init? and removed the graph-cache folder so that it applies the new config?

PS: in general it is better to create a new topic for a new question

It’s working now! I was stupidly overwriting the EncodingManager so killing the config. Just in case anyone might find this useful, I’m attaching a small snippet of code;

import com.graphhopper.*;
import com.graphhopper.config.Profile;
import com.graphhopper.reader.osm.GraphHopperOSM;
import com.graphhopper.util.details.PathDetail;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/*
    README
    wget https://oss.sonatype.org/content/groups/public/com/graphhopper/graphhopper-web/1.0/graphhopper-web-1.0.jar
    wget http://download.geofabrik.de/europe/berlin-latest.osm.pbf
    javac -cp graphhopper-web-1.0.jar TollTest.java
    java -cp ".:graphhopper-web-1.0.jar" TollTest
 */


public class TollTest {

    public static void main(String[] args) throws IOException {

        String osmFile = "berlin-latest.osm.pbf";
        String graphFolder = "berlin-graph";

        GraphHopper hopper = new GraphHopperOSM().forServer();
        hopper.setDataReaderFile(osmFile);
        hopper.init(new GraphHopperConfig().putObject("graph.flag_encoders", "car").putObject("graph.encoded_values", "road_class,road_environment,toll"));
        hopper.setGraphHopperLocation(graphFolder);
        hopper.setProfiles(new Profile("car").setVehicle("car").setWeighting("shortest"));
        hopper.importOrLoad();

        GHRequest request = new GHRequest(52.5373, 13.3603, 52.4983, 13.4066)
            .setProfile("car").setPathDetails(Arrays.asList("road_class", "road_environment", "toll"));
        GHResponse response = hopper.route(request);
        ResponsePath path = response.getBest();
        Map<String, List<PathDetail>> path_details = path.getPathDetails();

    }

}

PS: You are very right @karussell, I should have opened a new topic. Apologies! Thank you all so, so much for your kind help!!

1 Like

Awesome @diego-peteiro and thanks for sharing your working solution, it’s great to get more working examples for Java implementation!

1 Like

If you like you can contribute improvements for our Java code examples. E.g. for customizable routing we have them here:

They are linked e.g. from our documentation:

Happy to give it a try if that helps people. Also, haven’t done Java in a while so my code might need many, many code reviews :smile: Thanks again for your help!!

Powered by Discourse