com.graphhopper.routing.util.parsers.BikeCommonAverageSpeedParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of graphhopper-core Show documentation
Show all versions of graphhopper-core Show documentation
GraphHopper is a fast and memory efficient Java road routing engine
working seamlessly with OpenStreetMap data.
package com.graphhopper.routing.util.parsers;
import com.graphhopper.reader.ReaderWay;
import com.graphhopper.routing.ev.DecimalEncodedValue;
import com.graphhopper.routing.ev.EdgeIntAccess;
import com.graphhopper.routing.ev.EnumEncodedValue;
import com.graphhopper.routing.ev.Smoothness;
import com.graphhopper.routing.util.FerrySpeedCalculator;
import com.graphhopper.util.Helper;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public abstract class BikeCommonAverageSpeedParser extends AbstractAverageSpeedParser implements TagParser {
protected static final int PUSHING_SECTION_SPEED = 4;
protected static final int MIN_SPEED = 2;
// Pushing section highways are parts where you need to get off your bike and push it (German: Schiebestrecke)
protected final HashSet pushingSectionsHighways = new HashSet<>();
private final Map trackTypeSpeeds = new HashMap<>();
private final Map surfaceSpeeds = new HashMap<>();
private final Map smoothnessFactor = new HashMap<>();
private final Map highwaySpeeds = new HashMap<>();
private final EnumEncodedValue smoothnessEnc;
protected final Set intendedValues = new HashSet<>(5);
protected BikeCommonAverageSpeedParser(DecimalEncodedValue speedEnc, EnumEncodedValue smoothnessEnc, DecimalEncodedValue ferrySpeedEnc) {
super(speedEnc, ferrySpeedEnc);
this.smoothnessEnc = smoothnessEnc;
// duplicate code as also in BikeCommonPriorityParser
addPushingSection("footway");
addPushingSection("pedestrian");
addPushingSection("steps");
addPushingSection("platform");
setTrackTypeSpeed("grade1", 18); // paved
setTrackTypeSpeed("grade2", 12); // now unpaved ...
setTrackTypeSpeed("grade3", 8);
setTrackTypeSpeed("grade4", 6);
setTrackTypeSpeed("grade5", 4); // like sand/grass
setSurfaceSpeed("paved", 18);
setSurfaceSpeed("asphalt", 18);
setSurfaceSpeed("cobblestone", 8);
setSurfaceSpeed("cobblestone:flattened", 10);
setSurfaceSpeed("sett", 10);
setSurfaceSpeed("concrete", 18);
setSurfaceSpeed("concrete:lanes", 16);
setSurfaceSpeed("concrete:plates", 16);
setSurfaceSpeed("paving_stones", 16);
setSurfaceSpeed("paving_stones:30", 16);
setSurfaceSpeed("unpaved", 12);
setSurfaceSpeed("compacted", 14);
setSurfaceSpeed("dirt", 10);
setSurfaceSpeed("earth", 12);
setSurfaceSpeed("fine_gravel", 14); // should not be faster than compacted
setSurfaceSpeed("grass", 8);
setSurfaceSpeed("grass_paver", 8);
setSurfaceSpeed("gravel", 12);
setSurfaceSpeed("ground", 12);
setSurfaceSpeed("ice", MIN_SPEED);
setSurfaceSpeed("metal", 10);
setSurfaceSpeed("mud", 10);
setSurfaceSpeed("pebblestone", 14);
setSurfaceSpeed("salt", PUSHING_SECTION_SPEED);
setSurfaceSpeed("sand", PUSHING_SECTION_SPEED);
setSurfaceSpeed("wood", PUSHING_SECTION_SPEED);
setHighwaySpeed("living_street", PUSHING_SECTION_SPEED);
setHighwaySpeed("steps", MIN_SPEED);
setHighwaySpeed("cycleway", 18);
setHighwaySpeed("path", 10);
setHighwaySpeed("footway", 6);
setHighwaySpeed("platform", PUSHING_SECTION_SPEED);
setHighwaySpeed("pedestrian", PUSHING_SECTION_SPEED);
setHighwaySpeed("track", 12);
setHighwaySpeed("service", 12);
setHighwaySpeed("residential", 18);
// no other highway applies:
setHighwaySpeed("unclassified", 16);
// unknown road:
setHighwaySpeed("road", 12);
setHighwaySpeed("trunk", 18);
setHighwaySpeed("trunk_link", 18);
setHighwaySpeed("primary", 18);
setHighwaySpeed("primary_link", 18);
setHighwaySpeed("secondary", 18);
setHighwaySpeed("secondary_link", 18);
setHighwaySpeed("tertiary", 18);
setHighwaySpeed("tertiary_link", 18);
// special case see tests and #191
setHighwaySpeed("motorway", 18);
setHighwaySpeed("motorway_link", 18);
setHighwaySpeed("bridleway", PUSHING_SECTION_SPEED);
// note that this factor reduces the speed but only until MIN_SPEED
setSmoothnessSpeedFactor(Smoothness.MISSING, 1.0d);
setSmoothnessSpeedFactor(Smoothness.OTHER, 0.7d);
setSmoothnessSpeedFactor(Smoothness.EXCELLENT, 1.1d);
setSmoothnessSpeedFactor(Smoothness.GOOD, 1.0d);
setSmoothnessSpeedFactor(Smoothness.INTERMEDIATE, 0.9d);
setSmoothnessSpeedFactor(Smoothness.BAD, 0.7d);
setSmoothnessSpeedFactor(Smoothness.VERY_BAD, 0.4d);
setSmoothnessSpeedFactor(Smoothness.HORRIBLE, 0.3d);
setSmoothnessSpeedFactor(Smoothness.VERY_HORRIBLE, 0.1d);
setSmoothnessSpeedFactor(Smoothness.IMPASSABLE, 0);
intendedValues.add("yes");
intendedValues.add("designated");
intendedValues.add("official");
intendedValues.add("permissive");
}
/**
* @param way needed to retrieve tags
* @param speed speed guessed e.g. from the road type or other tags
* @return The assumed average speed.
*/
double applyMaxSpeed(ReaderWay way, double speed, boolean bwd) {
double maxSpeed = getMaxSpeed(way, bwd);
// We strictly obey speed limits, see #600
return isValidSpeed(maxSpeed) && speed > maxSpeed ? maxSpeed : speed;
}
@Override
public void handleWayTags(int edgeId, EdgeIntAccess edgeIntAccess, ReaderWay way) {
String highwayValue = way.getTag("highway");
if (highwayValue == null) {
if (FerrySpeedCalculator.isFerry(way)) {
double ferrySpeed = FerrySpeedCalculator.minmax(ferrySpeedEnc.getDecimal(false, edgeId, edgeIntAccess), avgSpeedEnc);
setSpeed(false, edgeId, edgeIntAccess, ferrySpeed);
if (avgSpeedEnc.isStoreTwoDirections())
setSpeed(true, edgeId, edgeIntAccess, ferrySpeed);
}
if (!way.hasTag("railway", "platform") && !way.hasTag("man_made", "pier"))
return;
}
double speed = getSpeed(way);
Smoothness smoothness = smoothnessEnc.getEnum(false, edgeId, edgeIntAccess);
speed = Math.max(MIN_SPEED, smoothnessFactor.get(smoothness) * speed);
setSpeed(false, edgeId, edgeIntAccess, applyMaxSpeed(way, speed, false));
if (avgSpeedEnc.isStoreTwoDirections())
setSpeed(true, edgeId, edgeIntAccess, applyMaxSpeed(way, speed, true));
}
int getSpeed(ReaderWay way) {
int speed = PUSHING_SECTION_SPEED;
String highwayTag = way.getTag("highway");
Integer highwaySpeed = highwaySpeeds.get(highwayTag);
if (way.hasTag("railway", "platform"))
highwaySpeed = PUSHING_SECTION_SPEED;
// Under certain conditions we need to increase the speed of pushing sections to the speed of a "highway=cycleway"
else if (way.hasTag("highway", pushingSectionsHighways)
&& ((way.hasTag("foot", "yes") && way.hasTag("segregated", "yes"))
|| (way.hasTag("bicycle", intendedValues)) && !way.hasTag("highway", "steps")))
highwaySpeed = getHighwaySpeed("cycleway");
String s = way.getTag("surface");
Integer surfaceSpeed = 0;
if (!Helper.isEmpty(s)) {
surfaceSpeed = surfaceSpeeds.get(s);
if (surfaceSpeed != null) {
speed = surfaceSpeed;
// boost handling for good surfaces but avoid boosting if pushing section
if (highwaySpeed != null && surfaceSpeed > highwaySpeed && pushingSectionsHighways.contains(highwayTag))
speed = highwaySpeed;
}
} else {
String tt = way.getTag("tracktype");
if (!Helper.isEmpty(tt)) {
Integer tInt = trackTypeSpeeds.get(tt);
if (tInt != null)
speed = tInt;
} else if (highwaySpeed != null) {
if (!way.hasTag("service"))
speed = highwaySpeed;
else
speed = highwaySpeeds.get("living_street");
}
}
// Until now we assumed that the way is no pushing section
// Now we check that, but only in case that our speed computed so far is bigger compared to the PUSHING_SECTION_SPEED
if (speed > PUSHING_SECTION_SPEED
&& (way.hasTag("highway", pushingSectionsHighways) || way.hasTag("bicycle", "dismount"))) {
if (!way.hasTag("bicycle", intendedValues)) {
// Here we set the speed for pushing sections and set speed for steps as even lower:
speed = way.hasTag("highway", "steps") ? MIN_SPEED : PUSHING_SECTION_SPEED;
} else if (way.hasTag("bicycle", "designated") || way.hasTag("bicycle", "official") ||
way.hasTag("segregated", "yes") || way.hasTag("bicycle", "yes")) {
// Here we handle the cases where the OSM tagging results in something similar to "highway=cycleway"
if (way.hasTag("segregated", "yes"))
speed = highwaySpeeds.get("cycleway");
else
speed = way.hasTag("bicycle", "yes") ? 10 : highwaySpeeds.get("cycleway");
// valid surface speed?
if (surfaceSpeed > 0)
speed = Math.min(speed, surfaceSpeed);
}
}
return speed;
}
void setHighwaySpeed(String highway, int speed) {
highwaySpeeds.put(highway, speed);
}
int getHighwaySpeed(String key) {
return highwaySpeeds.get(key);
}
void addPushingSection(String highway) {
pushingSectionsHighways.add(highway);
}
void setTrackTypeSpeed(String tracktype, int speed) {
trackTypeSpeeds.put(tracktype, speed);
}
void setSurfaceSpeed(String surface, int speed) {
surfaceSpeeds.put(surface, speed);
}
void setSmoothnessSpeedFactor(Smoothness smoothness, double speedfactor) {
smoothnessFactor.put(smoothness, speedfactor);
}
}