-
Notifications
You must be signed in to change notification settings - Fork 1.1k
GTFS flex support: flag stops, deviated-route service, call-and-ride #2603
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
Conversation
(cherry picked from commit d0ae263)
version and maven updates for camsys dev Initial commit for transfers. Partial PatternHop edges for hop-to-stop transfers Fix transfer heuristics initial work to get backwards transfers (stop->hop) to work backwards transfers should work now
This reverts commit d0c503a.
…s going the wrong way (since we are peds) - this solves bug in VGF-1
… transit boarding. Some refactoring to support this.
…t, which will prevent flag stops from being generated. Add extra check.
…order to do this cleanly, needed to ensure that ALL temporary vertices get added to rctx.temporaryVertices. The temporary subgraph of both endpoints is searched at routing context-creation time. The graph is searched again when the vertices are disposed.
…were added, then removed with Graph.remove)
|
I merged the Temporary Vertex cleanup code, extended it to work with GTFS-Flex, and added checks to ensure that only TemporaryEdges created by a particular request are used. The approach is:
@t2gran I'd appreciate your thoughts on this since it changes your fix in #2655 a bit! I think this is that last part of the PR that will require more code changes if there are concerns. Aside from this, I've got more documentation to do. |
…nd get rid of redundant excludeWalking parameter
|
I added more documentation, including a new overview page for GTFS-Flex. Open for comments! @thomastrillium, if you want to take a look: https://github.com/opentripplanner/OpenTripPlanner/blob/a275257a6afc8cfc3fd2f6d7bd8cafb0f1633b79/docs/Flex.md @abyrd, you've asked a few times about the distinction between "flexible" service and "demand-response transit" (DRT). "Flexible" transit is anything that's defined in the GTFS-Flex spec. I think DRT is specifically off-route flexible transit, e.g. call-and-ride and deviated-route. But in this PR, the word "DRT" only appears when it's part of a term that comes from the spec. For example, |
|
Thanks @sdjacobs for all the additional Javadoc and user documentation. Looks good. I now understand that the terms Flex and DRT are coming from the Flex spec, and it makes sense to follow the conventions and terms defined in that spec. We may need to add more definitions to the Flex spec. I'm a little hesitant about the combined temporary vertex/edge removal approach - if we're explicitly recording all the created temporary objects so we can remove them one by one, it seems strange to use a graph search to find them instead of just registering them when they're created. But I recognize that we can't change / fix everything at once. @t2gran if you approve of this combined approach we can leave any simplification for a subsequent refactor. I'm also hesitant about the method of avoiding temporary objects in threads other than the one that created them. We originally used a similar approach for avoiding temporary origin/destination edges in threads that shouldn't see them, but eliminated that approach it in favor of just making it topologically impossible for those temporary edges to be on successful paths in other threads (e.g. starting vertices only have edges leading out of them, so no search can enter them). It gives me pause to see active tracking and avoidance of temporary edges return to OTP because it introduces another type-checking conditional into every edge traversal (which may have performance implications as an inner loop "hot spot"), and because there are now more chances for the creation and removal of these temporary objects to be interleaved in unexpected ways with searches attempting to access them, e.g. another thread can be trying to access the incoming edges of a temporary vertex at exactly the moment those edges are removed. Critically, it might be able to access them as part of non-dead-end paths that actually lead toward the destination. The use of copy-on-write edge lists should continue to minimize these problems, but I'm not as convinced as with the topological avoidance approach. Also, if we're returning to active tracking and avoidance we should question why we are applying two different approaches, one to endpoint temporary objects and one to Flex temporary objects. If we are reverting to an older method of tracking (and removal) for Flex temporary objects, should we continue simultaneously using different methods for origin/destination temporary objects? Unfortunately these effects are not fully confined to Flex searches: a new conditional is hit on every traversal of an edge in every search. I discussed the current state of this whole PR with @t2gran a few days ago. We agreed that the PR plus all the changes are getting large enough that it's increasingly hard to have a full understanding of what we're merging. Most or all of the review comments have been addressed though, so the practical way forward is to merge this PR and then revise later if we spot any more things that need attention. We also discussed two main concerns about this PR, the depth of which only became apparent after working on it for a while:
All that said, we do want to get this merged without dragging it out longer, and incremental change can happen after the merge if needed. This is destined for the |
|
I just adjusted the PR base to |
|
Thanks Andrew. I share your concerns, but for the most part I agree that the path forward is to merge and address issues as they come up. For temporary edges, the changes I made are to track and remove ALL TemporaryEdges and to check they if they were created by the proper request on every edge traversal. A more conservative approach would be to keep the existing (solely topological, no tracking) behavior for all non-flex edges and only track-check-remove for flex TemporaryEdges. (The fundamental problem is that flex TemporaryEdges, as implemented, are not topologically impossible for a separate request to access, and they are not discoverable by the
The implementation above is more verbose than the current state of the PR, and it moves back toward treating flex TemporaryEdges and non-flex TemporaryEdges differently. But, it keeps existing behavior the same and avoids the possible inner loop hot spot. Would folks prefer the above? I believe I have some similar code in a branch from when I was experimenting with this, so it would not be much trouble to switch. In any case, once we determine what the solution in the PR is, I'll create an issue to come back to the TemporaryEdge problem and determine a better long-term solution. |
There is another much simpler option with the same resource-consumption characteristics as the current system in this PR: we could just not add temporary edges and vertices to the graph at all. The method that fetches the outgoing or incoming edges of a vertex would then check the main graph (shared between all threads) as well as a map in the request context (known only to the current thread) to find additional temporary edges. This has been done in the past in OTP and it works, it was just eliminated as part of other changes over the years because on the surface it looks inefficient. But this inefficiency is just one additional hash lookup per Dijkstra iteration, on a very small table that is likely to remain in processor cache, which is the same additional work created by the current approach in this PR. With the solution I describe above, we don't need to track and delete temporary objects at all because only request-scoped objects have references to them, and they are invisible to the shared graph. They are just garbage collected when the request is finished. It's a significant change but in many ways much less fragile and complicated. Instead of inserting objects into a complicated data structure shared across threads and detecting when to ignore them, we just don't add them to the shared data structure, and detect when to make them visible. Ideally we would prototype and profile this before accepting it, to determine whether it causes significant slowdown. Although if we need to profile my proposed approach, we should also profile the one currently in the PR because they add roughly the same amount of extra computation. |
I'm hesitant to make such a huge change as I just described as part of this PR. So I'd prefer to merge this one, then improve the temporary edge handling in a subsequent step. A problem I foresee though is that if we make the big temporary edge handling change, I'd like it to apply to both 1.x and 2.x, and after merging this PR, 1.x and 2.x will have diverged significantly. |
|
@abyrd I agree to let this PR pass and fix the temporary vertex problem in its own Issue/PR. I don't think it will be that difficult to merge such PR into 2.x (even with a lot of changes). I will mark my latest review as resovled, since it is on stuff that will be deleted or refactored anyway. I just want to keep the comments in case we decide to keep some of it. |
src/main/java/org/opentripplanner/routing/vertextype/TemporaryVertex.java
Show resolved
Hide resolved
src/main/java/org/opentripplanner/routing/vertextype/TemporaryVertex.java
Show resolved
Hide resolved
src/main/java/org/opentripplanner/routing/vertextype/TemporaryVertexDispose.java
Show resolved
Hide resolved
src/main/java/org/opentripplanner/routing/vertextype/TemporaryVertexDispose.java
Show resolved
Hide resolved
src/test/java/org/opentripplanner/routing/flex/VermontFlexRoutingTest.java
Show resolved
Hide resolved
|
All: sounds like there's sufficient agreement to merge now. Thanks to everyone for sticking with this review and for Simon for making many rounds of improvements. @sdjacobs can you resolve the current merge conflicts? Afterwards go ahead and merge, if you have permissions, or if not, let me know and I can do it. |
|
Actually @sdjacobs and @drewda please do not merge this PR immediately. I am intentionally finalizing and merging a round of small PRs into I'm not talking about a long wait, I imagine we should be able to merge this PR by next week. You may want to wait until all those smaller changes are merged into 1.x before resolving merge conflicts between 1.x and this branch - though I don't expect there to be many new conflicts. |
|
@abyrd O.K. Can you put together a checklist of the "small PRs into |
|
Yes @drewda, good idea to make a checklist. I think I've got everything merged except for the following two:
In fact #2714 builds upon #2700, so if someone can test routing results from #2714 that should allow approval of both PRs. Someone should be able to check out branch |
|
@abyrd great, thanks for the (short) list. Let's aim to ideally resolve those blockers by the end of next week. |
As part of the US DOT's Mobility on Demand Sandbox Grant, we added support for flexible transit to OpenTripPlanner, based on the emerging GTFS-flex spec. This work was done on behalf of VTrans, the Vermont Department of Transportation.
It includes:
The GTFS flex specification is available here.
The overall implementation is to run a "graph modifier" before the main graph search which does some preliminary graph searches around the origin and destination in order to create temporary edges and vertices to represent the flex options, which are disposed of after the request.
The VTrans project required a few other changes to be made to OTP which are not included in this PR:
This is currently usable via VTrans's website here: https://plan.govermont.org/