Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions gtfs-realtime/proto/gtfs-realtime.proto
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,32 @@ message TripUpdate {
// NOTE: This field is still experimental, and subject to change. It may be
// formally adopted in the future.
optional int32 delay = 5;

enum WheelchairAccessible {
// The trip doesn't have information about wheelchair accessibility.
// This is the **default** behavior. If the static GTFS contains a
// _wheelchair_accessible_ value, it won't be overwritten.
NO_VALUE = 0;

// The trip has no accessibility value present.
// This value will overwrite the value from the GTFS.
UNKNOWN = 1;

// The trip is wheelchair accessible.
// This value will overwrite the value from the GTFS.
WHEELCHAIR_ACCESSIBLE = 2;

// The trip is **not** wheelchair accessible.
// This value will overwrite the value from the GTFS.
WHEELCHAIR_INACCESSIBLE = 3;

// The extensions namespace allows 3rd-party developers to extend the
// GTFS Realtime Specification in order to add and evaluate new features and
// modifications to the spec.
extensions 1000 to 1999;
}
optional WheelchairAccessible wheelchair_accessible = 6
[default = NO_VALUE];

// The extensions namespace allows 3rd-party developers to extend the
// GTFS Realtime Specification in order to add and evaluate new features and
Expand Down
15 changes: 15 additions & 0 deletions gtfs-realtime/spec/en/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Fields labeled as **experimental** are subject to change and not yet formally ad
* [StopTimeUpdate](#message-stoptimeupdate)
* [StopTimeEvent](#message-stoptimeevent)
* [ScheduleRelationship](#enum-schedulerelationship)
* [WheelchairAccessible](#enum-wheelchairaccessible)
* [VehiclePosition](#message-vehicleposition)
* [TripDescriptor](#message-tripdescriptor)
* [ScheduleRelationship](#enum-schedulerelationship-1)
Expand Down Expand Up @@ -143,6 +144,7 @@ Note that the update can describe a trip that has already completed.To this end,
| **stop_time_update** | [StopTimeUpdate](#message-stoptimeupdate) | Conditionally required | Many | Updates to StopTimes for the trip (both future, i.e., predictions, and in some cases, past ones, i.e., those that already happened). The updates must be sorted by stop_sequence, and apply for all the following stops of the trip up to the next specified stop_time_update. At least one stop_time_update must be provided for the trip unless the trip.schedule_relationship is CANCELED - if the trip is canceled, no stop_time_updates need to be provided. |
| **timestamp** | [uint64](https://developers.google.com/protocol-buffers/docs/proto#scalar) | Optional | One | Moment at which the vehicle's real-time progress was measured. In POSIX time (i.e., the number of seconds since January 1st 1970 00:00:00 UTC). |
| **delay** | [int32](https://developers.google.com/protocol-buffers/docs/proto#scalar) | Optional | One | The current schedule deviation for the trip. Delay should only be specified when the prediction is given relative to some existing schedule in GTFS.<br>Delay (in seconds) can be positive (meaning that the vehicle is late) or negative (meaning that the vehicle is ahead of schedule). Delay of 0 means that the vehicle is exactly on time.<br>Delay information in StopTimeUpdates take precedent of trip-level delay information, such that trip-level delay is only propagated until the next stop along the trip with a StopTimeUpdate delay value specified.<br>Feed providers are strongly encouraged to provide a TripUpdate.timestamp value indicating when the delay value was last updated, in order to evaluate the freshness of the data.<br>**Caution:** this field is still **experimental**, and subject to change. It may be formally adopted in the future.|
| **wheelchair_accessible** | [WheelchairAccessible](#enum-wheelchairaccessible) | Optional | One | If provided, can overwrite the *wheelchair_accessible* value from the static GTFS. |

## _message_ StopTimeEvent

Expand Down Expand Up @@ -190,6 +192,19 @@ The relation between this StopTime and the static schedule.
| **SKIPPED** | The stop is skipped, i.e., the vehicle will not stop at this stop. Arrival and departure are optional. |
| **NO_DATA** | No data is given for this stop. It indicates that there is no realtime information available. When set NO_DATA is propagated through subsequent stops so this is the recommended way of specifying from which stop you do not have realtime information. When NO_DATA is set neither arrival nor departure should be supplied. |

## _enum_ WheelchairAccessible

If a particuliar trip is accessible to wheelchair. When available, this value should overwrite the _wheelchair_accessible_ value from the static GTFS.

#### Values

| _**Value**_ | _**Comment**_ |
|-------------|---------------|
| **NO_VALUE** | The trip doesn't have information about wheelchair accessibility. This is the **default** behavior. If the static GTFS contains a _wheelchair_accessible_ value, it won't be overwritten. |
| **UNKNOWN** | The trip has no accessibility value present. This value will overwrite the value from the GTFS. |
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this really required? Why not keep it simple with NO_VALUE as UNKNOWN?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For example, if a static GTFS says trip A is wheelchair accessible, how can a trip_update changes the value to Unknown? If we drop NO_VALUE we won't support this case. Maybe this is an edge case and in the eventuality this happens the producer can put WHEELCHAIR_INACCESSIBLE instead. I don't feel too strongly on either choices.

Copy link
Contributor

@barbeau barbeau Mar 13, 2018

Choose a reason for hiding this comment

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

This is definitely confusing at first glance, but the underlying issue is that protobufs don't allow enums to have a null value. I believe this is the first enumeration in GTFS that we're overriding in GTFS-rt, and as a result we haven't had this issue before.

From https://developers.google.com/protocol-buffers/docs/javatutorial?csw=1 (emphasis mine):

optional: the field may or may not be set. If an optional field value isn't set, a default value is used. For simple types, you can specify your own default value, as we've done for the phone number type in the example. Otherwise, a system default is used: zero for numeric types, the empty string for strings, false for bools. For embedded messages, the default value is always the "default instance" or "prototype" of the message, which has none of its fields set. Calling the accessor to get the value of an optional (or required) field which has not been explicitly set always returns that field's default value.

I think it's important to support the case where the GTFS says that the trip is wheelchair accessible, but then real-time information indicates that this is unknown for some reason (UNKNOWN) - for example, let's say an accessible vehicle was scheduled to run a trip, but then it broke down and was replaced with another vehicle, and dispatch doesn't know if that vehicle is wheelchair accessible. However, it's also important to say that there is no real-time information, and therefore the GTFS value should be used (NO_VALUE), especially for backwards compatibility and GTFS-rt feeds that aren't providing this field.

@gcamp The proto3 spec says:

  • There must be a zero value, so that we can use 0 as a numeric default value.
  • The zero value needs to be the first element, for compatibility with the proto2 semantics where the first enum value is always the default.

We're currently using proto2 for GTFS-realtime, but I'm assuming we should plan for eventually moving to proto3. This means that NO_VALUE would need to be 0, which makes this even more confusing, as the enum values in GTFS-rt wouldn't match GTFS.

I'm definitely supportive of trying simpler iterative implementations first especially if we have willing producers for them, but in this case because of the above I'm wondering if we should look at a simplified version of the carriage proposal instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@barbeau Good point for proto3. We could use values from 0 to 4. Not the same numerical value compared the static GTFS, but since protobuf libraries would use the name of the value anyway I'm not sure this is a problem.

Would the carriage proposal fix those issues? The WheelchairAccessible value there doesn't have a NO_DATA and I don't think there's a way to not specify WheelchairAccessible value for a carriage if you want to specify other information.

Copy link
Contributor

@barbeau barbeau Mar 14, 2018

Choose a reason for hiding this comment

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

Not the same numerical value compared the static GTFS, but since protobuf libraries would use the name of the value anyway I'm not sure this is a problem.

Good point - in code I assume most/all protobuf libraries producing and consuming libraries would reference the enumeration name, not the ID, so maybe that's not too big of a stumbling block in software development, just confusing to read in the spec itself.

Would the carriage proposal fix those issues?

Yeah, thinking more, it doesn't. I was thinking that because CarriageDescriptor is new, we wouldn't have the overriding issue that we would with GTFS trip.wheelchair_accessible. But, we'd still have to specify some behavior for interaction between the two. Unless we make CarriageDescriptor.WheelchairAccessible required, it could be empty, in which case we have the same overriding behavior problem as the default would be chosen.

So in summary using values from 0 to 4 for TripUpdate.WheelchairAccessible enumeration seems like a reasonable approach.

Given some of the potential interaction issues with GTFS here, I'd like to see a working implementation before we vote on it. Having a producer and consumer is a requirement for calling a GTFS vote for new fields, but in the past those requirements have been relaxed for GTFS-rt given the potential cost of an agency reverting a deployed protobuf extension to the canonical protobuf after the field is approved. Instead, a field has been voted on an accepted as "experimental" (see occupancy proposal). Due to the interactions with GTFS, though, this proposal seems potentially more complicated to me.

| **WHEELCHAIR_ACCESSIBLE** | The trip is wheelchair accessible. This value will overwrite the value from the GTFS. |
| **WHEELCHAIR_INACCESSIBLE** | The trip is **not** wheelchair accessible. This value will overwrite the value from the GTFS. |

## _message_ VehiclePosition

Realtime positioning information for a given vehicle.
Expand Down