Skip to content

Commit fe20c07

Browse files
committed
Revert "remove Bike2WeightTagParser (graphhopper#2668)"
This reverts commit 5b1c7b2.
1 parent 99be96a commit fe20c07

File tree

14 files changed

+359
-40
lines changed

14 files changed

+359
-40
lines changed

core/src/main/java/com/graphhopper/GraphHopper.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -652,12 +652,8 @@ private void buildEncodingManagerAndOSMParsers(String flagEncodersStr, String en
652652
osmParsers.addWayTagParser(new OSMMaxSpeedParser(encodingManager.getDecimalEncodedValue(MaxSpeed.KEY)));
653653
if (!encodedValueStrings.contains(RoadAccess.KEY))
654654
osmParsers.addWayTagParser(new OSMRoadAccessParser(encodingManager.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class), OSMRoadAccessParser.toOSMRestrictions(TransportationMode.CAR)));
655-
if (encodingManager.hasEncodedValue(AverageSlope.KEY) || encodingManager.hasEncodedValue(MaxSlope.KEY)) {
656-
if (!encodingManager.hasEncodedValue(AverageSlope.KEY) || !encodingManager.hasEncodedValue(MaxSlope.KEY))
657-
throw new IllegalArgumentException("Enable both, average_slope and max_slope");
658-
osmParsers.addWayTagParser(new SlopeCalculator(encodingManager.getDecimalEncodedValue(MaxSlope.KEY),
659-
encodingManager.getDecimalEncodedValue(AverageSlope.KEY)));
660-
}
655+
if (encodingManager.hasEncodedValue(AverageSlope.KEY) || encodingManager.hasEncodedValue(MaxSlope.KEY))
656+
osmParsers.addWayTagParser(new SlopeCalculator(encodingManager.getDecimalEncodedValue(MaxSlope.KEY), encodingManager.getDecimalEncodedValue(AverageSlope.KEY)));
661657
if (encodingManager.hasEncodedValue(Curvature.KEY))
662658
osmParsers.addWayTagParser(new CurvatureCalculator(encodingManager.getDecimalEncodedValue(Curvature.KEY)));
663659

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package com.graphhopper.routing.util;
19+
20+
import com.graphhopper.reader.ReaderWay;
21+
import com.graphhopper.routing.ev.*;
22+
import com.graphhopper.storage.IntsRef;
23+
import com.graphhopper.util.PMap;
24+
import com.graphhopper.util.PointList;
25+
26+
import static com.graphhopper.util.Helper.keepIn;
27+
28+
/**
29+
* Stores two speed values into an edge to support avoiding too much incline
30+
*
31+
* @author Peter Karich
32+
*/
33+
public class Bike2WeightTagParser extends BikeTagParser {
34+
35+
public Bike2WeightTagParser(EncodedValueLookup lookup, PMap properties) {
36+
this(
37+
lookup.getBooleanEncodedValue(VehicleAccess.key(properties.getString("name", "bike2"))),
38+
lookup.getDecimalEncodedValue(VehicleSpeed.key(properties.getString("name", "bike2"))),
39+
lookup.getDecimalEncodedValue(VehiclePriority.key(properties.getString("name", "bike2"))),
40+
lookup.getEnumEncodedValue(BikeNetwork.KEY, RouteNetwork.class),
41+
lookup.getBooleanEncodedValue(Roundabout.KEY),
42+
lookup.getEnumEncodedValue(Smoothness.KEY, Smoothness.class),
43+
lookup.hasEncodedValue(TurnCost.key(properties.getString("name", "bike2"))) ? lookup.getDecimalEncodedValue(TurnCost.key(properties.getString("name", "bike2"))) : null,
44+
properties
45+
);
46+
}
47+
48+
public Bike2WeightTagParser(BooleanEncodedValue accessEnc, DecimalEncodedValue speedEnc,
49+
DecimalEncodedValue priorityEnc, EnumEncodedValue<RouteNetwork> bikeRouteEnc,
50+
BooleanEncodedValue roundaboutEnc,
51+
EnumEncodedValue<Smoothness> smoothnessEnc, DecimalEncodedValue turnCostEnc, PMap properties) {
52+
super(accessEnc, speedEnc, priorityEnc, bikeRouteEnc, smoothnessEnc, properties.getString("name", "bike2"),
53+
roundaboutEnc, turnCostEnc);
54+
blockPrivate(properties.getBool("block_private", true));
55+
blockFords(properties.getBool("block_fords", false));
56+
}
57+
58+
@Override
59+
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way) {
60+
edgeFlags = super.handleWayTags(edgeFlags, way);
61+
return applyWayTags(way, edgeFlags);
62+
}
63+
64+
public IntsRef applyWayTags(ReaderWay way, IntsRef intsRef) {
65+
PointList pl = way.getTag("point_list", null);
66+
if (pl == null)
67+
throw new IllegalArgumentException("The artificial point_list tag is missing");
68+
if (!pl.is3D())
69+
throw new IllegalStateException(getName() + " requires elevation data to improve speed calculation based on it. Please enable it in config via e.g. graph.elevation.provider: srtm");
70+
71+
if (way.hasTag("tunnel", "yes") || way.hasTag("bridge", "yes") || way.hasTag("highway", "steps"))
72+
// do not change speed
73+
// note: although tunnel can have a difference in elevation it is very unlikely that the elevation data is correct for a tunnel
74+
return intsRef;
75+
76+
// Decrease the speed for ele increase (incline), and decrease the speed for ele decrease (decline). The speed-decrease
77+
// has to be bigger (compared to the speed-increase) for the same elevation difference to simulate losing energy and avoiding hills.
78+
// For the reverse speed this has to be the opposite but again keeping in mind that up+down difference.
79+
double incEleSum = 0, incDist2DSum = 0, decEleSum = 0, decDist2DSum = 0;
80+
// double prevLat = pl.getLat(0), prevLon = pl.getLon(0);
81+
double prevEle = pl.getEle(0);
82+
if (!way.hasTag("edge_distance"))
83+
throw new IllegalArgumentException("The artificial edge_distance tag is missing");
84+
double fullDist2D = way.getTag("edge_distance", 0d);
85+
86+
// for short edges an incline makes no sense and for 0 distances could lead to NaN values for speed, see #432
87+
if (fullDist2D < 2)
88+
return intsRef;
89+
90+
double eleDelta = pl.getEle(pl.size() - 1) - prevEle;
91+
if (eleDelta > 0.1) {
92+
incEleSum = eleDelta;
93+
incDist2DSum = fullDist2D;
94+
} else if (eleDelta < -0.1) {
95+
decEleSum = -eleDelta;
96+
decDist2DSum = fullDist2D;
97+
}
98+
99+
// Calculate slop via tan(asin(height/distance)) but for rather smallish angles where we can assume tan a=a and sin a=a.
100+
// Then calculate a factor which decreases or increases the speed.
101+
// Do this via a simple quadratic equation where y(0)=1 and y(0.3)=1/4 for incline and y(0.3)=2 for decline
102+
double fwdIncline = incDist2DSum > 1 ? incEleSum / incDist2DSum : 0;
103+
double fwdDecline = decDist2DSum > 1 ? decEleSum / decDist2DSum : 0;
104+
double restDist2D = fullDist2D - incDist2DSum - decDist2DSum;
105+
double maxSpeed = getHighwaySpeed("cycleway");
106+
if (accessEnc.getBool(false, intsRef)) {
107+
// use weighted mean so that longer incline influences speed more than shorter
108+
double speed = avgSpeedEnc.getDecimal(false, intsRef);
109+
double fwdFaster = 1 + 2 * keepIn(fwdDecline, 0, 0.2);
110+
fwdFaster = fwdFaster * fwdFaster;
111+
double fwdSlower = 1 - 5 * keepIn(fwdIncline, 0, 0.2);
112+
fwdSlower = fwdSlower * fwdSlower;
113+
speed = speed * (fwdSlower * incDist2DSum + fwdFaster * decDist2DSum + 1 * restDist2D) / fullDist2D;
114+
setSpeed(false, intsRef, keepIn(speed, MIN_SPEED, maxSpeed));
115+
}
116+
117+
if (accessEnc.getBool(true, intsRef)) {
118+
double speedReverse = avgSpeedEnc.getDecimal(true, intsRef);
119+
double bwFaster = 1 + 2 * keepIn(fwdIncline, 0, 0.2);
120+
bwFaster = bwFaster * bwFaster;
121+
double bwSlower = 1 - 5 * keepIn(fwdDecline, 0, 0.2);
122+
bwSlower = bwSlower * bwSlower;
123+
speedReverse = speedReverse * (bwFaster * incDist2DSum + bwSlower * decDist2DSum + 1 * restDist2D) / fullDist2D;
124+
setSpeed(true, intsRef, keepIn(speedReverse, MIN_SPEED, maxSpeed));
125+
}
126+
return intsRef;
127+
}
128+
129+
}

core/src/main/java/com/graphhopper/routing/util/DefaultVehicleEncodedValuesFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public VehicleEncodedValues createVehicleEncodedValues(String name, PMap configu
3939
if (name.equals(BIKE))
4040
return VehicleEncodedValues.bike(configuration);
4141

42-
if (name.equals("bike2"))
43-
throw new IllegalArgumentException("Instead of bike2 use the bike vehicle and a custom model, see custom_models/bike2.json and #1234");
42+
if (name.equals(BIKE2))
43+
return VehicleEncodedValues.bike2(configuration);
4444

4545
if (name.equals(RACINGBIKE))
4646
return VehicleEncodedValues.racingbike(configuration);

core/src/main/java/com/graphhopper/routing/util/DefaultVehicleTagParserFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public VehicleTagParser createParser(EncodedValueLookup lookup, String name, PMa
3131
return new CarTagParser(lookup, configuration);
3232
if (name.equals(BIKE))
3333
return new BikeTagParser(lookup, configuration);
34+
if (name.equals(BIKE2))
35+
return new Bike2WeightTagParser(lookup, configuration);
3436
if (name.equals(RACINGBIKE))
3537
return new RacingBikeTagParser(lookup, configuration);
3638
if (name.equals(MOUNTAINBIKE))

core/src/main/java/com/graphhopper/routing/util/SlopeCalculator.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationF
2323
PointList pointList = way.getTag("point_list", null);
2424
if (pointList != null) {
2525
if (pointList.isEmpty() || !pointList.is3D()) {
26-
averageSlopeEnc.setDecimal(false, edgeFlags, 0);
26+
if (averageSlopeEnc != null) averageSlopeEnc.setDecimal(false, edgeFlags, 0);
2727
return edgeFlags;
2828
}
2929
// Calculate 2d distance, although pointList might be 3D.
@@ -32,20 +32,20 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationF
3232

3333
if (distance2D < MIN_LENGTH) {
3434
// default is minimum of average_slope is negative so we have to explicitly set it to 0
35-
averageSlopeEnc.setDecimal(false, edgeFlags, 0);
35+
if (averageSlopeEnc != null) averageSlopeEnc.setDecimal(false, edgeFlags, 0);
3636
return edgeFlags;
3737
}
3838

3939
double towerNodeSlope = calcSlope(pointList.getEle(pointList.size() - 1) - pointList.getEle(0), distance2D);
4040
if (Double.isNaN(towerNodeSlope))
4141
throw new IllegalArgumentException("average_slope was NaN for OSM way ID " + way.getId());
4242

43-
44-
if (towerNodeSlope >= 0)
45-
averageSlopeEnc.setDecimal(false, edgeFlags, Math.min(towerNodeSlope, averageSlopeEnc.getMaxStorableDecimal()));
46-
else
47-
averageSlopeEnc.setDecimal(true, edgeFlags, Math.min(Math.abs(towerNodeSlope), averageSlopeEnc.getMaxStorableDecimal()));
48-
43+
if (averageSlopeEnc != null) {
44+
if (towerNodeSlope >= 0)
45+
averageSlopeEnc.setDecimal(false, edgeFlags, Math.min(towerNodeSlope, averageSlopeEnc.getMaxStorableDecimal()));
46+
else
47+
averageSlopeEnc.setDecimal(true, edgeFlags, Math.min(Math.abs(towerNodeSlope), averageSlopeEnc.getMaxStorableDecimal()));
48+
}
4949

5050
// max_slope is more error-prone as the shorter distances increase the fluctuation
5151
// so apply some more filtering (here we use the average elevation delta of the previous two points)
@@ -74,7 +74,8 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, IntsRef relationF
7474

7575
// TODO Use two independent values for both directions to store if it is a gain or loss and not just the absolute change.
7676
// TODO To save space then it would be nice to have an encoded value that can store two different values which are swapped when the reverse direction is used
77-
maxSlopeEnc.setDecimal(false, edgeFlags, Math.min(maxSlope, maxSlopeEnc.getMaxStorableDecimal()));
77+
if (maxSlopeEnc != null)
78+
maxSlopeEnc.setDecimal(false, edgeFlags, Math.min(maxSlope, maxSlopeEnc.getMaxStorableDecimal()));
7879
}
7980
return edgeFlags;
8081
}

core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValues.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import static com.graphhopper.routing.util.VehicleEncodedValuesFactory.*;
2828

2929
public class VehicleEncodedValues {
30-
public static final List<String> OUTDOOR_VEHICLES = Arrays.asList(BIKE, RACINGBIKE, MOUNTAINBIKE, FOOT, HIKE, WHEELCHAIR);
30+
public static final List<String> OUTDOOR_VEHICLES = Arrays.asList(BIKE, BIKE2, RACINGBIKE, MOUNTAINBIKE, FOOT, HIKE, WHEELCHAIR);
3131

3232
private final String name;
3333
private final BooleanEncodedValue accessEnc;

core/src/main/java/com/graphhopper/routing/util/VehicleEncodedValuesFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public interface VehicleEncodedValuesFactory {
2626
String ROADS = "roads";
2727
String CAR = "car";
2828
String BIKE = "bike";
29+
String BIKE2 = "bike2";
2930
String RACINGBIKE = "racingbike";
3031
String MOUNTAINBIKE = "mtb";
3132
String FOOT = "foot";

core/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMTest.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
import java.util.concurrent.atomic.AtomicInteger;
4242
import java.util.function.Function;
4343

44-
import static com.graphhopper.json.Statement.Op.LIMIT;
45-
import static com.graphhopper.json.Statement.Op.MULTIPLY;
4644
import static com.graphhopper.util.Parameters.Algorithms.*;
4745
import static org.junit.jupiter.api.Assertions.*;
4846

@@ -130,7 +128,7 @@ public void testMonacoMotorcycleCurvature() {
130128
queries.add(new Query(43.733802, 7.413433, 43.739662, 7.424355, 2423, 141));
131129
queries.add(new Query(43.730949, 7.412338, 43.739643, 7.424542, 2253, 120));
132130
queries.add(new Query(43.727592, 7.419333, 43.727712, 7.419333, 0, 1));
133-
CustomModel model = new CustomModel().addToPriority(Statement.If("true", MULTIPLY, "curvature"));
131+
CustomModel model = new CustomModel().addToPriority(Statement.If("true", Statement.Op.MULTIPLY, "curvature"));
134132

135133
GraphHopper hopper = createHopper(MONACO, new CustomProfile("motorcycle").setCustomModel(model).
136134
setVehicle("motorcycle").setWeighting("custom"));
@@ -146,9 +144,8 @@ public void testBike2_issue432() {
146144
queries.add(new Query(52.349969, 8.013813, 52.349713, 8.013293, 56, 7));
147145
// reverse route avoids the location
148146
// list.add(new OneRun(52.349713, 8.013293, 52.349969, 8.013813, 293, 21));
149-
CustomModel model = new CustomModel();
150147
GraphHopper hopper = createHopper(DIR + "/map-bug432.osm.gz",
151-
new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
148+
new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
152149
hopper.setElevationProvider(new SRTMProvider(DIR));
153150
hopper.importOrLoad();
154151
checkQueries(hopper, queries);
@@ -325,31 +322,25 @@ public void testNorthBayreuthHikeFastestAnd3D() {
325322
}
326323

327324
@Test
328-
public void testMonacoBike3D() {
325+
public void testMonacoBike3D_twoSpeedsPerEdge() {
329326
List<Query> queries = new ArrayList<>();
330327
// 1. alternative: go over steps 'Rampe Major' => 1.7km vs. around 2.7km
331-
queries.add(new Query(43.730864, 7.420771, 43.727687, 7.418737, 1999, 101));
328+
queries.add(new Query(43.730864, 7.420771, 43.727687, 7.418737, 2689, 118));
332329
// 2.
333-
queries.add(new Query(43.728499, 7.417907, 43.74958, 7.436566, 3939, 187));
330+
queries.add(new Query(43.728499, 7.417907, 43.74958, 7.436566, 3735, 194));
334331
// 3.
335-
queries.add(new Query(43.728677, 7.41016, 43.739213, 7.427806, 2776, 163));
332+
queries.add(new Query(43.728677, 7.41016, 43.739213, 7.427806, 2776, 167));
336333
// 4.
337334
queries.add(new Query(43.733802, 7.413433, 43.739662, 7.424355, 1544, 84));
338335

339336
// try reverse direction
340337
// 1.
341338
queries.add(new Query(43.727687, 7.418737, 43.730864, 7.420771, 2599, 115));
342-
queries.add(new Query(43.74958, 7.436566, 43.728499, 7.417907, 3902, 199));
343-
queries.add(new Query(43.739213, 7.427806, 43.728677, 7.41016, 2870, 154));
339+
queries.add(new Query(43.74958, 7.436566, 43.728499, 7.417907, 4180, 165));
340+
queries.add(new Query(43.739213, 7.427806, 43.728677, 7.41016, 2805, 145));
344341
// 4. avoid tunnel(s)!
345-
queries.add(new Query(43.739662, 7.424355, 43.733802, 7.413433, 1795, 96));
346-
CustomModel model = new CustomModel();
347-
model.addToSpeed(Statement.If("average_slope >= 10", LIMIT, "4")).
348-
addToSpeed(Statement.If("average_slope >= 5", MULTIPLY, "0.45")).
349-
addToSpeed(Statement.If("average_slope >= 3.5", MULTIPLY, "0.7")).
350-
addToSpeed(Statement.If("average_slope >= 2", MULTIPLY, "0.9")).
351-
addToSpeed(Statement.If("average_slope < -5", MULTIPLY, "1.25"));
352-
GraphHopper hopper = createHopper(MONACO, new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
342+
queries.add(new Query(43.739662, 7.424355, 43.733802, 7.413433, 2436, 112));
343+
GraphHopper hopper = createHopper(MONACO, new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
353344
hopper.setElevationProvider(new SRTMProvider(DIR));
354345
hopper.importOrLoad();
355346
checkQueries(hopper, queries);
@@ -580,8 +571,7 @@ public void testNeudrossenfeld() {
580571

581572
Helper.removeDir(new File(GH_LOCATION));
582573

583-
CustomModel model = new CustomModel();
584-
hopper = createHopper(BAYREUTH, new CustomProfile("bike2").setCustomModel(model).setVehicle("bike").setWeighting("custom"));
574+
hopper = createHopper(BAYREUTH, new Profile("bike2").setVehicle("bike2").setWeighting("fastest"));
585575
hopper.setElevationProvider(new SRTMProvider(DIR));
586576
hopper.importOrLoad();
587577
checkQueries(hopper, list);
@@ -696,7 +686,6 @@ private GraphHopper createHopper(String osmFile, Profile... profiles) {
696686
setStoreOnFlush(true).
697687
setOSMFile(osmFile).
698688
setProfiles(profiles).
699-
setEncodedValuesString("average_slope,max_slope").
700689
setGraphHopperLocation(GH_LOCATION);
701690
hopper.getRouterConfig().setSimplifyResponse(false);
702691
hopper.setMinNetworkSize(0);

0 commit comments

Comments
 (0)