Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Releasing is documented in RELEASE.md
### Added

### Changed
- improve road bike average speeds to be faster on cycleways but slower on bad road surface or certain road types such as footways ([#2076](https://github.com/GIScience/openrouteservice/pull/2076))

### Deprecated

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,7 @@ public abstract class CommonBikeFlagEncoder extends BikeCommonFlagEncoder {
private static final boolean DEBUG_OUTPUT = false;
FileWriter logWriter;

// MARQ24 MOD START
// MARQ24 ADDON in the case of the RoadBike Encoder we want to skip some
// conditions...
private final boolean isRoadBikeEncoder = this instanceof RoadBikeFlagEncoder; // TODO: design: parent class should not need to know of child
protected static final Logger LOGGER = Logger.getLogger(CommonBikeFlagEncoder.class.getName());
// MARQ24 MOD END

// MARQ24 MOD START
protected CommonBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts) {
Expand Down Expand Up @@ -415,7 +410,7 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.A
if (!access.isFerry()) {
wayTypeSpeed = applyMaxSpeed(way, wayTypeSpeed);
handleSpeed(edgeFlags, way, wayTypeSpeed);
handleBikeRelated(edgeFlags, way, priorityFromRelation > UNCHANGED.getValue());
handleBikeRelated(edgeFlags, way, isPartOfCycleRelation(priorityFromRelation));
if (access.isConditional() && conditionalAccessEncoder != null)
conditionalAccessEncoder.setBool(false, edgeFlags, true);
boolean isRoundabout = way.hasTag(KEY_JUNCTION, "roundabout") || way.hasTag(KEY_JUNCTION, "circular");
Expand All @@ -440,6 +435,10 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.A
return edgeFlags;
}

protected boolean isPartOfCycleRelation(int priorityFromRelation) {
return priorityFromRelation > UNCHANGED.getValue();
}

int getSpeed(ReaderWay way) {
int speed = Integer.MIN_VALUE;
String highwayTag = way.getTag(KEY_HIGHWAY);
Expand Down Expand Up @@ -639,28 +638,7 @@ private PriorityCode convertClassValueToPriority(String tagvalue) {
void collect(ReaderWay way, double wayTypeSpeed, TreeMap<Double, Integer> weightToPrioMap) {
String service = way.getTag(KEY_SERVICE);
String highway = way.getTag(KEY_HIGHWAY);
// MARQ24 MOD START
if (!isRoadBikeEncoder) {
// MARQ24 MOD END
// MARQ24 MOD START
if (way.hasTag(KEY_BICYCLE, KEY_DESIGNATED) || way.hasTag(KEY_BICYCLE, KEY_OFFICIAL) || way.hasTag(KEY_BICYCLE_ROAD, "yes")) {
// MARQ24 MOD END
if ("path".equals(highway)) {
weightToPrioMap.put(100d, VERY_NICE.getValue());
} else {
weightToPrioMap.put(100d, PREFER.getValue());
}
}
if (KEY_CYCLEWAY.equals(highway)) {
if (way.hasTag("foot", intendedValues) && !way.hasTag(KEY_SEGREGATED, "yes")) {
weightToPrioMap.put(100d, PREFER.getValue());
} else {
weightToPrioMap.put(100d, VERY_NICE.getValue());
}
}
// MARQ24 MOD START
}
// MARQ24 MOD END
handleDesignatedCyclingPriority(way, weightToPrioMap, highway);

double maxSpeed = getMaxSpeed(way);
if (preferHighwayTags.contains(highway) || this.isValidSpeed(maxSpeed) && maxSpeed <= 30) {
Expand All @@ -679,27 +657,7 @@ void collect(ReaderWay way, double wayTypeSpeed, TreeMap<Double, Integer> weight

if (pushingSectionsHighways.contains(highway)
|| "parking_aisle".equals(service)) {
int pushingSectionPrio = AVOID_IF_POSSIBLE.getValue();
// MARQ24 MOD START
if (!isRoadBikeEncoder) {
// MARQ24 MOD END
if (way.hasTag(KEY_BICYCLE, "use_sidepath") || way.hasTag(KEY_BICYCLE, "yes") || way.hasTag(KEY_BICYCLE, "permissive")) {
pushingSectionPrio = PREFER.getValue();
}
if (way.hasTag(KEY_BICYCLE, KEY_DESIGNATED) || way.hasTag(KEY_BICYCLE, KEY_OFFICIAL)) {
pushingSectionPrio = VERY_NICE.getValue();
}
// MARQ24 MOD START
}
// MARQ24 MOD END

if (way.hasTag("foot", "yes")) {
pushingSectionPrio = Math.max(pushingSectionPrio - 1, WORST.getValue());
if (!isRoadBikeEncoder && way.hasTag(KEY_SEGREGATED, "yes")) {
pushingSectionPrio = Math.min(pushingSectionPrio + 1, BEST.getValue());
}
}
weightToPrioMap.put(100d, pushingSectionPrio);
handlePushingSectionPriority(way, weightToPrioMap);
}

if (way.hasTag(KEY_RAILWAY, "tram")) {
Expand All @@ -724,6 +682,40 @@ void collect(ReaderWay way, double wayTypeSpeed, TreeMap<Double, Integer> weight
}
}

protected void handlePushingSectionPriority(ReaderWay way, TreeMap<Double, Integer> weightToPrioMap) {
int pushingSectionPrio = AVOID_IF_POSSIBLE.getValue();
if (way.hasTag(KEY_BICYCLE, "use_sidepath") || way.hasTag(KEY_BICYCLE, "yes") || way.hasTag(KEY_BICYCLE, "permissive")) {
pushingSectionPrio = PREFER.getValue();
}
if (way.hasTag(KEY_BICYCLE, KEY_DESIGNATED) || way.hasTag(KEY_BICYCLE, KEY_OFFICIAL)) {
pushingSectionPrio = VERY_NICE.getValue();
}
if (way.hasTag("foot", "yes")) {
pushingSectionPrio = Math.max(pushingSectionPrio - 1, WORST.getValue());
if (way.hasTag(KEY_SEGREGATED, "yes")) {
pushingSectionPrio = Math.min(pushingSectionPrio + 1, BEST.getValue());
}
}
weightToPrioMap.put(100d, pushingSectionPrio);
}

protected void handleDesignatedCyclingPriority(ReaderWay way, TreeMap<Double, Integer> weightToPrioMap, String highway) {
if (way.hasTag(KEY_BICYCLE, KEY_DESIGNATED) || way.hasTag(KEY_BICYCLE, KEY_OFFICIAL) || way.hasTag(KEY_BICYCLE_ROAD, "yes")) {
if ("path".equals(highway)) {
weightToPrioMap.put(100d, VERY_NICE.getValue());
} else {
weightToPrioMap.put(100d, PREFER.getValue());
}
}
if (KEY_CYCLEWAY.equals(highway)) {
if (way.hasTag("foot", intendedValues) && !way.hasTag(KEY_SEGREGATED, "yes")) {
weightToPrioMap.put(100d, PREFER.getValue());
} else {
weightToPrioMap.put(100d, VERY_NICE.getValue());
}
}
}

/**
* Handle surface and wayType encoding
*/
Expand Down Expand Up @@ -751,7 +743,7 @@ void handleBikeRelated(IntsRef edgeFlags, ReaderWay way, boolean partOfCycleRela
wayType = WayType.PUSHING_SECTION;
} else {
// boost "none identified" partOfCycleRelation
if (!isRoadBikeEncoder && partOfCycleRelation) {
if (partOfCycleRelation) {
wayType = WayType.CYCLEWAY;
}

Expand Down Expand Up @@ -821,6 +813,10 @@ protected void setSurfaceSpeed(String surface, int speed) {
surfaceSpeeds.put(surface, new SpeedValue(speed));
}

protected void setSurfaceSpeed(String surface, int speed, UpdateType type) {
surfaceSpeeds.put(surface, new SpeedValue(speed, type));
}

protected void setSurfaceSpeed(String surface, SpeedValue speed) {
surfaceSpeeds.put(surface, speed);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import java.util.TreeMap;

import static com.graphhopper.routing.ev.RouteNetwork.LOCAL;
import static org.heigit.ors.routing.graphhopper.extensions.util.PriorityCode.*;

/**
Expand All @@ -35,6 +34,7 @@
*/
public class RoadBikeFlagEncoder extends CommonBikeFlagEncoder {
private static final int MEAN_SPEED = 25;
protected static final int PAVED_WAY_SPEED = 20;
public static final String VAL_SECONDARY = "secondary";
public static final String VAL_SECONDARY_LINK = "secondary_link";
public static final String VAL_TERTIARY = "tertiary";
Expand All @@ -45,6 +45,7 @@ public class RoadBikeFlagEncoder extends CommonBikeFlagEncoder {
public static final String VAL_SERVICE = "service";
public static final String VAL_UNCLASSIFIED = "unclassified";
public static final String VAL_HIGHWAY = "highway";
public static final String VAL_ROAD = "road";

public RoadBikeFlagEncoder() {
// MARQ24 MOD START
Expand Down Expand Up @@ -75,29 +76,30 @@ public RoadBikeFlagEncoder(String propertiesStr) {
public RoadBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts, boolean considerElevation) {
super(speedBits, speedFactor, maxTurnCosts, considerElevation);
// MARQ24 MOD END
preferHighwayTags.add("road");
preferHighwayTags.add(VAL_ROAD);
preferHighwayTags.add(VAL_SECONDARY);
preferHighwayTags.add(VAL_SECONDARY_LINK);
preferHighwayTags.add(VAL_TERTIARY);
preferHighwayTags.add(VAL_TERTIARY_LINK);
preferHighwayTags.add(VAL_RESIDENTIAL);
preferHighwayTags.add(VAL_UNCLASSIFIED);

setTrackTypeSpeed(VAL_GRADE_1, 20); // paved
setTrackTypeSpeed(VAL_GRADE_1, PAVED_WAY_SPEED); // paved
setTrackTypeSpeed("grade2", 10); // now unpaved ...
setTrackTypeSpeed("grade3", PUSHING_SECTION_SPEED);
setTrackTypeSpeed("grade4", PUSHING_SECTION_SPEED);
setTrackTypeSpeed("grade5", PUSHING_SECTION_SPEED);

setSurfaceSpeed("paved", 20);
setSurfaceSpeed("asphalt", 20);
setSurfaceSpeed("cobblestone", 10);
setSurfaceSpeed("cobblestone:flattened", 10);
setSurfaceSpeed("sett", 10);
setSurfaceSpeed("concrete", 20);
setSurfaceSpeed("concrete:lanes", 16);
setSurfaceSpeed("concrete:plates", 16);
setSurfaceSpeed("paving_stones", 10);
setSurfaceSpeed("paving_stones:30", 10);
setSurfaceSpeed("paved", PAVED_WAY_SPEED, UpdateType.UPGRADE_ONLY);
setSurfaceSpeed("asphalt", PAVED_WAY_SPEED, UpdateType.UPGRADE_ONLY);
setSurfaceSpeed("concrete", PAVED_WAY_SPEED, UpdateType.UPGRADE_ONLY);

setSurfaceSpeed("cobblestone", 10, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("cobblestone:flattened", 10, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("sett", 10, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("concrete:lanes", 16, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("concrete:plates", 16, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("paving_stones", 12, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("paving_stones:30", 12, UpdateType.DOWNGRADE_ONLY);
setSurfaceSpeed("unpaved", PUSHING_SECTION_SPEED / 2);
setSurfaceSpeed("compacted", PUSHING_SECTION_SPEED / 2);
setSurfaceSpeed("dirt", PUSHING_SECTION_SPEED / 2);
Expand All @@ -115,88 +117,36 @@ public RoadBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts,
setSurfaceSpeed("sand", PUSHING_SECTION_SPEED / 2);
setSurfaceSpeed("wood", PUSHING_SECTION_SPEED / 2);

setHighwaySpeed("cycleway", 18);
setHighwaySpeed(KEY_CYCLEWAY, new SpeedValue(18, UpdateType.DOWNGRADE_ONLY));
setHighwaySpeed("living_street", 10);
setHighwaySpeed("path", 8);
setHighwaySpeed("footway", 6);
setHighwaySpeed("pedestrian", 6);
setHighwaySpeed("road", 12);
setHighwaySpeed(VAL_ROAD, PAVED_WAY_SPEED);
setHighwaySpeed(VAL_TRACK, PUSHING_SECTION_SPEED / 2); // assume unpaved
setHighwaySpeed(VAL_SERVICE, 12);
setHighwaySpeed(VAL_UNCLASSIFIED, 16);
setHighwaySpeed(VAL_RESIDENTIAL, 16);
setHighwaySpeed(VAL_UNCLASSIFIED, PAVED_WAY_SPEED);
setHighwaySpeed(VAL_RESIDENTIAL, new SpeedValue(18, UpdateType.DOWNGRADE_ONLY));

setHighwaySpeed("trunk", 20);
setHighwaySpeed("trunk_link", 20);
setHighwaySpeed("primary", 20);
setHighwaySpeed("primary_link", 20);
setHighwaySpeed(VAL_SECONDARY, 20);
setHighwaySpeed(VAL_SECONDARY_LINK, 20);
setHighwaySpeed(VAL_TERTIARY, 20);
setHighwaySpeed(VAL_TERTIARY_LINK, 20);
setHighwaySpeed("primary", 22);
setHighwaySpeed("primary_link", 22);
setHighwaySpeed(VAL_SECONDARY, 24);
setHighwaySpeed(VAL_SECONDARY_LINK, 24);
setHighwaySpeed(VAL_TERTIARY, 26);
setHighwaySpeed(VAL_TERTIARY_LINK, 26);

addPushingSection("path");
addPushingSection("footway");
addPushingSection("pedestrian");
addPushingSection("steps");
addPushingSection(KEY_BRIDLEWAY);

routeMap.put(LOCAL, UNCHANGED.getValue());

blockByDefaultBarriers.add("kissing_gate");

setAvoidSpeedLimit(81);
setSpecificClassBicycle("roadcycling");

// MARQ24 MOD START
//**********************************************************************
// REQUIRED ADDON OR OVERWRITE OF Default GH-RoadBikeProfile
// created by MARQ24
//**********************************************************************
preferHighwayTags.remove(VAL_RESIDENTIAL);
preferHighwayTags.add(VAL_UNCLASSIFIED);

// adjusted speeds...
setHighwaySpeed("trunk", 20);
setHighwaySpeed("trunk_link", 20);
setHighwaySpeed("primary", 22);
setHighwaySpeed("primary_link", 22);
setHighwaySpeed(VAL_SECONDARY, 24);
setHighwaySpeed(VAL_SECONDARY_LINK, 24);
setHighwaySpeed(VAL_TERTIARY, 26);
setHighwaySpeed(VAL_TERTIARY_LINK, 26);
setHighwaySpeed("road", 20);
setHighwaySpeed(VAL_UNCLASSIFIED, 20);
setHighwaySpeed(VAL_RESIDENTIAL, new SpeedValue(18, UpdateType.DOWNGRADE_ONLY));

// make sure that we will avoid 'cycleway' & 'service' ways where ever
// it is possible...
setHighwaySpeed("cycleway", new SpeedValue(8, UpdateType.DOWNGRADE_ONLY));
setHighwaySpeed(VAL_SERVICE, new SpeedValue(8, UpdateType.DOWNGRADE_ONLY));

// overwriting also the SurfaceSpeeds... to the "max" of the residential speed
setSurfaceSpeed("paved", new SpeedValue(18, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("asphalt", new SpeedValue(18, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("concrete", new SpeedValue(18, UpdateType.UPGRADE_ONLY));

setSurfaceSpeed("concrete:lanes", new SpeedValue(16, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("concrete:plates", new SpeedValue(16, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("paving_stones", new SpeedValue(10, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("paving_stones:30", new SpeedValue(10, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("cobblestone", new SpeedValue(10, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("cobblestone:flattened", new SpeedValue(10, UpdateType.UPGRADE_ONLY));
setSurfaceSpeed("sett", new SpeedValue(10, UpdateType.UPGRADE_ONLY));

// overwriting also the trackTypeSpeeds... to the "max" of the residential speed
setTrackTypeSpeed(VAL_GRADE_1, new SpeedValue(18, UpdateType.UPGRADE_ONLY));
setTrackTypeSpeed("grade2", new SpeedValue(10, UpdateType.UPGRADE_ONLY));

// HSW - asphalt cycleway vs asphalt roundabout
// http://localhost:3035/directions?n1=51.965101&n2=8.24595&n3=18&a=51.965555,8.243968,51.964878,8.245057&b=1c&c=0&g1=-1&g2=0&h2=3&k1=en-US&k2=km

// Aschloh roundabout vs cycleway (cycle relation) & service shortcut
// http://localhost:3035/directions?n1=52.064701&n2=8.386386&n3=19&a=52.065407,8.386171,52.064821,8.386833&b=1c&c=0&g1=-1&g2=0&h2=3&k1=en-US&k2=km
LOGGER.info("NextGen RoadBike FlagEncoder is active...");
// MARQ24 MOD END
}

public double getMeanSpeed() {
Expand All @@ -217,6 +167,8 @@ void collect(ReaderWay way, double wayTypeSpeed, TreeMap<Double, Integer> weight
} else if (trackType == null || trackType.startsWith("grade")) {
weightToPrioMap.put(110d, AVOID_AT_ALL_COSTS.getValue());
}
} else if (way.hasTag("foot", intendedValues)) {
weightToPrioMap.put(110d, AVOID_IF_POSSIBLE.getValue());
}
}

Expand Down Expand Up @@ -245,4 +197,24 @@ public String toString() {
protected double getDownhillMaxSpeed() {
return 60;
}

@Override
protected void handlePushingSectionPriority(ReaderWay way, TreeMap<Double, Integer> weightToPrioMap) {
int pushingSectionPrio = AVOID_IF_POSSIBLE.getValue();
if (way.hasTag("foot", "yes")) {
pushingSectionPrio = Math.max(pushingSectionPrio - 1, WORST.getValue());
}
weightToPrioMap.put(100d, pushingSectionPrio);
}

@Override
protected void handleDesignatedCyclingPriority(ReaderWay way, TreeMap<Double, Integer> weightToPrioMap, String highway) {
// do nothing
}

@Override
protected boolean isPartOfCycleRelation(int priorityFromRelation) {
return false;
}

}
Loading