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

transfer rules for routes and trips, and in-seat transfers #32

Conversation

antrim
Copy link
Contributor

@antrim antrim commented Nov 26, 2016

Updates [see below discussion]:

  • agency.disallow_block_transfer field proposal has been removed.
  • change Spec reference so that block transfers are not assumed by default

@antrim
Copy link
Contributor Author

antrim commented Nov 26, 2016

Notes and justification for proposal:

  1. Some feed publishers with to specify trip-to-trip and route-to-route transfers. Google Maps has defined this in a GTFS extension, which is incorporated here: https://developers.google.com/transit/gtfs/reference/gtfs-extensions#TripToTripTransfers
  2. Current interpretations of block_id are inconsistent. Real-time prediction systems such as Transitime require block_id, but the current GTFS assumes that in-seat transfers are always allowed. The new field agency.disallow_block_transfer and new values for transfer.transfer_type, 4 and 5 would allow overriding this default. This feature would work with the trip-to-trip and route-to-route transfer capabilities.
  3. For backwards-compatibility, block transfers (in-seat transfers) are assumed to be allowed unless overriding parameters are set.

@antrim
Copy link
Contributor Author

antrim commented Dec 1, 2016

Does anyone have comments on these proposed changes? Since there are changes in a few files addressing a few issues, there is more here to think about than with some other recent proposed changes.

@barbeau
Copy link
Collaborator

barbeau commented Dec 1, 2016

@antrim Please remind me - do we have existing consumers and producers for this?

@antrim
Copy link
Contributor Author

antrim commented Dec 1, 2016 via email

@mgilligan
Copy link

+1

@abyrd
Copy link

abyrd commented Dec 1, 2016

OpenTripPlanner uses this GTFS extension (see https://github.com/opentripplanner/OpenTripPlanner/blob/master/src/main/java/org/opentripplanner/routing/core/TransferTable.java#L69), as does Google Maps. @antrim reports that Trillium is generating these transfers and I thought that OpenOV did for the Netherlands, but I don't see them in a recent feed. @skinkie are you still generating transfers with trip/stop/route specificity?

About "disallow block transfers" and the corresponding transfer types, I talked to someone at TriMet about this and they were in fact fine with exhaustively listing out all the allowed block transfers in their feed. It is going to be confusing to have some feeds that assume block transfers are allowed (where you have to individually disallow them) and other feeds that assume they are not allowed (where you have to individually enable them). I'm leaning toward just requiring all block transfers to be allowed individually, and if no such transfers are present in the feed, but block IDs are in use, then the consumer can take a guess at what that means.

@antrim
Copy link
Contributor Author

antrim commented Dec 1, 2016

Trillium is actually not yet producing these transfer types. We could very quickly add support for transfer_type = {4,5} but it would take more time to add route-to-route and trip-to-trip transfers because we will probably wait a month or two while transitioning to an overhauled version of the GTFS Manager software.

quoting @abyrd:

It is going to be confusing to have some feeds that assume block transfers are allowed (where you have to individually disallow them) and other feeds that assume they are not allowed (where you have to individually enable them).

I proposed a default value of 0 (NO) for the new agency.disallow_block_transfer field. This was designed to support backward compatibility with the spec today -- block transfers are assumed to be allowed unless otherwise specified.

@abyrd
Copy link

abyrd commented Dec 2, 2016

I should have been more clear. This proposal is really two different things. First, route-to-route and trip-to-trip transfers. Trillium, OTP, Google, and OpenOV (I believe) are already using this. Second, better handling of in-seat transfers, for which nothing has been implemented yet.

After all the mailing list and personal discussion, I would propose doing this a different way than previously suggested. In my view, in-seat transfers should never be assumed, and all in-seat transfers should be enumerated in transfers.txt using the trip-to-trip or route-to-route mechanism. Block_ids would only imply that a vehicle was passing from one trip to the next, and would only be relevant for consumers propagating real-time data. This means we only need one new transfer type (4) for adding an in-seat transfer.

In the event that a feed has no in-seat transfers listed but has block_ids, the GTFS consumer might want to infer that some in-seat transfers exist but this would be a heuristic based on knowledge about a particular agency, not a standardized behavior.

I'm aware that this could be considered breaking backward compatibility, but I don't get the sense that there was ever strong agreement on how this feature was supposed to work.

@DaveBarker
Copy link

+1 to the overall proposal and to abyrd's recommendation of approach that in-seat transfers should never be assumed.

@skinkie
Copy link
Contributor

skinkie commented Dec 4, 2016

are you still generating transfers with trip/stop/route specificity?

Yes, and also for FlixBus.

@antrim
Copy link
Contributor Author

antrim commented Jan 3, 2017

I changed the proposal so that in-seat transfers are not assumed -- disallowed by default. This can be set with the new agency.block_transfer_default field. 0e149ca

@abyrd
Copy link

abyrd commented Jan 18, 2017

@antrim do we ever want to enable blanket block transfers using agency.block_transfer_default ? It doesn't seem clear that this should be enabled at the feed, agency, or route level, and I don't personally think this deserves cluttering the spec with a new field. Any agency technically sophisticated enough to consider using block IDs to communicate in-seat transfer availability can probably also pull off the transfers.txt approach.

@antrim
Copy link
Contributor Author

antrim commented Jan 22, 2017

@abyrd : We could remove the disallow_block_transfer.

However, my reasoning for block_transfer_default was that it allows any feed publisher that had assumed block transfers are allowed to publish a new feed that is consistent with the amended spec by adding only one field.

In public Trillium feeds that are provided to trip planners, we presently assume that block transfers are always allowed. This is consistent with how the Spec is written. For arrival prediction software, we actually have a function to provide different feeds (technically not Spec compliant) with block_id values for all trips (including where in-seat transfer is not allowed).

Trillium can quickly change the way we are publishing feeds. I worry that some other feed publishers assumed block transfers and it will take time for them to catch up with the Spec. I propose that we provide opportunity for a broader scan of practice.

For convenient reference, this was the proposed added field in agency.txt.

Field Name Required Details
disallow_block_transfer Optional Specifies whether in-seat transfers are allowed by default for the agency (see block_id field in trips.txt). Overriding parameters are specified in transfers.txt.
* 0 or (empty) - In-seat transfers are disallowed unless an override is set in transfers.txt. This is the default behavior.
* 1 - In-seat transfers are allowed unless an override is set in transfers.txt.

@abyrd
Copy link

abyrd commented Jan 23, 2017

I am mainly concerned about the proliferation of rarely-used fields that exist only for historical reasons, or to preserve backward compatibility when all producers are prepared to accept a small change in semantics to yield a new, clearer specification. Among the main benefits of GTFS are its simplicity and pragmatic approach. There should not be many different ways to represent the same thing, and special fields only used by one operator somewhere.

So ultimately this is going to depend on feedback from feed producers. We should also search for concrete examples of agencies that allow in-seat block transfers across their network. Do we have examples of this in the wild?

@antrim
Copy link
Contributor Author

antrim commented Jan 26, 2017

@abyrd @mgilligan : Point taken. I removed the proposed agency.block_transfer_default field. This aimed to provide a convenient bridge to forwards-compatibility, but would create Spec baggage, confusion, and burden over the long term.

@dbabramov dbabramov added GTFS Schedule Issues and Pull Requests that focus on GTFS Schedule Non-Backward-Compatible labels Mar 2, 2017
| | | * **3** - Transfers are not possible between routes at this location. |
| | | * **3** - Transfers are not possible. |
| | | * **4** - Passengers can transfer from one route to another by staying onboard the same vehicle (an "in-seat transfer") in cases where sequential trips are made by the same vehicle (same block_id). In-seat transfer between these two stops / routes / trips is allowed. |
| | | * **5** - In-seat transfers are not allowed between sequential trips with the same block ID. The passenger must alight from the vehicle and re-board. |
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose we should remove transfer_type=5 because in-seat transfers are disallowed by default with this current version.

@googlebot
Copy link
Collaborator

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.


  • If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address. Check your existing CLA data and verify that your email is set on your git commits.
  • If you signed the CLA as a corporation, please let us know the company's name.

@antrim
Copy link
Contributor Author

antrim commented May 22, 2017

I signed it!

@antrim
Copy link
Contributor Author

antrim commented May 22, 2017

Summary of the latest proposal - 4b77a2d.

Original motivation

It is not presently possible to specify blocks for all trips (useful for arrival prediction software) AND to precisely specify in-seat transfer availability. The original (and currently published) Spec defines that "A block consists of two or more sequential trips made using the same vehicle, where a passenger can transfer from one trip to the next just by staying in the vehicle." (at developers.google.com)

What the proposal accomplishes

  • Maintains backwards compatibility with the current Spec: in-seat transfers are allowed by default. (We could therefore remove the "non-backward-compatible" label from this pull request.)
  • Allows changing the default of whether in-seat transfers are allowed for an agency
  • Provide for granular control of in-seat transfers (by stop, trip, and route)

Why the 360° turn back to the original proposal?

Off-list discussion has brought up the need for backwards compatibility, given the number of feeds that presently follow the spec and are integrated in present systems. This is an attempt to minimize disruption to existing feed producers and consumers.

[Update: Sep 16, 2020] Here is a link to a Slack conversation in 2017 that shows of the research on block_id practices from the time.

Suggested path forward

Let's continue to discuss on GitHub for as long as it takes to arrive at a solution. Given that this has lingered for some time (and the original motivating problem has not been solved), I suggest we attempt to limit discussion to 2 weeks from today before bringing this proposal, or any revised proposal, to a vote.

Copy link
Collaborator

@barbeau barbeau left a comment

Choose a reason for hiding this comment

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

I'm a +1 on this proposal as current proposed in 4b77a2d, but this PR needs to be updated before it can be merged.

@antrim Looks like some changes unrelated to this proposal snuck into this pull request - I'm flagging them here so they don't accidentally get merged. You should be able to get rid of these updating your local branch to the google/transit master, creating a new branch temp from the updated master branch, and then git cherry-pick 4b77a2da51a74f1362df577bb6771e46bc04dc4d to pull 4b77a2d into your temp branch and then force pushing to your Github remote branch transfers-inseat_and_trips/routes with git push -f origin temp:transfers-inseat_and_trips/routes (hopefully I got that syntax right). Just be aware that the force-push will destroy whatever is currently in this PR, so keep a local backup if you're unsure of exactly what will happen. We've all been bitten by Git at least once ;).

@@ -19,7 +19,6 @@ The official specification, reference and documentation are written in English.
If a voter changes her vote, it is recommended to do it by updating the original vote comment by striking through the vote and writing the new vote.
- Votes before the start of the voting period are not considered.
1. The proposal is accepted if there is a unanimous consensus yes with at least 3 votes.
- The proposer's vote does not count towards the 3 vote total. For example, if Proposer X creates a pull request and votes yes, and User Y and Z vote yes, this is counted as 2 total yes votes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

gtfs/CHANGES.md Outdated
@@ -5,22 +5,20 @@ The official specification, reference and documentation are written in English.

1. Create a git branch with update of all relevant parts of protocol definition, specification and documentation files (except for translations).
1. Create pull request on https://github.com/google/transit. Pull request must contain an extended description of the patch. The creator of the pull request becomes the _advocate_.
1. Once pull request is registered, it must be announced by its advocate in the [GTFS Changes mailing list](https://groups.google.com/forum/#!forum/gtfs-changes), including a link to the pull request. Once announced, the pull request is considered a proposal. The pull request should also be edited to contain a link to the Google Groups announcement so they can easily be cross-referenced.
1. Once pull request is registered, it must be announced by its advocate in the [GTFS Changes mailing list](https://groups.google.com/forum/#!forum/gtfs-changes). Once announced, the pull request is considered a proposal.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

gtfs/CHANGES.md Outdated
- Since the advocate is a contributor, they must sign the [Contributor License Agreement](../CONTRIBUTING.md) before pull request can be accepted.
1. The discussion of the proposal follows. Pull request comments should be used as the sole discussion forum.
- The discussion lasts for as long as the advocate feels necessary, but must be at least 7 calendar days.
- The advocate is responsible for timely update of the proposal (i.e. pull request) based on the comments for which they agree to.
- At any point in time the advocate can claim proposal abandoned.
1. The advocate can call for a vote on a version of the proposal at any point in time following the initial 7-day interval required for discussion.
- Before calling for a vote, at least one GTFS producer and one GTFS consumer should implement the proposed change. It is expected that the GTFS producer(s) include the change in a public-facing GTFS feed and provide a link to that data within the pull request comments, and that the GTFS consumer(s) provides a link in the pull request comments to an application that is utilizing the change in a non-trivial manner (i.e, it is supporting new or improved functionality).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

gtfs/CHANGES.md Outdated
1. Vote lasts the minimum period sufficient to cover 7 full calendar days and 5 full Swiss business days. Vote ends at 23:59:59 UTC.
- The advocate should announce the specific end time at the start of the vote.
- During voting period only editorial changes to the proposal are allowed (typos, wording may change as long as it does not change the meaning).
- Anyone is allowed to vote yes/no in a form of comment to the pull request, and votes can be changed until the end of the voting period.
If a voter changes her vote, it is recommended to do it by updating the original vote comment by striking through the vote and writing the new vote.
- Votes before the start of the voting period are not considered.
1. The proposal is accepted if there is a unanimous consensus yes with at least 3 votes.
- The proposer's vote does not count towards the 3 vote total. For example, if Proposer X creates a pull request and votes yes, and User Y and Z vote yes, this is counted as 2 total yes votes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

gtfs/CHANGES.md Outdated
@@ -31,7 +29,6 @@ The official specification, reference and documentation are written in English.
- Google is committed to merging the voted upon version of the pull request (provided that the contributors have signed the [CLA](../CONTRIBUTING.md)), and performing the pull request within 5 business days.
- Translations must not be included into the original pull request.
Google is responsible for eventually updating relevant translations into supported languages, but pure translation pull requests from the community are welcome and will be accepted as soon as all editorial comments are addressed.
1. The final result of the pull request (accepted or abandoned) should be announced on the same Google Groups thread where the pull request was originally announced.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

@@ -348,8 +329,6 @@ For examples that demonstrate how to specify a fare structure with fare_rules.tx

File: **Optional**

Shapes describe the physical path that a vehicle takes, and are defined in the file shapes.txt. Shapes belong to Trips, and consist of a sequence of points. Tracing the points in order provides the path of the vehicle. The points do not need to match stop locations.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

@@ -384,8 +363,8 @@ This table is intended to represent schedules that don't have a fixed list of st
| Field Name | Required | Details |
| ------ | ------ | ------ |
| trip_id | **Required** | The **trip_id** contains an ID that identifies a trip on which the specified frequency of service applies. Trip IDs are referenced from the [trips.txt](#tripstxt) file. |
| start_time | **Required** | The **start_time** field specifies the time at which the first vehicle departs from the first stop of the trip with the specified frequency. The time is measured from "noon minus 12h" (effectively midnight, except for days on which daylight savings time changes occur) at the beginning of the service day. For times occurring after midnight, enter the time as a value greater than 24:00:00 in HH:MM:SS local time for the day on which the trip schedule begins. E.g. 25:35:00. |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

@@ -405,14 +384,35 @@ Trip planners normally calculate transfer points based on the relative proximity
| ------ | ------ | ------ |
| from_stop_id | **Required** | The **from_stop_id** field contains a stop ID that identifies a stop or station where a connection between routes begins. Stop IDs are referenced from the [stops.txt](#stopstxt) file. If the stop ID refers to a station that contains multiple stops, this transfer rule applies to all stops in that station. |
| to_stop_id | **Required** | The **to_stop_id** field contains a stop ID that identifies a stop or station where a connection between routes ends. Stop IDs are referenced from the [stops.txt](#stopstxt) file. If the stop ID refers to a station that contains multiple stops, this transfer rule applies to all stops in that station. |
| from_route_id | **Optional** | The from_route_id field can contain a route_id (as specified by [routes.txt](#routestxt)), reducing the scope to which the given transfer applies. If from_route_id is specified, the transfer will only apply to the arriving trip with the given route id, at the given from_stop_id. |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @barbeau : The additional transfer types are intended to be part of this proposal/PR. If block transfers are turned off by default for an agency (as many agencies will likely choose), then they will also need a way to override and allow block transfers in specific cases.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, thanks - makes sense.

| transfer_type | **Required** | The **transfer_type** field specifies the type of connection for the specified (from_stop_id, to_stop_id) pair. Valid values for this field are: |
| | | * **0** or **(empty)** - This is a recommended transfer point between two routes. |
| | | * **1** - This is a timed transfer point between two routes. The departing vehicle is expected to wait for the arriving one, with sufficient time for a passenger to transfer between routes. |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Intentional to provide additional capabilities to manage transfers broadly, and block transfers as a subset.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, right - gotcha.

| min_transfer_time | Optional | When a connection between routes requires an amount of time between arrival and departure (transfer_type=2), the **min_transfer_time** field defines the amount of time that must be available in an itinerary to permit a transfer between routes at these stops. The min_transfer_time must be sufficient to permit a typical rider to move between the two stops, including buffer time to allow for schedule variance on each route. |
| | | The min_transfer_time value must be entered in seconds, and must be a non-negative integer. |

**Specificity of a transfer**
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated to this proposal - needs to be removed from PR.

@antrim antrim force-pushed the transfers-inseat_and_trips/routes branch from 4b77a2d to 03a4592 Compare May 30, 2017 06:02
@antrim
Copy link
Contributor Author

antrim commented May 30, 2017

@barbeau Your instructions worked perfectly. Thank you. The proposed changes are now all in 03a4592.
.

@devinbraun
Copy link

@antrim We can make the change block_transfer_default immediately as our block_ids are vehicle tasks (for real-time information) and aren't specific to in-seat transfers which we don't allow except if it's another trip on the same route (for example, a looping route). We can add in the route-to-route in-seat transfers to transfers.txt for those few routes where it is allowed.

@davidlattimore
Copy link

Something I had been thinking about, that's related to this, is when two trips share a block_id, but the later trip starts from a different stop than the earlier trip finishes. Currently Google still allows an in-seat transfer. I'm wondering however if perhaps it shouldn't. I've observed at least some data providers that have given us such trips who didn't intend for them to be in-seat transfers.

GTFS best practices says:

If in-seat (block) transfers are allowed between trips, then the last stop of the arriving trip must be the same as the first stop of the departing trip.

I wonder what proportion of unwanted in-seat transfers would go away if we only allowed in-seat transfers when the last/first stops matched up.

Regardless of the more explicit rules in this proposal as to whether in-seat transfers are allowed, it'd be good to clarify the expected behavior when the stops don't match. Is it an error? Is it OK, but in-seat transfers are disallowed, even if the default is to allow them? The best practices doc seems to suggest the latter.

Also, there's still a Non-Backwards-Compatible label on this pull request. My impression is that it's no longer required, right?

@antrim
Copy link
Contributor Author

antrim commented Jul 29, 2019

tl;dr: Should we even allow blocked trips where the last stop of the earlier trip is different than the first stop of the subsequent trip? This strikes me as problematic and unnecessary. Longer discussion below.

Quoting @davidlattimore :

Something I had been thinking about, that's related to this, is when two trips share a block_id, but the later trip starts from a different stop than the earlier trip finishes. Currently Google still allows an in-seat transfer. I'm wondering however if perhaps it shouldn't. I've observed at least some data providers that have given us such trips who didn't intend for them to be in-seat transfers.

Question to all -- particularly feed producers: What would be the purpose of specifying subsequent trips where the later trip starts from a different stop than the earlier trip finishes at? @davidlattimore: Are there particular feeds you can point to that do this?

How should a feed consumer interpret a case where the last stop of the earlier (blocked) trip and first stop of the subsequent trip are different? This strikes me as problematic, especially in cases where a real-time system is consuming the GTFS. Opinions / insights?: @scrudden @mike-swiftly @barbeau @nselikoff

If the vehicle goes into non-revenue service, that can be represented in GTFS (see Best Practices RE deadhead trips: https://gtfs.org/best-practices/#stop_timestxt).

@skinkie
Copy link
Contributor

skinkie commented Jul 29, 2019

Should we even allow blocked trips where the last stop of the earlier trip is different than the first stop of the subsequent trip? This strikes me as problematic and unnecessary. Longer discussion below.

If Trip 1 ends at a drop-off only stop, and Trip 2 starts at the pick-up that is, in The Netherlands at least, a very common situation to get disembarking passengers as close to the train station entrance as possible, while picking up new passengers at a dedicated platform. The block will not start and end in the same stop.

@davidlattimore
Copy link

Sure. Here's a couple of feeds:
https://bkk.hu/gtfs/budapest_gtfs.zip
http://opendata.tec-wl.be/Current%20GTFS/TEC-GTFS.zip
I have no idea if they're representative. Both have a mix of block transfers where the first and last stop match and ones that don't.

@skinkie
Copy link
Contributor

skinkie commented Jul 30, 2019

@antrim a compromise might be to state that a block should end and begin at the same parent station. Given the entrances proposal, every station will get one anyway.

@mike-swiftly
Copy link

mike-swiftly commented Aug 15, 2019 via email

@abyrd
Copy link

abyrd commented Aug 16, 2019

Thanks @mike-swiftly. It also seems completely normal to me to allow in-seat transfers between sequential trips in blocks, independent of whether the last stop of trip 1 is the first stop of trip 2. I would expect this to be very common, and maybe even the most common case (any time route 2 begins at a stop a bit farther down the road from where route 1 ends).

I am not sure what we would accomplish by creating more rules about when in-seat transfers are allowed or not. It seems like any such set of more complicated heuristics would give better results for certain agencies and worse results for others, while requiring every consumer to implement more complex code, so I'd prefer the simplest possible behavior. When the broad backward-compatible default is used to enable in-seat transfers, I would expect in-seat transfers to then exist after every trip within each block. Each consumer could perhaps implement a few sanity-check heuristics of their own design for good measure, but such things should not be part of the spec.

If a producer needs to communicate more nuanced information they can disable in-seat transfers by default and employ transfer_type 4. Based on input in the comments above about existing feeds, we do need a field creating backward-compatible behavior, and allowing producers to switch that behavior off and use transfer_type 4.

@abyrd
Copy link

abyrd commented Aug 16, 2019

I have just re-read most of the comments and the current content of the pull request. I'm still quite supportive of having a way to individually enable in-seat transfers, using transfers.txt. Some comments on the current state of the proposal:

transfer_type 4 and block_id

The text describing transfer_type 4 should be updated to clarify the reference to block_id. To me, block_ids do not seem relevant when a producer is listing individual transfers instead of using the backward-compatible block-based default in-seat transfer behavior. Also, consider that the block_id field only exists for trips. This PR allows transfer_type 4 transfers to be created between routes or stops, not just trips, in which case that transfer should (?) still be available to the rider even in the absence of block_ids. Alternatively, if you really do want to enforce creation of in-seat transfers only between trips with the same block_id even when the enabling transfers.txt entry is between stops or routes, then this behavior needs to be very clearly defined in the spec, including a description of what happens when trips do not have defined block_ids but are nonetheless tied together by a transfer_type 4 transfer. Some additional information should also be given clarifying whether the transfer_type 4 only applies when it connects the last stop of the first trip to the first stop of the next trip (i.e. what if the transfer is between stops that are not at the end of a trip).

My proposed system (which of course needs scrutiny from other people) is this: When default in-seat transfers are enabled, in-seat transfers are available after every trip in every block, with no restrictions. Whether or not this default is enabled, transfers with the new transfer type have the same function: they allow in-seat transfers from the final stop of all trips that meet its from_stop_id, from_route_id, and from_trip_id criteria, toward the initial stop of all trips that meet its to_stop_id, to_route_id, and to_trip_id criteria, with no regard to block_ids at all. In this way, the new transfer_type can be used to exhaustively specify all in-seat transfers, or to augment default in-seat transfers inferred from block_ids.

It definitely makes sense for a producer using transfer_type 4 to still include block_ids for realtime propagation purposes, but how block_id meaning and effect changes in response to the default in-seat transfer flag must be clearly described.

transfer_type 5

I am thinking transfer_type 5 should be eliminated. This leaves only two modes of operation: default in-seat transfers enabled, augmented by any transfer_type 4 transfers; or default in-seat transfers disabled, with all in-seat transfers exhaustively listed with transfer_type 4. Since the mode with default in-seat transfers enabled exists primarily for backward compatibility, I am hesitant about additional complexity allowing producers to subtractively pare down the full default set of in-seat transfers.

@gcamp
Copy link
Contributor

gcamp commented Sep 13, 2019

I tried to read as much as possible from this proposition and comments, but I didn't read everything. I'm sorry if I'm repeating discussion that happened before.

My biggest problem with block_id is how they are hard to interpret since they can change depending on the current service day, which is a pain (see this example). The trip to trip transfer solves this.

My proposition would be to actually deprecate completely block_id and replace it with trip to trip with transfers type 4 and 5. If block_id are deprecated, that also means we can remove the block_transfer_default value. from_route_id and to_route_id are also not required in this PR and can be moved to an other proposition.

If that makes sense for everybody we can implement this fairly quickly in Transit. We can also potentially open source a convertor that transforms GTFSs with block_ids with GTFSs with trip to trip transfers. I know this is a big change, but in my opinion it would really clarify the spec and reduce the amount of potential bugs in both producers and consumers.

For those interested, we came to this conclusion because we are actually fixing bugs in our block_id support (bug that is basically the example from the spec). Our final solution was basically have a first step of transformation of block_id to trip to trip transfers inspired by this proposition to simplify processing later on. Instead of duplicating work, we could just share our transformation step and hopefully become part of the spec.

@skinkie
Copy link
Contributor

skinkie commented Sep 13, 2019

@gcamp I consider this certainly a very good direction to go to. Considering how blocks in GTFS never represent what they are in more complex systems downstream unless all data is denormalised. But I do want to suggest something that I hope you could take in a account. Would your consider adding an optional service_id to the trip_to_trip transfers?

@gcamp
Copy link
Contributor

gcamp commented Sep 14, 2019

@skinkie could you have the same trip to trip transfer with multiple service_id? You want that to avoid duplication of trips just to create different continuations?

In our case we would want to duplicate the trip anyway to simplify storage of trip to trip transfers, but that can be done on our side. If this reduce size and complexity a lot for producers, that's something we can support.

@skinkie
Copy link
Contributor

skinkie commented Sep 14, 2019

@gcamp I indeed want to prevent that new trips are created (while the internal trip identifiers are equal) that on certain dates will not share the same block id therefore would not have that trip-to-trip transfer.

@gcamp
Copy link
Contributor

gcamp commented Sep 23, 2019

Bump on proposition above ☝️

@paulswartz
Copy link
Contributor

Would this deprecate block_id only for in-seat transfers, or entirely? I imagine it is still useful for consumers to know that two different trips are scheduled to be provided by the same vehicle.

@gcamp
Copy link
Contributor

gcamp commented Sep 24, 2019

@paulswartz I would deprecate entirely. If the producer wants to provide the information about two different trips are provided by the same vehicle could do so with a trip to trip transfer type = 5.

@paulswartz
Copy link
Contributor

@gcamp

@paulswartz I would deprecate entirely. If the producer wants to provide the information about two different trips are provided by the same vehicle could do so with a trip to trip transfer type = 5.

Hmm: our current GTFS has ~85k trips on ~5k blocks; that's a lot of trip-to-trip transfers to add to the file. But if that's what the consensus is, we can make it work.

@stale
Copy link

stale bot commented Aug 21, 2021

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.

@stale stale bot added the Status: Stale Issues and Pull Requests that have remained inactive for 30 calendar days or more. label Aug 21, 2021
@gcamp
Copy link
Contributor

gcamp commented Aug 25, 2021

My proposition above is still valid on my side. It's one of the next thing we want to improve in our backend.

@stale stale bot removed the Status: Stale Issues and Pull Requests that have remained inactive for 30 calendar days or more. label Aug 25, 2021
@antrim
Copy link
Contributor Author

antrim commented Sep 15, 2021

Closing this PR. This function is covered in #278.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GTFS Schedule Issues and Pull Requests that focus on GTFS Schedule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet