Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add escalator reluctance parameter #5046

Merged
merged 36 commits into from Jul 10, 2023

Conversation

nurmAV
Copy link
Contributor

@nurmAV nurmAV commented Apr 13, 2023

Summary

This PR adds a new parameter escalatorReluctance so that escalators can be treated differently than regular stairs in routing.
Also disables bicycle walking in escalators.

Unit tests

Write a few words on how the new code is tested.

The changes were tested manually

Documentation

The parameter escalatorReluctance was added to documentation

@nurmAV nurmAV requested a review from a team as a code owner April 13, 2023 13:09
@nurmAV nurmAV changed the title Escalator reluctance Add escalator reluctance parameter Apr 13, 2023
@leonardehrenfried
Copy link
Member

We discussed this at today's dev meeting and we have come to the conclusion that we want to have a meeting to come up with a plan for further features around the StreetEdge first. @optionsome will fill you in.

@leonardehrenfried leonardehrenfried marked this pull request as draft April 18, 2023 08:18
Copy link
Member

@optionsome optionsome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this issue today in a meeting and came to the conclusion that we should at least try to implement this as a EscalatorEdge instead of using the StreetEdge with escalator flag as the StreetEdge implements BikeWalkableEdge and it makes no sense in this case and the StreetEdge is already a big file so adding more logic into it is not ideal. Contrary to what I suggested in a private message a couple of weeks ago, we shouldn't create a BikeUnwalkableEdge but instead put the logic directly into EscalatorEdge.

@leonardehrenfried suggested that we should also ideally handle the other conveying tag values listed in https://wiki.openstreetmap.org/wiki/Key:conveying to handle one way escalators. conveying:reversible and conveying:yes should be handled both as bidirectional.

) {
if (edgeIsStairs) {
return pref.walk().stairsReluctance();
} else if (edgeIsEscalator) {
if (traverseMode == TraverseMode.BICYCLE) return Double.POSITIVE_INFINITY;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't use really high cost but instead prevent "bicycle walking" and cycling in escalators completely.

@t2gran t2gran added this to the 2.4 milestone Apr 24, 2023
@nurmAV nurmAV marked this pull request as ready for review May 23, 2023 12:08
Copy link
Member

@optionsome optionsome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quickly tested this and it did seem to work so that only walking works. However, it also allowed traversal on wheelchairs which is wrong. The traversal permission map layer on the debug client showed the escalators as link (or maybe the edge was completely missing there). That code should be updated so it renders these edges with escalator text and maybe pink color like the stairs.

return (
"steps".equals(osmWay.getTag("highway")) &&
osmWay.getTag("conveying") != null &&
Set.of("yes", "forward", "backward", "reversible").contains(osmWay.getTag("conveying"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should set the escalator as one directional when the value is either forward or backward. There are probably some examples how it's done for one way streets in code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think you should have the method in the OSM way for checking if the way is an escalator (like you already have but slightly modify it).

/**
* Contains the logic for extracting elevators out of OSM data
*/
class EscalatorProcessor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure if having an processor that goes through all the ways is the best solution or having some common top level processor for each way that then delegates the handling to separate processor based on some information. We can discuss this at a dev meeting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it makes sense not to go through all the ways for the escalators separately if it can be avoided. This could probably be done in the same function that generates the street edges as well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could move the code that generates the StreetEdges into an own class (or classes) from the OsmModule and just initialize these processors in the OsmModule. I think you can iterate over the ways there and then just call either buildEscalatorEdge or buildStreetEdge method from one of those processor depending when is appropriate for the way.

@@ -252,7 +259,9 @@ private void buildBasicGraph() {
params.banDiscouragedBiking(),
issueStore
);
if (!OsmFilter.isWayRoutable(way) || permissions.allowsNothing()) continue;
if (
!OsmFilter.isWayRoutable(way) || permissions.allowsNothing() || way.hasTag("conveying")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to use the isEscalator method here as well from the OSMWay class. Also, wrap the continue with {} and put it on an own line (I know it was like this before but it shouldn't be).

private WalkPreferences() {
this.speed = 1.33;
this.reluctance = 2.0;
this.boardCost = 60 * 10;
this.stairsReluctance = 2.0;
this.stairsTimeFactor = 3.0;
this.safetyFactor = 1.0;
this.escalatorReluctance = 2.0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this value should be lower. Not quite sure what though. Kinda weird that the default for reluctance and stairsReluctance are the same. Maybe the stairsReluctance is added on top of the normal reluctance but I'm not sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We investigated the stairsReluctance a bit in the dev meeting and the cost comes from both the stairsReluctance and the stairsTimeFactor so the default reluctance value is probably approriate as is.

For the escalatorReluctance, maybe set this default value as 1.5.

@Override
public State[] traverse(State s0) {
// Only allow traversal by walking
if (s0.getNonTransitMode() == TraverseMode.WALK) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the getNonTransitMode WALK also when one is walking a bicycle or BICYCLE. Maybe it's just some flag set in the state data and the mode is still BICYCLE. I'm not sure. We should also block traversal on wheelchairs here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We think that the getNonTransitMode returns BICYCLE even when walking a bicycle so this code is probably right but the wheelchair should still be blocked somehow (there are probably examples in the street edge).

// Only allow traversal by walking
if (s0.getNonTransitMode() == TraverseMode.WALK) {
var s1 = s0.edit(this);
var time = getDistanceMeters() / s0.getPreferences().walk().speed();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should consider that walk speed preference here at all? We could just have some static (maybe configurable) speed. I wonder if the speed is ever set through tagging in OSM.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could try to search the internet if you can find what is usually the horizontal velocity of escalators and just use that as a static speed for the escalator instead of using the walk speed from preferences.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs to be done.

@@ -778,6 +778,7 @@ private static void mapWalkPreferences(NodeAdapter c, WalkPreferences.Builder wa
"Value should be between 0 and 1." + " If the value is set to be 0, safety is ignored."
)
.asDouble(dft.safetyFactor())
);
)
.withEscalatorReluctance(c.of("escalatorReluctance").asDouble(dft.escalatorReluctance()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import org.opentripplanner.street.search.state.State;

/** Represents an escalator. An escalator edge can only be traversed by walking */
public class EscalatorEdge extends Edge {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test for this class. You can use PathwayEdgeTest as a template.

Co-authored-by: Joel Lappalainen <lappalj8@gmail.com>
@codecov
Copy link

codecov bot commented May 25, 2023

Codecov Report

Patch coverage: 75.32% and project coverage change: -0.02 ⚠️

Comparison is base (de5c168) 65.60% compared to head (4d870cc) 65.59%.

Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #5046      +/-   ##
=============================================
- Coverage      65.60%   65.59%   -0.02%     
- Complexity     14656    14668      +12     
=============================================
  Files           1765     1767       +2     
  Lines          68455    68521      +66     
  Branches        7280     7291      +11     
=============================================
+ Hits           44911    44947      +36     
- Misses         21055    21078      +23     
- Partials        2489     2496       +7     
Impacted Files Coverage Δ
...er/graph_builder/module/osm/ElevatorProcessor.java 54.43% <0.00%> (-2.54%) ⬇️
...ector/raster/TraversalPermissionsEdgeRenderer.java 14.49% <0.00%> (-0.66%) ⬇️
.../opentripplanner/street/model/edge/StreetEdge.java 86.96% <ø> (ø)
...rg/opentripplanner/openstreetmap/model/OSMWay.java 85.36% <50.00%> (-6.07%) ⬇️
...r/graph_builder/module/osm/EscalatorProcessor.java 64.00% <64.00%> (ø)
...outing/api/request/preference/WalkPreferences.java 85.10% <90.00%> (+0.40%) ⬆️
...entripplanner/street/model/edge/EscalatorEdge.java 92.30% <92.30%> (ø)
...ripplanner/graph_builder/module/osm/OsmModule.java 92.94% <100.00%> (+0.17%) ⬆️
...dalone/config/routerequest/RouteRequestConfig.java 97.83% <100.00%> (+0.02%) ⬆️

... and 4 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@leonardehrenfried
Copy link
Member

@nurmAV I did a refactoring which will allow you to remove the EscalatorProcessor and be a lot more efficient.

@nurmAV
Copy link
Contributor Author

nurmAV commented Jun 29, 2023

On top of my review comments, you also need to regenerate the documentation.

Is there some command for this? I'm a bit confused by this error as when I run mvn test locally, the tests pass and it looks like to me that neither of the expected or found lines match the line in the actual document (RouteRequest line 575)

@leonardehrenfried
Copy link
Member

CI merges your branch and dev-2.x. It might be that that is the problem. To solve it merge dev-2.x into this branch and run mvn test.

@@ -22,6 +22,7 @@ name.ramp=Auffahrrampe
name.link=Verbindung
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last request: please add a default translation for English. Then I'm happy to approve.


class EscalatorEdgeTest {

Graph graph = new Graph();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Graph graph = new Graph();

You can remove the graph completely.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this and I will approve.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

optionsome
optionsome previously approved these changes Jul 10, 2023
optionsome
optionsome previously approved these changes Jul 10, 2023
@optionsome optionsome dismissed stale reviews from leonardehrenfried and themself via 4d870cc July 10, 2023 11:30
@optionsome optionsome merged commit fb8a777 into opentripplanner:dev-2.x Jul 10, 2023
5 checks passed
@optionsome optionsome deleted the escalator-reluctance branch July 10, 2023 12:13
t2gran pushed a commit that referenced this pull request Jul 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants