-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix missing transfers #7042
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
Fix missing transfers #7042
Conversation
|
We are using this feature for GTFS feeds so this is a concern to us. The original feature, which is part of the 2.8.1 release, works in both GTFS and NeTEx. |
1f1c0c5 to
2dadef6
Compare
…and PatternConsideringNearbyStopFinder
…smaller responsibilities
…ing, causing the the best transfer alternative to be dropped.
…etuned false for the last stop. + Improve documentation and deprecate canAlight(StopLocation) and canBoard(StopLocation) methods
…ansferToString utility
2dadef6 to
0348616
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #7042 +/- ##
=============================================
+ Coverage 72.29% 72.31% +0.02%
- Complexity 20182 20217 +35
=============================================
Files 2189 2192 +3
Lines 81217 81288 +71
Branches 8140 8147 +7
=============================================
+ Hits 58712 58784 +72
Misses 19630 19630
+ Partials 2875 2874 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
leonardehrenfried
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are few things I would like a clarification on.
1bd0f38 to
3df0b60
Compare
|
Please resolve the conflicts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old feature is replaced by a new one that currently supports only NeTEx. Does it mean loss of functionality for GTFS-based deployments?
application/src/main/java/org/opentripplanner/transit/model/network/StopPattern.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/opentripplanner/transit/model/site/RegularStop.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/opentripplanner/framework/application/OTPFeature.java
Outdated
Show resolved
Hide resolved
.../java/org/opentripplanner/graph_builder/module/transfer/filter/FlexTripNearbyStopFilter.java
Show resolved
Hide resolved
...java/org/opentripplanner/graph_builder/module/transfer/filter/CompositeNearbyStopFilter.java
Show resolved
Hide resolved
...opentripplanner/graph_builder/module/transfer/filter/PatternConsideringNearbyStopFinder.java
Show resolved
Hide resolved
...n/java/org/opentripplanner/graph_builder/module/transfer/filter/PatternNearbyStopFilter.java
Show resolved
Hide resolved
I missed that there is an extension in GTFS that set the |
ebc15ef to
7afaba1
Compare
7afaba1 to
73a22ad
Compare
| var repository = DirectTransferGeneratorTestData.of() | ||
| .withTransferRequests(REQUEST_WITH_WALK_TRANSFER) | ||
| .build(); | ||
| // S0 <-> S23 is too fare, not found in neardby search |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // S0 <-> S23 is too fare, not found in neardby search | |
| // S0 <-> S23 is too far, not found in nearby search |
| * @return {@code true} if this stop may be used by real-time trips despite having no scheduled | ||
| * patterns, {@code false} otherwise | ||
| */ | ||
| public boolean isSometimesUsedRealtime() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to start a linguistic argument, but sometimesUsesRealtime is already correct English.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you could drop the is prefix.
leonardehrenfried
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already good to go, IMO, but I noticed a few tiny things that you may want to consider. I will approve once Vincent does.
leonardehrenfried
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you wish, you can apply my changes but that's not required.
Summary
This PR fixes critical bugs in transfer generation that could cause missing transfers and incorrect routing results. It also refactors the transfer generation code for better maintainability and improves support for stops used in real-time updates.
The PR addresses two critical bugs:
StopPattern.canAlight()was always returning false for valid alighting stops at the last stop in a stop patterntransfersNotAllowedstops after pattern filtering, causing valid transfer alternatives to be droppedAdditionally, the PR refactors the pattern-based filtering logic into smaller, more focused classes and renames the
IncludeEmptyRailStopsInTransfersfeature toIncludeStopsUsedRealtimeInTransferswith improved semantics.Issue
Fixes #7013
Critical Bug Fixes
StopPattern.canAlight() Logic Error
The
StopPattern.canAlight(StopLocation stop)method had a critical copy-paste bug where it was skipping the last stop instead of the first stop:Result: The method would always return
falsefor the last stop in a pattern, even though that's typically where passengers SHOULD be able to alight.The fix corrects the loop to skip the first stop instead:
Impact: This bug caused the last stop in patterns to be incorrectly excluded from transfer generation, potentially resulting in missing transfers, longer journeys, or no route found.
Missing Transfers Due to Filtering Order
In
DirectTransferGenerator, stops withtransfersNotAllowed()were being filtered out AFTER pattern filtering. This caused valid transfer alternatives to be dropped when the closest stop on a pattern hadtransfersNotAllowedset, even though there might be other nearby stops on the same pattern that should be included.The fix moves the
transfersNotAllowed()check to occur BEFORE pattern/flex filtering inPatternConsideringNearbyStopFinder:Impact: This ensures that pattern filtering can select alternative stops when the closest stop is not available for transfers.
Architecture Improvements
Transfer Module Organization
Moved
DirectTransferGeneratorfromgraph_builder.moduletograph_builder.module.transferto better organize transfer-related code.Filter Architecture Refactoring
Split the monolithic
PatternConsideringNearbyStopFinderinto a cleaner architecture with separated concerns:New classes:
NearbyStopFilter(interface) - Defines the contract for filtering nearby stopsPatternNearbyStopFilter- Filters stops based on trip patterns (boarding/alighting rules)FlexTripNearbyStopFilter- Filters stops based on flex trip availabilityCompositeNearbyStopFilter- Composes multiple filters togetherMinMap- Utility class for tracking minimum values (moved from nearbystops package)Refactored class:
PatternConsideringNearbyStopFinder- Now orchestrates the filtering process using composed filtersThis separation makes the code easier to understand, test, and extend with new filtering strategies.
Real-time Stop Support Enhancement
Feature Rename and Improved Semantics
Renamed
IncludeEmptyRailStopsInTransferstoIncludeStopsUsedRealtimeInTransferswith improved functionality:Old behavior:
New behavior:
sometimesUsedRealtimefield onRegularStopthat is set during importsometimesUsedRealtimeare included in transfer generation even without scheduled patternsRAIL_REPLACEMENT_BUS)Key Architectural Improvement
The new approach separates the identification of real-time stops (during import) from their usage in transfer generation:
sometimesUsedRealtime = truebased on mode/submodePatternNearbyStopFilterchecks thesometimesUsedRealtimeflag to include these stopsThis architecture makes it easy to extend support to GTFS feeds in the future - the transfer generation code doesn't need to change, only the import logic needs to implement the tagging for GTFS stops.
Implementation Details
Added
sometimesUsedRealtimefield toRegularStop:QuayMapper)PatternNearbyStopFilter.includeFromStop()andfilterToStops()to include these stops even without scheduled patternsIncludeStopsUsedRealtimeInTransfersfeature flag is enabledNeTEx Mapping (QuayMapper):
Transfer Generation Usage (PatternNearbyStopFilter):
Future extensibility: The same pattern can be implemented for GTFS feeds by adding similar logic to the GTFS import process. The transfer generation code already supports it - no changes needed there.
Testing
Unit Tests
canAlight()method to ensure correct behaviorDirectTransferGeneratorCarTestDirectTransferGeneratorTest.drawio.png) to illustrate test scenariosManual Testing
The changes have been validated with the existing integration tests and do not introduce performance regressions.
Documentation
doc/user/Configuration.mdwith the renamed feature flagIncludeStopsUsedRealtimeInTransfersPerformance Impact
Significant improvement in graph building performance and graph size:
When building the Norway graph, the number of transfers decreased from 651,965 to 546,892 (a reduction of ~16% or 105,073 transfers).
Why the reduction?
The improved filtering logic removes unnecessary transfers more effectively:
canAlight()logic: The bug fix ensures we only consider stops where passengers can actually alight, eliminating invalid transferstransfersNotAllowedcheck before pattern filtering prevents unnecessary computationBenefits:
Breaking Changes
The OTP feature flag has been renamed:
IncludeEmptyRailStopsInTransfersIncludeStopsUsedRealtimeInTransfersMigration steps:
Check your
otp-config.jsonfor the old feature flag:{ "otpFeatures": { "IncludeEmptyRailStopsInTransfers": true } }Update to the new name:
{ "otpFeatures": { "IncludeStopsUsedRealtimeInTransfers": true } }Behavioral changes:
RAIL_REPLACEMENT_BUS) in addition to rail stopssometimesUsedRealtime), not during transfer generationChecklist
fix-missing-tx-performance-testChangelog
Bumping the serialization version id
sometimesUsedRealtimetoRegularStopclass