Hello,
we are using the GH routing engine as a component in one of our java projects. We are using GraphHopper version 2.3.
In our setup we need routing for Vespas, i.e. essentially small, slow motorcycles. We initially hard-coded these with a custom flag encoder like this:
public class VespaFlagEncoder extends MotorcycleFlagEncoder {
public VespaFlagEncoder() {
super();
// motorcycles are capped at 120 km/h, vespas should be noticeably slower
maxPossibleSpeed = 50;
}
@Override
public String toString() {
return "vespa";
}
}
The hopper is then initialised like this (simplified):
Flagencoder = new VespaFlagEncoder();
String vehicle = "vespa";
EncodingManager em = EncodingManager.create(encoder);
hopper = new GraphHopperOSM().forDesktop();
hopper.setDataReaderFile(osmFile);
hopper.setGraphHopperLocation(ghStorage);
hopper.setEncodingManager(em);
hopper.setProfiles(new Profile(vehicle).setVehicle(vehicle).setWeighting("fastest"));
hopper.getCHPreparationHandler().setCHProfiles(new CHProfile(vehicle));
hopper.setMinNetworkSize(200);
hopper.importOrLoad();
… and queried like this:
GHRequest request = new GHRequest(origin.y, origin.x, dest.y, dest.x);
request.setProfile(vehicle);
request.setAlgorithm(Parameters.Algorithms.ASTAR_BI);
GHResponse response = hopper.route(request);
We currently try to use the new GH config file interface to handle the whole router initialisation to be more flexible and rely less on hard-coding custom vehicles. We successfully managed to parse a config object from the following YAML file:
datareader.file: <PATH-TO-OSM>
graph.location: <CACHE-DIR>
graph.flag_encoders: motorcycle
profiles:
- name: vespa
vehicle: motorcycle
weighting: custom
custom_model_file: vespa_model.yml
profiles_ch:
- profile: vespa
prepare.min_network_size: 200
graph.dataaccess: RAM_STORE
and associated custom vespa_model.yml
:
max_speed:
road_class:
motorway: 0
trunk: 50
primary: 50
secondary: 50
tertiary: 50
max_speed_fallback: 50
Printing the resulting GraphHopperConfig object yields:
profiles:
name=vespa|vehicle=motorcycle|weighting=custom|turnCosts=false|hints={custom_model_file=empty, custom_model=distanceInfluence=70.0|speedFactor={}|maxSpeed={road_class={motorway=0, trunk=50, primary=50, secondary=50, tertiary=50}}|maxSpeedFallback=50.0|priorityMap={}|areas={}}
profiles_ch:
vespa
profiles_lm:
properties:
datareader.file: <PATH-TO-OSM>
graph.location: <CACHE-DIR>
graph.flag_encoders: motorcycle
prepare.min_network_size: 200
graph.dataaccess: RAM_STORE
We can use this to initialise our hopper simply as follows:
hopper = new GraphHopperOSM().forDesktop();
hopper.init(ghConfig);
hopper.importOrLoad();
and query it as before.
Problem: The two hoppers route differently. In particular, if my custom model does not contain the motorway:0 setting, it actually chooses a route which contains a significant portion of road_class motorway, despite the overall speed-cap of 50 km/h (which I don’t want and which the initial VespaFlagEncoder did not do). If on the other hand I set motorway:0, as above, I still get a deviation, this time with a shortcut along a poor surface-quality unhewn cobble street (the blue route corresponds to the VespaFlagEncoder, the red route with the suboptimal short-cut is produced from the custom model as shown above) …
Question: Now that we have most of the relevant context … What is the correct way to control, via GH yaml configs and custom model files, the exact behaviour of the VespaFlagEncoder. In other words: how do I control the maxPossibleSpeed attribute of the encoder through the model configuration? Contrary to the available documentation, the config key max_speed_fallback does not appear to achieve this, I think … or am I missing some other aspect where the two solutions deviate and which could be the cause of the differing routing behaviour …
I am aware that config files are still a beta feature in 2.3 but we would like to refrain from upgrading to 3.0 until there is a proper release.