From 3a7142703c46e103ab5f613df427b08ecdac68a8 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 5 Dec 2019 10:58:28 +0200 Subject: [PATCH 1/3] Remove extra files left over after a merge --- .../elevation/ToblersHickingFunction.java | 125 ------------------ .../elevation/ToblersHickingFunctionTest.java | 65 --------- 2 files changed, 190 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunction.java delete mode 100644 src/test/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunctionTest.java diff --git a/src/main/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunction.java b/src/main/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunction.java deleted file mode 100644 index 0e9e102f2ca..00000000000 --- a/src/main/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunction.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - This program is free software: you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -package org.opentripplanner.routing.util.elevation; - - -/** - *

- * Tobler's hiking function is an exponential function determining the hiking speed, taking into account the - * slope angle. It was formulated by Waldo Tobler. This function was estimated from empirical data of Eduard Imhof. - * [ Wikipedia ] - *

- *
- * Walking speed(W):
- *
- *     W = 6 m/s * Exp(-3.5 * Abs(dh/dx + 0.05))
- * 
- * - *

- * The {@code 6 m/s} is the Maximum speed achieved. This happens at angle 2.86 degrees or -5% downhill. In OTP we - * want to apply this as a multiplier to the horizontal walking distance. This is done for all walkable edges in - * the graph. To find the walkingtime for an edge we use the horizontal walking speed. Therefore: - *

- *
- * Given:
- *   Vflat : Speed at 0 degrees - flat
- *   Vmax  : Maximum speed (6 m/s)
- *
- *   Vmax = C * Vflat
- *
- * Then:
- *               1
- *   C = ------------------  = 1.19
- *        EXP(-3.5 * 0.05)
- * And:
- *
- *   dx = Vflat *  t
- *   W = C * Vflat * EXP(-3.5 * ABS(dh/dx + 0.05))
- *
- * The Horizontal walking distance multiplier(F) then becomes:
- *
- *                      1
- *   F = -----------------------------------
- *        C * EXP(-3.5 * ABS(dh/dx + 0.05))
- *
- * Examples:
- *
- *   Angle  | Slope % | Horizontal walking distance multiplier
- *   -------+---------------------------------------
- *    19,3  |   35 %  |  3,41
- *    16,7  |   30 %  |  2,86
- *    14,0  |   25 %  |  2,40
- *    11,3  |   20 %  |  2,02
- *     8,5  |   15 %  |  1,69
- *     5,7  |   10 %  |  1,42
- *     2,9  |    5 %  |  1,19
- *     0,0  |    0 %  |  1,00
- *    −2,9  |   −5 %  |  0,84
- *    −5,7  |  −10 %  |  1,00
- *    −8,5  |  −15 %  |  1,19
- *   −11,3  |  −20 %  |  1,42
- *   −14,0  |  −25 %  |  1,69
- *   −16,7  |  −30 %  |  2,02
- *   −19,3  |  −35 %  |  2,40
- *   −21,8  |  −40 %  |  2,86
- *   −24,2  |  −45 %  |  3,41
- * 
- */ -public class ToblersHickingFunction { - - /** - * The exponential growth factor in Tobler´s function. - */ - private static final double E = -3.5; - - /** - * The slope offset where the maximum speed will occur. The value 0.05 will result in a maximum speed at - * -2.86 degrees (5% downhill). - */ - private static final double A = 0.05; - - /** The horizontal speed to maximum speed factor: Vmax = C * Vflat */ - private static final double C = 1 / Math.exp(E * A); - - - private final double walkDistMultiplierMaxLimit; - - - /** - * @param walkDistMultiplierMaxLimit this property is used to set a maximum limit for the horizontal walking - * distance multiplier. Must be > 1.0. See the table in the class documentation - * for finding reasonable values for this constant. - */ - public ToblersHickingFunction(double walkDistMultiplierMaxLimit) { - if(walkDistMultiplierMaxLimit < 1.0) { - throw new IllegalArgumentException("The 'walkDistMultiplierMaxLimit' is " + walkDistMultiplierMaxLimit + - ", but must be greater then 1."); - } - this.walkDistMultiplierMaxLimit = walkDistMultiplierMaxLimit; - } - - /** - * Calculate a walking distance multiplier to account tor the slope penalty. - * @param dx The horizontal walking distance - * @param dh The vertical distance (height) - */ - public double calculateHorizontalWalkingDistanceMultiplier(double dx, double dh) { - - double distanceMultiplier = 1.0 / (C * Math.exp(E * Math.abs(dh/dx + A))); - - return distanceMultiplier < walkDistMultiplierMaxLimit ? distanceMultiplier : walkDistMultiplierMaxLimit; - } -} diff --git a/src/test/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunctionTest.java b/src/test/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunctionTest.java deleted file mode 100644 index 477a9c35293..00000000000 --- a/src/test/java/org/opentripplanner/routing/util/elevation/ToblersHickingFunctionTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.opentripplanner.routing.util.elevation; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.opentripplanner.routing.util.elevation.ToblersHickingFunctionTest.TestCase.tc; - -public class ToblersHickingFunctionTest { - - private static final double CUT_OFF_LIMIT = 3.2; - - @Test - public void calculateHorizontalWalkingDistanceMultiplier() { - TestCase[] testCases = { - tc(35, CUT_OFF_LIMIT), - tc(31.4, 3.0), - tc(30, 2.86), - tc(25, 2.40), - tc(20, 2.02), - tc(15, 1.69), - tc(10, 1.42), - tc(5, 1.19), - tc(0, 1.00), - tc(-5, 0.84), - tc(-10, 1.00), - tc(-15, 1.19), - tc(-20, 1.42), - tc(-25, 1.69), - tc(-30, 2.02), - tc(-35, 2.40), - tc(-40, 2.86), - tc(-45, CUT_OFF_LIMIT) - }; - - ToblersHickingFunction f = new ToblersHickingFunction(CUT_OFF_LIMIT); - - for (TestCase it : testCases) { - double distMultiplier = f.calculateHorizontalWalkingDistanceMultiplier(it.dx, it.dh); - assertEquals(it.describe(), it.expected, distMultiplier, 0.01); - } - } - - static class TestCase { - - final double slopeAnglePercentage, dx, dh, expected; - - TestCase(double slopeAnglePercentage, double expected) { - this.slopeAnglePercentage = slopeAnglePercentage; - // Set the horizontal distance to 300 meters - this.dx = 300.0; - // Calculate the height: - this.dh = dx * slopeAnglePercentage / 100.0; - - this.expected = expected; - } - - static TestCase tc(double slopeAngle, double expected) { - return new TestCase(slopeAngle, expected); - } - - String describe() { - return String.format("Multiplier at %.1f%% slope angle with dx %.1f and dh %.1f.", slopeAnglePercentage, dx, dh); - } - } -} \ No newline at end of file From fe76dc3bff75c12035327b2e3f8510ba87c45e1e Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 5 Dec 2019 13:27:46 +0200 Subject: [PATCH 2/3] Expose maxSlope for configuration --- .../opentripplanner/api/common/RoutingResource.java | 10 ++++++++++ .../java/org/opentripplanner/index/GraphQlPlanner.java | 1 + .../org/opentripplanner/index/IndexGraphQLSchema.java | 5 +++++ .../opentripplanner/routing/core/RoutingRequest.java | 6 ++++++ 4 files changed, 22 insertions(+) diff --git a/src/main/java/org/opentripplanner/api/common/RoutingResource.java b/src/main/java/org/opentripplanner/api/common/RoutingResource.java index fd7237aa61e..ad28cb91f03 100644 --- a/src/main/java/org/opentripplanner/api/common/RoutingResource.java +++ b/src/main/java/org/opentripplanner/api/common/RoutingResource.java @@ -90,6 +90,13 @@ public abstract class RoutingResource { @QueryParam("maxPreTransitTime") protected Integer maxPreTransitTime; + /** + * The maximum slope, up or downhill, that can be used in wheelchair accessible routing. + * Value is between 0 and 1, and calculated by dividing change of elevation by change of distance. + */ + @QueryParam("maxSlope") + protected Double maxSlope; + /** * A multiplier for how bad walking is, compared to being in transit for equal lengths of time. * Defaults to 2. Empirically, values between 10 and 20 seem to correspond well to the concept @@ -537,6 +544,9 @@ protected RoutingRequest buildRequest() throws ParameterException { if (maxPreTransitTime != null) request.setMaxPreTransitTime(maxPreTransitTime); + if (maxSlope != null) + request.setMaxSlope(maxSlope); + if(carParkCarLegWeight != null) { request.setCarParkCarLegWeight(carParkCarLegWeight); } diff --git a/src/main/java/org/opentripplanner/index/GraphQlPlanner.java b/src/main/java/org/opentripplanner/index/GraphQlPlanner.java index 60a3541e7d1..9366998c774 100644 --- a/src/main/java/org/opentripplanner/index/GraphQlPlanner.java +++ b/src/main/java/org/opentripplanner/index/GraphQlPlanner.java @@ -178,6 +178,7 @@ private RoutingRequest createRequest(DataFetchingEnvironment environment) { callWith.argument("wheelchair", request::setWheelchairAccessible); callWith.argument("numItineraries", request::setNumItineraries); callWith.argument("maxWalkDistance", request::setMaxWalkDistance); + callWith.argument("maxSlope", request::setMaxSlope); callWith.argument("maxPreTransitTime", request::setMaxPreTransitTime); callWith.argument("carParkCarLegWeight", request::setCarParkCarLegWeight); callWith.argument("itineraryFiltering", request::setItineraryFiltering); diff --git a/src/main/java/org/opentripplanner/index/IndexGraphQLSchema.java b/src/main/java/org/opentripplanner/index/IndexGraphQLSchema.java index b3c920cbc84..ea98777ba4c 100644 --- a/src/main/java/org/opentripplanner/index/IndexGraphQLSchema.java +++ b/src/main/java/org/opentripplanner/index/IndexGraphQLSchema.java @@ -613,6 +613,11 @@ public IndexGraphQLSchema(GraphIndex index) { .description("The maximum time (in seconds) of pre-transit travel when using drive-to-transit (park and ride or kiss and ride). Default value: 1800.") .type(Scalars.GraphQLInt) .build()) + .argument(GraphQLArgument.newArgument() + .name("maxSlope") + .description("The maximum slope, up or downhill, that can be used in wheelchair accessible routing. Value is between 0 and 1, and calculated by dividing change of elevation by change of distance. Default value: 0.0833333333333") + .type(Scalars.GraphQLFloat) + .build()) .argument(GraphQLArgument.newArgument() .name("carParkCarLegWeight") .description("How expensive it is to drive a car when car&parking, increase this value to make car driving legs shorter. Default value: 1.") diff --git a/src/main/java/org/opentripplanner/routing/core/RoutingRequest.java b/src/main/java/org/opentripplanner/routing/core/RoutingRequest.java index 1c0da0688d1..e7665b4d103 100644 --- a/src/main/java/org/opentripplanner/routing/core/RoutingRequest.java +++ b/src/main/java/org/opentripplanner/routing/core/RoutingRequest.java @@ -1431,6 +1431,12 @@ public void setMaxPreTransitTime(int maxPreTransitTime) { } } + public void setMaxSlope(double maxSlope) { + if (maxSlope >= 0 && maxSlope <= 1) { + this.maxSlope = maxSlope; + } + } + public void setModeWeight(TraverseMode traverseMode, Double weight) { if (weight > 0) { this.modeWeights.put(traverseMode, weight); From 7dfcbc39d4afc425d04f0ba774b3c25be1e07f95 Mon Sep 17 00:00:00 2001 From: Joel Lappalainen Date: Thu, 5 Dec 2019 13:28:13 +0200 Subject: [PATCH 3/3] Use maxSlope from defaultRoutingRequest in wheelchair debug layer --- .../org/opentripplanner/inspector/TileRendererManager.java | 5 +++-- .../opentripplanner/inspector/WheelchairEdgeRenderer.java | 6 ++++-- src/main/java/org/opentripplanner/standalone/Router.java | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/opentripplanner/inspector/TileRendererManager.java b/src/main/java/org/opentripplanner/inspector/TileRendererManager.java index 3d27a21cb49..fc0b26b15ca 100644 --- a/src/main/java/org/opentripplanner/inspector/TileRendererManager.java +++ b/src/main/java/org/opentripplanner/inspector/TileRendererManager.java @@ -8,6 +8,7 @@ import org.opentripplanner.analyst.request.TileRequest; import org.opentripplanner.api.resource.GraphInspectorTileResource; import org.opentripplanner.inspector.TileRenderer.TileRenderContext; +import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.services.GraphService; import org.slf4j.Logger; @@ -35,14 +36,14 @@ public class TileRendererManager { private Graph graph; - public TileRendererManager(Graph graph) { + public TileRendererManager(Graph graph, RoutingRequest routingRequest) { this.graph = graph; // Register layers. renderers.put("bike-safety", new EdgeVertexTileRenderer(new BikeSafetyEdgeRenderer())); renderers.put("traversal", new EdgeVertexTileRenderer( new TraversalPermissionsEdgeRenderer())); - renderers.put("wheelchair", new EdgeVertexTileRenderer(new WheelchairEdgeRenderer())); + renderers.put("wheelchair", new EdgeVertexTileRenderer(new WheelchairEdgeRenderer(routingRequest))); } public void registerRenderer(String layer, TileRenderer tileRenderer) { diff --git a/src/main/java/org/opentripplanner/inspector/WheelchairEdgeRenderer.java b/src/main/java/org/opentripplanner/inspector/WheelchairEdgeRenderer.java index 2e372a46a49..dbe5d72c930 100644 --- a/src/main/java/org/opentripplanner/inspector/WheelchairEdgeRenderer.java +++ b/src/main/java/org/opentripplanner/inspector/WheelchairEdgeRenderer.java @@ -1,6 +1,7 @@ package org.opentripplanner.inspector; import org.opentripplanner.inspector.EdgeVertexTileRenderer.EdgeVertexRenderer; +import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.edgetype.StreetEdge; import org.opentripplanner.routing.graph.Edge; import org.opentripplanner.routing.graph.Vertex; @@ -16,7 +17,7 @@ public class WheelchairEdgeRenderer implements EdgeVertexRenderer { - private ScalarColorPalette slopePalette = new DefaultScalarColorPalette(0.0, 0.08, 1.0); + private ScalarColorPalette slopePalette; private static final Color NO_WHEELCHAIR_COLOR = Color.RED; @@ -24,7 +25,8 @@ public class WheelchairEdgeRenderer implements EdgeVertexRenderer { private static final Color NO_WHEELCHAIR_INFORMATION_COLOR = Color.ORANGE; - public WheelchairEdgeRenderer() { + public WheelchairEdgeRenderer(RoutingRequest routingRequest) { + this.slopePalette = new DefaultScalarColorPalette(0.0, routingRequest.maxSlope, 1.0); } @Override diff --git a/src/main/java/org/opentripplanner/standalone/Router.java b/src/main/java/org/opentripplanner/standalone/Router.java index d3826778fe4..515556fdd95 100644 --- a/src/main/java/org/opentripplanner/standalone/Router.java +++ b/src/main/java/org/opentripplanner/standalone/Router.java @@ -80,8 +80,6 @@ public Router(String id, Graph graph) { */ public void startup(JsonNode config) { - this.tileRendererManager = new TileRendererManager(this.graph); - // Analyst Modules FIXME make these optional based on JSON? { this.tileCache = new TileCache(this.graph); @@ -101,6 +99,8 @@ public void startup(JsonNode config) { this.defaultRoutingRequest = new RoutingRequest(); } + this.tileRendererManager = new TileRendererManager(this.graph, this.defaultRoutingRequest); + /* Apply single timeout. */ JsonNode timeout = config.get("timeout"); if (timeout != null) {