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

In seat transfers #4

Closed
wants to merge 14 commits into from
Closed

In seat transfers #4

wants to merge 14 commits into from

Conversation

gcamp
Copy link
Member

@gcamp gcamp commented Nov 24, 2021

This PR adds new transfer_types for trip to trip transfers to define if a user can do an "in seat transfer" when the same vehicle is operating two consecutive trips and the user can stay onboard. In addition, the transfer type can define when in-seat transfers aren't allowed but can link together two different trips operationally.

Why are in-seat transfers useful? Why is vehicle operational information on trips useful?

Some transit systems have in-seat transfers as a core concept on how their system functions. It's also not an edge case or a lightly used feature. It's core to how Trimet, King County Metro1, and others function. With the current definition of block_id, those feeds are not representing their systems correctly.

On the other hand, it's also useful to know how a vehicle continues between trips. The main use case is to help create predictions of vehicle arrival at the start of the trip. Without knowing the link between trips, it's not possible to propagate delay information. This is used by at least Transit and Swiftly for prediction creation, and probably much more I don't know.

I thought block_ids represented this information?

Before Jan 21, 2017, block_id in GTFS would represent in-seat transfers while ignoring the operational-only functionalities. After google#44, the definition was changed to represent the "same vehicle" operational definition and ignored the in-seat transfer feature. Confusion about what functionality block_id was present before that change, but that change didn't help.

Currently, Google Maps is still using block_id under the pre-2017 definition of in-seat transfers (Googlers can correct me if I'm wrong). At Transit, we try to deduce via heuristics if block_id represent an in-seat transfer or not, with varying success. I'm assuming other consumers are doing something similar since in-seat transfers are so important in some markets it can't be ignored.

Shouldn't the in-seat transfers be based on block_id?

There are multiple problems of the current block_id as implemented currently

  • Some information is lost and needs to be reconstructed by consumers. The producer knows the order of trips inside a block which is lost when using block_id.
  • "Block" often refers to a driver assignation. However what the spec is asking for is vehicle information, creating confusion.
  • Ambiguity around how block_id works across different service requires lengthy explanations. This interpretation across services is both error prone on the producer side and hard to implement on the consumer side. Some more ambiguity still exists around midnight when the service day changes (should it continue or not?).

Why use transfer_type?

The recent addition of trip to trip transfers in the spec allows us to make the type of transfer explicit. The idea of using transfer_type actually comes from @antrim from an old PR google#32.

In addition

  • It provides in-seat transfer information, absent from block_id.
  • It makes a clear distinction between transfers where riders can stay on board and transfers where riders cannot stay on board while not duplicating that information.
  • It makes trip continuations explicit without any reconstructing of information.
  • It allows producers and consumers of block_ids to still use it in parallel.

A downside of this approach is that it's more data heavy. However, data consumers are already required to recreate this data themselves anyway.

Transit open-sourced a converter from block_id to trip-to-trip transfers : GTFS-blocks-to-transfers. Data examples are also available in that repo. We intend to only use trip-to-trip transfers in our internal GTFS representation.

Footnotes

  1. Notice the "to route" mention on the right

@@ -380,7 +382,7 @@ For a given ordered pair of arriving trip and departing trip, the transfer with
| `to_route_id` | Foreign ID referencing `routes.route_id` | Optional | Identifies a route where a connection ends.<br><br>If `to_route_id` is defined, the transfer will apply to the departing trip on the route for the given `to_stop_id`.<br><br>If both `to_trip_id` and `to_route_id` are defined, the `trip_id` must belong to the `route_id`, and `to_trip_id` will take precedence. |
| `from_trip_id` | Foreign ID referencing `trips.trip_id` | Optional | Identifies a trip where a connection between routes begins.<br><br>If `from_trip_id` is defined, the transfer will apply to the arriving trip for the given `from_stop_id`.<br><br>If both `from_trip_id` and `from_route_id` are defined, the `trip_id` must belong to the `route_id`, and `from_trip_id` will take precedence. |
| `to_trip_id` | Foreign ID referencing `trips.trip_id` | Optional | Identifies a trip where a connection between routes ends.<br><br>If `to_trip_id` is defined, the transfer will apply to the departing trip for the given `to_stop_id`.<br><br>If both `to_trip_id` and `to_route_id` are defined, the `trip_id` must belong to the `route_id`, and `to_trip_id` will take precedence. |
| `transfer_type` | Enum | **Required** | Indicates the type of connection for the specified (`from_stop_id`, `to_stop_id`) pair. Valid options are:<br><br> `0` or empty - Recommended transfer point between routes.<br>`1` - Timed transfer point between two routes. The departing vehicle is expected to wait for the arriving one and leave sufficient time for a rider to transfer between routes.<br>`2` - Transfer requires a minimum amount of time between arrival and departure to ensure a connection. The time required to transfer is specified by `min_transfer_time`.<br>`3` - Transfers are not possible between routes at the location. |
| `transfer_type` | Enum | **Required** | Indicates the type of connection for the specified (`from_stop_id`, `to_stop_id`) pair. Valid options are:<br><br> `0` or empty - Recommended transfer point between routes.<br>`1` - Timed transfer point between two routes. The departing vehicle is expected to wait for the arriving one and leave sufficient time for a rider to transfer between routes.<br>`2` - Transfer requires a minimum amount of time between arrival and departure to ensure a connection. The time required to transfer is specified by `min_transfer_time`.<br>`3` - Transfers are not possible between routes at the location.<br>`4` - Passengers can transfer from one trip to another by staying onboard the same vehicle (an "in-seat transfer"). Using this transfer type REQUIRES that the the two trips linked are operated by the same vehicle. When using this type of transfer, it's REQUIRED that both `from_trip_id` and `to_trip_id` values are set. Additionally, the last stop of `from_trip_id` SHOULD be geographically close from the first stop `to_trip_id` and the last arrival time of `from_trip_id` SHOULD be close to the first departure time of `to_trip_id`. <br>`5` - In-seat transfers are not allowed between sequential trips. The passenger must alight from the vehicle and re-board. Using this transfer type REQUIRES that the the two trips linked are operated by the same vehicle. When using this type of transfer, it's REQUIRED that both `from_trip_id` and `to_trip_id` values are set. Additionally, the last stop of `from_trip_id` SHOULD be geographically close from the first stop `to_trip_id` and the last arrival time of `from_trip_id` SHOULD be close to the first departure time of `to_trip_id`. |
Copy link
Member

Choose a reason for hiding this comment

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

for the specified (from_stop_id, to_stop_id, from_trip_id, to_trip_id, from_route_id, to_route_id) pair.

Choose a reason for hiding this comment

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

When using this type of transfer, it's REQUIRED that both from_trip_id and to_trip_id values are set.

IMHO, this sentence should be removed from the definitions of enum 4&5. The fields from_trip_id and to_trip_id should become conditionally required instead (required with enum 4&5, optional otherwise), as well as the fields from_stop_id and to_stop_id (required with enum -,0,1,2,3 and optional otherwise)

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point @timMillet. Updated. Didn't touch stop_ids because trip transfers are also valid with the other types. (Anyway probably out of scope for this PR?)

@jsteelz
Copy link
Member

jsteelz commented Nov 25, 2021

We should provide an example using the new transfer specification

@@ -378,9 +378,9 @@ For a given ordered pair of arriving trip and departing trip, the transfer with
| `to_stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies a stop or station where a connection between routes ends. If this field refers to a station, the transfer rule applies to all child stops. |
Copy link

@hannesj hannesj Dec 4, 2021

Choose a reason for hiding this comment

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

Should this and the from_stop_id be required to be of type stop, and not a station, when the transfer type is 4 or 5?

@BodoMinea
Copy link

If my (and a few MobilityData Slack colleagues') interpretation of this suggestion is correct, we could represent trips partially merging or vehicles otherwise coupling/decoupling between trips and allowing riders to make different in-seat-transfers. This could be simply achieved by defining from_trip_id, to_trip_id AND from_stop_id, to_stop_id with transfer_type=4.

This is my crude illustration of this intricate use case:
image

The dotted line means that trip B may continue to a different destination after attaching only some if its carriages to the now long consist of trip C.

Given the potentially confusing nature of this type of transfer (although usually when these kinds of things are done, the headsign displays/papers on the sides of the carriages are clear enough for passengers), maybe a free-text field „naming” or „describing” the specific transfer vehicle configuration or limitation could work (indicating that car 2B facilitates this specific in-seat transfer to the linked trip for example) - as such providing information to users beforehand and making it possible to board directly the appropriate carriage / wait in the appropriate platform segment/zone.

In my view, the required change in your documentation would be from Using this transfer type REQUIRES that the the two trips linked are operated by the same vehicle. to Using this transfer type REQUIRES that the the two trips linked are operated by the same vehicle or a subset of the same carriages that form the consist. Or something to that extent, if you think this change is benefic maybe you could try wording it better.

This also means, in my opinion, that any validation regarding to this types of transfers should consider stop-time subsets when checking for invalid overlaps and not whole trips' timeframe.

I understand that it will be more data-intensive to represent in-seat transfers in this way but it looks like the only comprehensive enough way and would allow for configurations that are invalid/impossible as described by the current GTFS spec.

@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale label Jan 12, 2022
@github-actions
Copy link

This pull request has been closed due to inactivity. Pull requests can always be reopened after they have been closed. See the Specification Amendment Process.

@github-actions github-actions bot closed this Jan 20, 2022
@npaun npaun reopened this Jan 25, 2022
@gcamp gcamp closed this Jan 26, 2022
@gcamp gcamp deleted the in-seat-transfers branch January 26, 2022 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants