Skip to content

Commit 53cd688

Browse files
authored
Merge pull request opentripplanner#6783 from Aubin-MaaS/multiplicative-stairs-and-turn-reluctance
Multiplicative stairs and turn reluctance
2 parents f505716 + d4d5680 commit 53cd688

File tree

22 files changed

+289
-295
lines changed

22 files changed

+289
-295
lines changed

application/src/ext-test/java/org/opentripplanner/ext/flex/FlexIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ void flexDirect() {
164164
// walk, flex
165165
assertEquals(2, itin.legs().size());
166166
assertEquals("2021-12-02T12:52:56-05:00[America/New_York]", itin.startTime().toString());
167-
assertEquals(3200, itin.generalizedCost());
167+
assertEquals(3248, itin.generalizedCost());
168168

169169
var walkToFlex = itin.streetLeg(0);
170170
assertEquals(WALK, walkToFlex.getMode());

application/src/main/java/org/opentripplanner/apis/transmodel/model/DefaultRouteRequestType.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ private GraphQLObjectType createGraphQLType() {
117117
.field(
118118
GraphQLFieldDefinition.newFieldDefinition()
119119
.name("stairsReluctance")
120-
.description("Used instead of walkReluctance for stairs.")
120+
.description(
121+
"A multiplier to specify how bad walking on stairs is, compared to walking on flat ground, on top of the walk reluctance."
122+
)
121123
.type(Scalars.GraphQLFloat)
122124
.dataFetcher(env -> preferences.walk().stairsReluctance())
123125
.build()

application/src/main/java/org/opentripplanner/routing/api/request/preference/VehicleWalkingPreferences.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ private VehicleWalkingPreferences() {
2828
this.reluctance = 5.0;
2929
this.mountDismountTime = Duration.ZERO;
3030
this.mountDismountCost = Cost.ZERO;
31-
// very high reluctance to carry the bike up/down a flight of stairs
32-
this.stairsReluctance = 10;
31+
// multiplicative factor to carry the bike up/down a flight of stairs on top of the walk reluctance
32+
this.stairsReluctance = 2;
3333
}
3434

3535
/**
@@ -82,7 +82,7 @@ public Cost mountDismountCost() {
8282
return mountDismountCost;
8383
}
8484

85-
/** Reluctance of walking carrying a vehicle up a flight of stairs. */
85+
/** Reluctance of carrying a vehicle up a flight of stairs on top of walking the vehicle. */
8686
public double stairsReluctance() {
8787
return stairsReluctance;
8888
}

application/src/main/java/org/opentripplanner/routing/api/request/preference/WalkPreferences.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ public int boardCost() {
9292
return boardCost.toSeconds();
9393
}
9494

95-
/** Used instead of walk reluctance for stairs */
95+
/**
96+
* Used on top of {@link #reluctance()} for stairs. If the value is set to 1, walking on stairs is
97+
* treated the same as walking on flat ground.
98+
*/
9699
public double stairsReluctance() {
97100
return stairsReluctance;
98101
}

application/src/main/java/org/opentripplanner/standalone/config/routerequest/RouteRequestConfig.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,9 @@ private static void mapWalkPreferences(NodeAdapter root, WalkPreferences.Builder
841841
c
842842
.of("stairsReluctance")
843843
.since(V2_0)
844-
.summary("Used instead of walkReluctance for stairs.")
844+
.summary(
845+
"A multiplier to specify how bad walking on stairs is, on top of the reluctance parameter."
846+
)
845847
.asDouble(dft.stairsReluctance())
846848
)
847849
.withStairsTimeFactor(

application/src/main/java/org/opentripplanner/standalone/config/routerequest/VehicleWalkingConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private static void mapVehicleWalkingPreferences(
7474
.of("stairsReluctance")
7575
.since(V2_3)
7676
.summary(
77-
"How bad is it to walk the vehicle up/down a flight of stairs compared to taking a detour."
77+
"How bad is it to walk the vehicle up/down a flight of stairs, on top of the reluctance parameter."
7878
)
7979
.asDouble(dft.stairsReluctance())
8080
);

application/src/main/java/org/opentripplanner/street/model/edge/StreetEdge.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,14 +1021,16 @@ private StateEditor doTraverse(State s0, TraverseMode traverseMode, boolean walk
10211021
* that during reverse traversal, we must also use the speed for the mode of
10221022
* the backEdge, rather than of the current edge.
10231023
*/
1024+
var intersectionMode = arriveBy ? backMode : traverseMode;
1025+
boolean walkingBikeThroughIntersection = arriveBy ? s0.isBackWalkingBike() : walkingBike;
10241026
if (arriveBy && tov instanceof IntersectionVertex traversedVertex) { // arrive-by search
10251027
turnDuration = s0
10261028
.intersectionTraversalCalculator()
10271029
.computeTraversalDuration(
10281030
traversedVertex,
10291031
this,
10301032
backPSE,
1031-
backMode,
1033+
intersectionMode,
10321034
(float) speed,
10331035
(float) backSpeed
10341036
);
@@ -1039,7 +1041,7 @@ private StateEditor doTraverse(State s0, TraverseMode traverseMode, boolean walk
10391041
traversedVertex,
10401042
backPSE,
10411043
this,
1042-
traverseMode,
1044+
intersectionMode,
10431045
(float) backSpeed,
10441046
(float) speed
10451047
);
@@ -1049,8 +1051,18 @@ private StateEditor doTraverse(State s0, TraverseMode traverseMode, boolean walk
10491051
turnDuration = 0;
10501052
}
10511053

1054+
var modeReluctance =
1055+
switch (intersectionMode) {
1056+
case WALK -> walkingBikeThroughIntersection
1057+
? preferences.bike().walking().reluctance()
1058+
: preferences.walk().reluctance();
1059+
case BICYCLE -> preferences.bike().reluctance();
1060+
case SCOOTER -> preferences.scooter().reluctance();
1061+
case CAR -> preferences.car().reluctance();
1062+
case FLEX -> 1;
1063+
};
10521064
time_ms += (long) Math.ceil(1000.0 * turnDuration);
1053-
weight += preferences.street().turnReluctance() * turnDuration;
1065+
weight += modeReluctance * preferences.street().turnReluctance() * turnDuration;
10541066
}
10551067

10561068
if (!traverseMode.isInCar()) {
@@ -1152,10 +1164,6 @@ private TraversalCosts walkingTraversalCosts(
11521164
if (walkingBike) {
11531165
// take slopes into account when walking bikes
11541166
time = weight = (getEffectiveBikeDistance() / speed);
1155-
if (isStairs()) {
1156-
// we do allow walking the bike across a stairs but there is a very high default penalty
1157-
weight *= preferences.bike().walking().stairsReluctance();
1158-
}
11591167
} else {
11601168
// take slopes into account when walking
11611169
time = getEffectiveWalkDistance() / speed;

application/src/main/java/org/opentripplanner/street/model/edge/StreetEdgeReluctanceCalculator.java

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.opentripplanner.street.model.edge;
22

33
import org.opentripplanner.routing.api.request.preference.RoutingPreferences;
4+
import org.opentripplanner.routing.api.request.preference.VehicleWalkingPreferences;
5+
import org.opentripplanner.routing.api.request.preference.WalkPreferences;
46
import org.opentripplanner.street.search.TraverseMode;
57

68
class StreetEdgeReluctanceCalculator {
@@ -18,19 +20,28 @@ static double computeReluctance(
1820
boolean walkingBike,
1921
boolean edgeIsStairs
2022
) {
21-
if (edgeIsStairs) {
22-
return pref.walk().stairsReluctance();
23-
} else {
24-
return switch (traverseMode) {
25-
case WALK -> walkingBike ? pref.bike().walking().reluctance() : pref.walk().reluctance();
26-
case BICYCLE -> pref.bike().reluctance();
27-
case CAR -> pref.car().reluctance();
28-
case SCOOTER -> pref.scooter().reluctance();
29-
default -> throw new IllegalArgumentException(
30-
"getReluctance(): Invalid mode " + traverseMode
31-
);
32-
};
33-
}
23+
return switch (traverseMode) {
24+
case WALK -> walkingBike
25+
? computeBikeWalkingReluctance(pref.bike().walking(), edgeIsStairs)
26+
: computeWalkReluctance(pref.walk(), edgeIsStairs);
27+
case BICYCLE -> pref.bike().reluctance();
28+
case CAR -> pref.car().reluctance();
29+
case SCOOTER -> pref.scooter().reluctance();
30+
default -> throw new IllegalArgumentException(
31+
"getReluctance(): Invalid mode " + traverseMode
32+
);
33+
};
34+
}
35+
36+
private static double computeWalkReluctance(WalkPreferences pref, boolean edgeIsStairs) {
37+
return pref.reluctance() * (edgeIsStairs ? pref.stairsReluctance() : 1);
38+
}
39+
40+
private static double computeBikeWalkingReluctance(
41+
VehicleWalkingPreferences pref,
42+
boolean edgeIsStairs
43+
) {
44+
return pref.reluctance() * (edgeIsStairs ? pref.stairsReluctance() : 1);
3445
}
3546

3647
static double computeWheelchairReluctance(

application/src/main/resources/org/opentripplanner/apis/transmodel/schema.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ type RoutingParameters {
11091109
reverseOptimizeOnTheFly: Boolean @deprecated(reason : "NOT IN USE IN OTP2.")
11101110
"Whether the planner should return intermediate stops lists for transit legs."
11111111
showIntermediateStops: Boolean @deprecated(reason : "This parameter is always enabled")
1112-
"Used instead of walkReluctance for stairs."
1112+
"A multiplier to specify how bad walking on stairs is, compared to walking on flat ground, on top of the walk reluctance."
11131113
stairsReluctance: Float
11141114
"An extra penalty added on transfers (i.e. all boardings except the first one)."
11151115
transferPenalty: Int

0 commit comments

Comments
 (0)