Add cyclist position availability fields to VehiclePosition and CarriageDetails#611
Draft
oliver-sturrock wants to merge 1 commit intogoogle:masterfrom
Draft
Conversation
…ageDetails Add four new experimental fields to enable real-time reporting of bicycle rack/storage availability on transit vehicles: - VehiclePosition.cyclist_positions_available (field 12) - VehiclePosition.total_cyclist_positions (field 13) - CarriageDetails.cyclist_positions_available (field 6) - CarriageDetails.total_cyclist_positions (field 7) These fields allow transit apps to display bike rack availability alongside existing vehicle position and occupancy information. A working producer implementation (Sportworks Global LLC Velolink) is live at https://cascadia-metro-gtfs-rt.sportworks.com/gtfs-rt/vehicle-positions and has been validated against protoc, Python gtfs-realtime-bindings, and Node.js gtfs-realtime-bindings.
|
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). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Collaborator
|
Hello @oliver-sturrock, and thank you for this proposal. According to the GTFS Realtime governance process, we typically start by reaching community consensus on an Issue regarding the field's usefulness and type. A Pull Request follows once consensus is reached. Since you’ve opened both, I suggest moving this PR to draft for now so we can focus the discussion on the Issue first. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #610
Summary
This proposal adds two new experimental fields to the
VehiclePositionandCarriageDetailsmessages to enable real-time reporting of bicycle rack/storage availability on transit vehicles.Proposed Fields
cyclist_positions_availableuint32VehiclePosition,CarriageDetailstotal_cyclist_positionsuint32VehiclePosition,CarriageDetailsMotivation
Transit passengers traveling with bicycles currently have no way to know whether a bike rack or bike storage area will be available on an approaching vehicle. A typical transit bus has only 2–3 external bike rack positions, and when full, cyclists are denied boarding — they must wait for the next vehicle or abandon their transit trip entirely.
This is a documented and quantified problem:
Providing this data in GTFS-RT enables trip planning applications (Transit App, Google Maps, Apple Maps) to display bike rack availability alongside existing vehicle position and occupancy information.
Working Implementation
Producer: Sportworks Global LLC — Velolink — a commercially available bike rack occupancy monitoring system deployed on transit buses. Velolink uses magnetic reed switches embedded in Sportworks Apex-3 bike racks to detect individual slot occupancy in real-time, transmitting data via cellular modem to a cloud platform with a public API.
https://cascadia-metro-gtfs-rt.sportworks.com/gtfs-rt/vehicle-positions— live VehiclePositions feed includingcyclist_positions_available(field 12) andtotal_cyclist_positions(field 13)https://cascadia-metro-gtfs-rt.sportworks.com/gtfs-rt/gtfs.zipConsumer: [TO BE CONFIRMED — we are actively reaching out to Transit App, Swiftly, OpenTripPlanner, Google Maps, and Apple Maps to secure a consumer implementation before calling for a vote.] Example consumer: https://cascadia-metro-gtfs-rt.sportworks.com/consumer
Ecosystem Validation Results
The public GTFS-RT feed has been tested against all major ecosystem tools. All 11 tests pass:
/validate)protoc --decode_rawprotoc --decode(official proto)protoc --decode(extended proto)cyclist_positions_availableandtotal_cyclist_positionsnamedgtfs-realtime-bindings2.0.0gtfs-realtime-bindings0x60/0x68tags correct, all values in boundsAccess-Control-Allow-Origin: *on all endpointsForward Compatibility
Adding
optional uint32fields is a fully forward-compatible change under proto2 semantics:UnknownFieldSetand preservedXXX_unrecognizedand preservedThis is the same pattern used when
occupancy_status(field 9),occupancy_percentage(field 10), andmulti_carriage_details(field 11) were previously added to the specification.Design Decisions
Why separate
availableandtotalfields?This mirrors the existing pattern of
occupancy_statusalongsideoccupancy_percentage. For cyclist positions:cyclist_positions_availableprovides the real-time signal consumers need ("2 of 3 bike spots open")total_cyclist_positionsprovides the capacity context needed for meaningful displayWhy
uint32instead of an enum?Cyclist positions are discrete, low-count integers (typically 2–3 on buses, 4–10 per train car). An exact count is more useful than a qualitative classification, and the low cardinality makes exact counts practical.
Why both VehiclePosition and CarriageDetails?
Absence vs. zero semantics
Following GTFS-RT conventions:
Privacy Considerations
A typical bus has 2–3 bike rack positions. Sequential occupancy changes could theoretically identify an individual cyclist boarding. However:
OccupancyStatusvalues on small vehiclesExample: Bus with Apex-3 Bike Rack
entity { id: "vehicle_4403" vehicle { trip { trip_id: "trip_22_1045" route_id: "22" direction_id: 0 } position { latitude: 37.3382 longitude: -121.8863 } occupancy_status: FEW_SEATS_AVAILABLE cyclist_positions_available: 1 # 1 of 3 rack slots open total_cyclist_positions: 3 # Apex-3 rack = 3 slots } }Example: Multi-Car Train
entity { id: "vehicle_lrv_101" vehicle { cyclist_positions_available: 5 # Vehicle-level total total_cyclist_positions: 8 multi_carriage_details { id: "car_A" carriage_sequence: 1 cyclist_positions_available: 2 total_cyclist_positions: 4 } multi_carriage_details { id: "car_B" carriage_sequence: 2 # No cyclist fields — no bike storage } multi_carriage_details { id: "car_C" carriage_sequence: 3 cyclist_positions_available: 3 total_cyclist_positions: 4 } } }Checklist
.protofile with correct field numbersContact
Oliver Sturrock
olst+gtfs@silverfallscapital.com
(425) 358-9055
Sportworks Global LLC / Silver Falls Capital