Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set default vehicle type for HGV profile #1126

Merged
merged 1 commit into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ RELEASING:
- Dockerfile now creates intermediate directories if they are not present ([#1109](https://github.com/GIScience/openrouteservice/issues/1109))
- internal properties of `IsochronesRequest` model not ignored for swagger file generation
- remove non-parameter `metricsStrings` from API documentation ([#756](https://github.com/GIScience/openrouteservice/issues/756))
- set default vehicle type for HGV profile ([#816](https://github.com/GIScience/openrouteservice/issues/816))

## [6.7.0] - 2022-01-04
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@EndPointAnnotation(name = "isochrones")
@VersionAnnotation(version = "v2")
public class ResultTest extends ServiceTest {
private static float REACHFACTOR_REFERENCE_VALUE = 0.0648f;

public ResultTest() {

Expand Down Expand Up @@ -116,9 +117,9 @@ public void testPolygon() {
.then()
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].geometry.coordinates[0].size()", is(88))
.body("features[0].geometry.coordinates[0].size()", is(85))
.body("features[0].properties.center.size()", is(2))
.body("bbox", hasItems(8.652489f, 49.40263f, 8.708881f, 49.447865f))
.body("bbox", hasItems(8.652559f, 49.40263f, 8.708881f, 49.447865f))
.body("features[0].type", is("Feature"))
.body("features[0].geometry.type", is("Polygon"))
.body("features[0].properties.group_index", is(0))
Expand Down Expand Up @@ -187,7 +188,7 @@ public void testBoundingBox() {
.when()
.post(getEndPointPath() + "/{profile}/geojson")
.then()
.body("bbox[0]", is(8.652489f))
.body("bbox[0]", is(8.652559f))
.body("bbox[1]", is(49.40263f))
.body("bbox[2]", is(8.708881f))
.body("bbox[3]", is(49.447865f))
Expand All @@ -213,7 +214,7 @@ public void testReachfactorAndArea() {
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].properties.area", is(both(greaterThan(12000000f)).and(lessThan(13000000f))))
.body("features[0].properties.reachfactor", is(0.0663f))
.body("features[0].properties.reachfactor", is(REACHFACTOR_REFERENCE_VALUE))
.statusCode(200);

}
Expand All @@ -238,7 +239,7 @@ public void testReachfactorAndAreaAreaUnitsM() {
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].properties.area", is(both(greaterThan(12000000f)).and(lessThan(13000000f))))
.body("features[0].properties.reachfactor", is(0.0663f))
.body("features[0].properties.reachfactor", is(REACHFACTOR_REFERENCE_VALUE))
.statusCode(200);

}
Expand All @@ -263,7 +264,7 @@ public void testReachfactorAndAreaAreaUnitsKM() {
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].properties.area", is(both(greaterThan(12.0f)).and(lessThan(13.0f))))
.body("features[0].properties.reachfactor", is(0.0663f))
.body("features[0].properties.reachfactor", is(REACHFACTOR_REFERENCE_VALUE))
.statusCode(200);

}
Expand Down Expand Up @@ -314,7 +315,7 @@ public void testReachfactorAndAreaAreaUnitsMI() {
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].properties.area", is(both(greaterThan(4.7f)).and(lessThan(5.0f))))
.body("features[0].properties.reachfactor", is(0.0663f))
.body("features[0].properties.reachfactor", is(REACHFACTOR_REFERENCE_VALUE))
.statusCode(200);

}
Expand Down Expand Up @@ -345,7 +346,7 @@ public void testIntersections() {
.body("features[1].geometry.type", is("Polygon"))
.body("features[2].type", is("Feature"))
.body("features[2].geometry.type", is("Polygon"))
.body("features[2].geometry.coordinates[0].size()", is(86))
.body("features[2].geometry.coordinates[0].size()", is(80))
.body("features[2].properties.contours.size()", is(2))
.body("features[2].properties.containsKey('area')", is(true))
.body("features[0].properties.area", is(both(greaterThan(12000000f)).and(lessThan(13000000f))))
Expand Down Expand Up @@ -379,7 +380,7 @@ public void testSmoothingFactor() {
.then()
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].geometry.coordinates[0].size", is(75))
.body("features[0].geometry.coordinates[0].size", is(69))
.statusCode(200);

body.put("smoothing", "100");
Expand All @@ -393,7 +394,7 @@ public void testSmoothingFactor() {
.then()
.body("any { it.key == 'type' }", is(true))
.body("any { it.key == 'features' }", is(true))
.body("features[0].geometry.coordinates[0].size", is(89))
.body("features[0].geometry.coordinates[0].size", is(94))
.statusCode(200);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class RouteSearchParameters {
public static final String KEY_AVOID_POLYGONS = "avoid_polygons";
public static final String KEY_ALTERNATIVE_ROUTES_WEIGHT_FACTOR = "alternative_routes_weight_factor";
public static final String KEY_ALTERNATIVE_ROUTES_SHARE_FACTOR = "alternative_routes_share_factor";
public static final int DEFAULT_HGV_VEHICLE_TYPE = HeavyVehicleAttributes.HGV;
private int profileType;
private int weightingMethod = WeightingMethod.FASTEST;
private Boolean considerTurnRestrictions = false;
Expand Down Expand Up @@ -100,6 +101,9 @@ public void setProfileType(int profileType) throws Exception {
throw new Exception("Routing profile is unknown.");

this.profileType = profileType;

if (RoutingProfileType.isHeavyVehicle(profileType))
setVehicleType(DEFAULT_HGV_VEHICLE_TYPE);
}

public int getWeightingMethod() {
Expand Down Expand Up @@ -304,34 +308,34 @@ public void setOptions(String options) throws Exception {

if (json.has("vehicle_type")) {
String type = json.getString("vehicle_type");
this.vehicleType = HeavyVehicleAttributes.getFromString(type);
setVehicleType(HeavyVehicleAttributes.getFromString(type));
}

// Since 4.2, all restrictions are packed in its own element
if (jRestrictions == null)
jRestrictions = jProfileParams;
// Since 4.2, all restrictions are packed in its own element
if (jRestrictions == null)
jRestrictions = jProfileParams;

if (jRestrictions.has("length"))
vehicleParams.setLength(jRestrictions.getDouble("length"));
if (jRestrictions.has("length"))
vehicleParams.setLength(jRestrictions.getDouble("length"));

if (jRestrictions.has("width"))
vehicleParams.setWidth(jRestrictions.getDouble("width"));
if (jRestrictions.has("width"))
vehicleParams.setWidth(jRestrictions.getDouble("width"));

if (jRestrictions.has("height"))
vehicleParams.setHeight(jRestrictions.getDouble("height"));
if (jRestrictions.has("height"))
vehicleParams.setHeight(jRestrictions.getDouble("height"));

if (jRestrictions.has("weight"))
vehicleParams.setWeight(jRestrictions.getDouble("weight"));
if (jRestrictions.has("weight"))
vehicleParams.setWeight(jRestrictions.getDouble("weight"));

if (jRestrictions.has("axleload"))
vehicleParams.setAxleload(jRestrictions.getDouble("axleload"));
if (jRestrictions.has("axleload"))
vehicleParams.setAxleload(jRestrictions.getDouble("axleload"));

int loadCharacteristics = 0;
if (jRestrictions.has("hazmat") && jRestrictions.getBoolean("hazmat"))
loadCharacteristics |= VehicleLoadCharacteristicsFlags.HAZMAT;
int loadCharacteristics = 0;
if (jRestrictions.has("hazmat") && jRestrictions.getBoolean("hazmat"))
loadCharacteristics |= VehicleLoadCharacteristicsFlags.HAZMAT;

if (loadCharacteristics != 0)
vehicleParams.setLoadCharacteristics(loadCharacteristics);
}
if (loadCharacteristics != 0)
vehicleParams.setLoadCharacteristics(loadCharacteristics);

profileParams = vehicleParams;
} else if (profileType == RoutingProfileType.WHEELCHAIR) {
Expand Down Expand Up @@ -572,13 +576,17 @@ public boolean isProfileTypeHeavyVehicle() {
return RoutingProfileType.isHeavyVehicle(this.getProfileType());
}

public boolean hasNonDefaultVehicleType() {
return isProfileTypeHeavyVehicle() && getVehicleType() != DEFAULT_HGV_VEHICLE_TYPE;
}

public boolean requiresDynamicPreprocessedWeights() {
return hasAvoidAreas()
|| hasAvoidFeatures()
|| hasAvoidBorders()
|| hasAvoidCountries()
|| getConsiderTurnRestrictions()
|| isProfileTypeHeavyVehicle() && getVehicleType() > 0
|| hasNonDefaultVehicleType()
|| isProfileTypeDriving() && hasParameters(VehicleParameters.class)
|| hasMaximumSpeed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import org.geotools.feature.SchemaException;
import org.heigit.ors.api.requests.routing.RouteRequest;
import org.heigit.ors.common.TravelRangeType;
import org.heigit.ors.fastisochrones.Contour;
Expand All @@ -62,14 +61,16 @@
import org.heigit.ors.routing.graphhopper.extensions.core.PrepareCore;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.AvoidFeaturesEdgeFilter;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.EdgeFilterSequence;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.HeavyVehicleEdgeFilter;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.TrafficEdgeFilter;
import org.heigit.ors.routing.graphhopper.extensions.flagencoders.FlagEncoderNames;
import org.heigit.ors.routing.graphhopper.extensions.storages.BordersGraphStorage;
import org.heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils;
import org.heigit.ors.routing.graphhopper.extensions.storages.HeavyVehicleAttributesGraphStorage;
import org.heigit.ors.routing.graphhopper.extensions.storages.TrafficGraphStorage;
import org.heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder;
import org.heigit.ors.routing.graphhopper.extensions.storages.builders.HereTrafficGraphStorageBuilder;
import org.heigit.ors.routing.graphhopper.extensions.util.ORSPMap;
import org.heigit.ors.routing.graphhopper.extensions.util.ORSParameters;
import org.heigit.ors.routing.graphhopper.extensions.weighting.HgvAccessWeighting;
import org.heigit.ors.routing.graphhopper.extensions.weighting.MaximumSpeedCalculator;
import org.heigit.ors.routing.pathprocessors.BordersExtractor;
import org.heigit.ors.util.CoordTools;
Expand All @@ -82,6 +83,8 @@
import java.util.*;
import java.util.concurrent.locks.Lock;

import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.EDGE_OR_NODE;
import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.OFF;
import static com.graphhopper.routing.weighting.TurnWeighting.INFINITE_U_TURN_COSTS;
import static com.graphhopper.util.Parameters.Algorithms.*;
import static org.heigit.ors.routing.RouteResult.KEY_TIMEZONE_ARRIVAL;
Expand Down Expand Up @@ -612,6 +615,44 @@ public void initLMAlgoFactoryDecorator() {
ORSWeightingFactory.addTrafficSpeedCalculator(getLMFactoryDecorator().getWeightings(), getGraphHopperStorage());
}

@Override
public void initCHAlgoFactoryDecorator() {
CHAlgoFactoryDecorator chFactoryDecorator = getCHFactoryDecorator();
EncodingManager encodingManager = getEncodingManager();
if (!chFactoryDecorator.hasCHProfiles()) {
for (FlagEncoder encoder : encodingManager.fetchEdgeEncoders()) {
for (String chWeightingStr : chFactoryDecorator.getCHProfileStrings()) {
// ghStorage is null at this point

// extract weighting string and u-turn-costs
String configStr = "";
if (chWeightingStr.contains("|")) {
configStr = chWeightingStr;
chWeightingStr = chWeightingStr.split("\\|")[0];
}
PMap config = new PMap(configStr);
int uTurnCosts = config.getInt(Parameters.Routing.U_TURN_COSTS, INFINITE_U_TURN_COSTS);

Weighting weighting = createWeighting(new HintsMap(chWeightingStr), encoder, null);
if (encoder.toString().equals(FlagEncoderNames.HEAVYVEHICLE) && graphStorageFactory instanceof ORSGraphStorageFactory) {
ORSGraphStorageFactory orsGraphStorageFactory = (ORSGraphStorageFactory) graphStorageFactory;
HeavyVehicleAttributesGraphStorage hgvStorage = GraphStorageUtils.getGraphExtension(orsGraphStorageFactory.getGraphExtension(), HeavyVehicleAttributesGraphStorage.class);
EdgeFilter hgvEdgeFilter = new HeavyVehicleEdgeFilter(HeavyVehicleAttributes.HGV, null, hgvStorage);
weighting = new HgvAccessWeighting(weighting, hgvEdgeFilter);
}

CHAlgoFactoryDecorator.EdgeBasedCHMode edgeBasedCHMode = chFactoryDecorator.getEdgeBasedCHMode();
if (!(edgeBasedCHMode == EDGE_OR_NODE && encoder.supports(TurnWeighting.class))) {
chFactoryDecorator.addCHProfile(CHProfile.nodeBased(weighting));
}
if (edgeBasedCHMode != OFF && encoder.supports(TurnWeighting.class)) {
chFactoryDecorator.addCHProfile(CHProfile.edgeBased(weighting, uTurnCosts));
}
}
}
}
}

/**
* Does the preparation and creates the location index as well as the traffic graph storage
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class ORSGraphStorageFactory implements GraphStorageFactory {

private final List<GraphStorageBuilder> graphStorageBuilders;

private GraphExtension graphExtension = null;

public ORSGraphStorageFactory(List<GraphStorageBuilder> graphStorageBuilders) {
this.graphStorageBuilders = graphStorageBuilders;
}
Expand Down Expand Up @@ -65,8 +67,6 @@ public GraphHopperStorage createStorage(GHDirectory dir, GraphHopper gh) {
}
}

GraphExtension graphExtension = null;

if (geTurnCosts == null && graphExtensions.isEmpty())
graphExtension = new GraphExtension.NoOpExtension();
else if (geTurnCosts != null && !graphExtensions.isEmpty()) {
Expand Down Expand Up @@ -127,4 +127,8 @@ private boolean hasGraph(GraphHopper gh) {
}
return false;
}

public GraphExtension getGraphExtension() {
return graphExtension;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ public IntObjectMap<SPTEntry> getMap()
private static final int MODE_ROUTE = 0;

public HeavyVehicleEdgeFilter(int vehicleType, VehicleParameters vehicleParams, GraphStorage graphStorage) {
this(vehicleType, vehicleParams, GraphStorageUtils.getGraphExtension(graphStorage, HeavyVehicleAttributesGraphStorage.class));
}

public HeavyVehicleEdgeFilter(int vehicleType, VehicleParameters vehicleParams, HeavyVehicleAttributesGraphStorage hgvStorage) {
float[] vehicleAttrs = new float[VehicleDimensionRestrictions.COUNT];

if (vehicleParams!=null) {
Expand Down Expand Up @@ -100,7 +104,7 @@ public HeavyVehicleEdgeFilter(int vehicleType, VehicleParameters vehicleParams,
this.vehicleType = vehicleType;
this.buffer = new byte[2];

this.gsHeavyVehicles = GraphStorageUtils.getGraphExtension(graphStorage, HeavyVehicleAttributesGraphStorage.class);
this.gsHeavyVehicles = hgvStorage;
}

public void setDestinationEdge(EdgeIteratorState edge, Graph graph, FlagEncoder encoder, TraversalMode tMode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,24 @@ public static <T extends GraphExtension> T getGraphExtension(GraphStorage graphS
if (graphStorage instanceof GraphHopperStorage) {
GraphHopperStorage ghs = (GraphHopperStorage) graphStorage;
GraphExtension ge = ghs.getExtension();
return getGraphExtension(ge, type);
}
return null;
}

if(ge instanceof ExtendedStorageSequence) {
ExtendedStorageSequence ess = (ExtendedStorageSequence)ge;
GraphExtension[] exts = ess.getExtensions();
for (int i = 0; i < exts.length; i++) {
if (type.isInstance(exts[i])) {
return (T)exts[i];
}
}
} else {
if (type.isInstance(ge)) {
return (T)ge;
public static <T extends GraphExtension> T getGraphExtension(GraphExtension ge, Class<T> type) {
if (ge instanceof ExtendedStorageSequence) {
ExtendedStorageSequence ess = (ExtendedStorageSequence)ge;
GraphExtension[] exts = ess.getExtensions();
for (int i = 0; i < exts.length; i++) {
if (type.isInstance(exts[i])) {
return (T)exts[i];
}
}
} else {
if (type.isInstance(ge)) {
return (T)ge;
}
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.heigit.ors.routing.graphhopper.extensions.weighting;

import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.weighting.AbstractAdjustedWeighting;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.util.EdgeIteratorState;

public class HgvAccessWeighting extends AbstractAdjustedWeighting {
EdgeFilter hgvAccessFilter;

public HgvAccessWeighting(Weighting superWeighting, EdgeFilter hgvAccessFilter) {
super(superWeighting);
this.hgvAccessFilter = hgvAccessFilter;
}

@Override
public double calcWeight(EdgeIteratorState edge, boolean reverse, int prevOrNextEdgeId, long time) {
if (!hgvAccessFilter.accept(edge))
return Double.POSITIVE_INFINITY;
return superWeighting.calcWeight(edge, reverse, prevOrNextEdgeId, time);
}

@Override
public String toString() {
return "hgv_access|" + this.superWeighting.toString();
}

public String getName() {
return this.superWeighting.getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,9 @@ public void requiresDynamicPreprocessedWeights() throws Exception {

routeSearchParameters = new RouteSearchParameters();
routeSearchParameters.setProfileType(RoutingProfileType.DRIVING_HGV);
routeSearchParameters.setVehicleType(HeavyVehicleAttributes.HGV);
Assert.assertTrue("heavy vehicle", routeSearchParameters.requiresDynamicPreprocessedWeights());
Assert.assertFalse("default vehicle type", routeSearchParameters.requiresDynamicPreprocessedWeights());
routeSearchParameters.setVehicleType(HeavyVehicleAttributes.BUS);
Assert.assertTrue("non-default vehicle type", routeSearchParameters.requiresDynamicPreprocessedWeights());

routeSearchParameters = new RouteSearchParameters();
routeSearchParameters.setProfileType(RoutingProfileType.DRIVING_HGV);
Expand Down