GTFS direction_id on loops

Use of the GTFS direction_id field for trips is optional, but it’s also helpful to have, as it can make it easier to display the data and analyze it. However, the present specification for direction_id doesn’t work well for trips which change direction mid-trip, as is the case for trains or buses which operate around a loop.

Not all loops are problematic. If there’s only one station on the loop, as is the case on PATH at the World Trade Center, then what a train crew might regard as a continuous trip from Newark to World Trade Center and back can be scheduled as two separate trips—one from Newark to World Trade Center, and one from World Trade Center to Newark. One direction gets direction_id 0, and the other gets direction_id 1.

But what if there are multiple stations on the loop, as is the case with The Loop in Chicago? Within the Loop, certain services only operate in one direction—either clockwise or counterclockwise—so there’s no need to distinguish between trips in different directions. Moreover, unlike on PATH, trains don’t terminate on the Loop—it’s a continuous trip all the way around. On the Pink Line, for example, trains only run around the Loop clockwise. But at Ashland/Lake (a station on the portion of the Pink Line outside the Loop), the service most definitely operates in two directions, and there there’s a need to distinguish between the directions.

What’s the solution? I would propose the use of a third value for the direction_id field. The two existing values, 0 and 1, have no pre-defined meaning, but are often used to designate opposing geographic directions. A third value (presumably 2) could be used to indicate uni-directional service on an ordinarily bi-directional route. That’s only part of the solution, though, since presently direction_id is set per-trip. Curiously, headsigns can be set for trips, or for individual stoptimes, where the headsign changes mid-trip.

If the headsign can change mid-trip, why can’t the direction? So, direction_id should be treated in the same manner as the headsign—if it’s the same for every stop on a trip, then set it in the trip. But if it changes mid-trip, then omit the field from the trip definition, and set it for each stoptime individually.