Better escalator duration control: specific duration from OSM duration tag, default speed from build-config.json - #6268
Conversation
|
Will be a draft until I have completed my full-program manual testing. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #6268 +/- ##
=============================================
+ Coverage 69.71% 69.79% +0.07%
- Complexity 17698 17816 +118
=============================================
Files 2008 2020 +12
Lines 75830 76221 +391
Branches 7764 7799 +35
=============================================
+ Hits 52868 53201 +333
- Misses 20248 20308 +60
+ Partials 2714 2712 -2 ☔ View full report in Codecov by Sentry. |
| .asInt(dftElevator.hopTime()) | ||
| ); | ||
| }) | ||
| .withEscalator(escalator -> { |
There was a problem hiding this comment.
If you add an example here: https://github.com/opentripplanner/OpenTripPlanner/blob/198ed907d1c5daf48349c205cdb443f0d0c7dfec/application/src/test/resources/standalone/config/router-config.json it will show up in the documentation.
leonardehrenfried
left a comment
There was a problem hiding this comment.
This is a good PR but I've picked up on a few things.
| * @return Duration | ||
| * @throws DateTimeParseException on bad input | ||
| */ | ||
| public static Duration parseClockDuration(String duration) { |
There was a problem hiding this comment.
I wonder if we need this or could we just use Duration.between(LocalTime.MIN, LocalTime.parse(duration))? The parse function probably accepts more formats that what is in theory allowed by OSM tagging.
There was a problem hiding this comment.
There are also factories in the data API to create custom parsers - we do not need this.
There was a problem hiding this comment.
Joel also wanted to use Duration.between(LocalTime.MIN, LocalTime.parse(duration, DateTimeFormatter.ISO_LOCAL_TIME)), which I guess will probably work ok for durations smaller than 24 hours. But the format specified in https://wiki.openstreetmap.org/wiki/Key:duration does not limit the duration to under 24 hours, which is of course irrelevant for the escalator use case, but if we ever want to recycle the duration tag parsing code for other durations, it might become relevant. Let's go through this in today's meeting.
There was a problem hiding this comment.
But now I noticed that my implementation is against the spec anyway. It specifies that the duration is either mm, hh:mm or hh:mm:ss. Not hh, hh:mm or hh:mm:ss as I implemented it.
There was a problem hiding this comment.
Anyway, the fact that the supported formats are mm, hh:mm, and hh:mm:ss means that there has to be a place for the switch off the number of colons somewhere, even if the branches use some ready-made parser. I'll bring this up in the meeting as well.
There was a problem hiding this comment.
DateTimeFormatterBuilder will not work for this. It has the capability for expressing optional parts, so it could express hh(:mm(:ss)?)? but it cannot express (hh:)?mm(:ss)? where the existence of (:ss) implies the existence of (hh:). Even if it did, it would not be able to handle the cases where hours are greater than 23 or (if there is no hours part at all) minutes are greater than 59, which are both allowed by the spec and exist in OSM data. Durations are not LocalTimes after all, in parsing a LocalTime it makes sense and is correct that hours cannot be more than 23 or minutes more than 59, but in durations if you have capped the largest unit, it is reasonable for the amount of the largest unit to be as large as it needs to be.
I did rewrite the parsing to be quite explicit in what it accepts, so its correctness should be obvious.
|
While going through the comments, I noticed our ElevatorEdge implementation uses the OSM tag duration as an integer number of seconds, which is just wrong, compared to the duration tag spec. We couldn't even find an elevator tagged like this anywhere. |
| issueStore.add( | ||
| Issue.issue( | ||
| "InvalidDuration", | ||
| "Duration for osm node %d is not a valid duration: '%s'; it's replaced with 'Optional.empty()' (unknown).", |
There was a problem hiding this comment.
I think you could use a link to OSM instead of just referencing the id (nodes have url() method). Also, the "it's replaced with 'Optional.empty()'" is too technical for the issue report. Instead you could just say something like "the value is ignored".
| issueStore.add( | ||
| Issue.issue( | ||
| "InvalidDuration", | ||
| "Duration for osm node {} makes implied speed {} be outside acceptable range.", |
leonardehrenfried
left a comment
There was a problem hiding this comment.
I approve this. The typo I can fix after the merge.
…hTags.java Co-authored-by: Leonard Ehrenfried <mail@leonard.io>
ffffb13
Summary
Escalator durations tend too high. This PR makes it possible to use duration=hh:mm:ss tag in OSM data to set the duration accurately. It also makes it possible to set a configuration-wide speed in build-config.json at routingDefaults.escalatorSpeed.
Issue
None.
Unit tests
New case in EscalatorEdgeTest: if a duration is set for the edge, it takes precedence over a calculated duration.
Documentation
doc/user/RouteRequest.md has been autogenerated
Changelog
Definitely will be included in changelog.
Bumping the serialization version id
No