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

add runtimes.txt #42

Open
BTollison opened this issue Nov 30, 2023 · 13 comments
Open

add runtimes.txt #42

BTollison opened this issue Nov 30, 2023 · 13 comments

Comments

@BTollison
Copy link
Collaborator

BTollison commented Nov 30, 2023

The purpose of this proposal is to easily send running time information between software packages. In the current state, software must interpolate the running times from trips. However, if a trip is modified or if trips were generated with runtimes that are not "segment" based, it may be impossible to interpolate them. This is especially problematic in network planning software, where a user may want to modify trips and frequency but has no insight into when running times change during the day.

service_Id
From calendar.txt or calendar_dates.txt, runtimes are tied to a service_id to ensure that they are up to date and relevant for the selected route and trips.

  • Required

route_id
From routes.txt, route_id is used to tie the runtime back to a route if relevant. When it is left blank it is assumed to be global.

  • Conditionally required when shape_id or direction_id has a value.

direction_id
From trips.txt, direction_id is required when route_id is present to differentiate runtime direction.

shape_id
Shape_id is used to tie a runtime to a particular route_id and shape_id. If shape_id is present then route_id and direction_id should have values.

from
The from location that the runtime applies to.

  • It should be a stop_id when route_id is present or ops_location_id when is_deadhead = 1
  • To be valid for a trip, in stop_times.txt timepoint does not need to = 1, but then should instead be interpreted as where timepoint = 1 then a timepoint is public, where there is a runtime, but timepoint = 0 then that timepoint is for internal use.

to
The to location that the runtime applies to.

  • It should be a stop_id when route_id is present or ops_location_id when is_deadhead = 1
  • To be valid for a trip, in stop_times.txt timepoint does not need to = 1, but then should instead be interpreted as where timepoint = 1 then a timepoint is public, where there is a runtime, but timepoint = 0 then that timepoint is for internal use.

start_time
The start time of the period of which the runtime applies.

  • if this is blank, it is for the entire service day.

end_time
The end time of the period of which the runtime applies.

  • if this is blank, it is for the entire service day.

runtime
The amount of time it takes to travel from one point to another in seconds.

is_deadhead
Denotes if the runtime applies to in service trips or only deadhead trips.

  • boolean, 0 = in-service, 1 = deadhead

runtime_style
Enum value for types of runtime. There are various methods for distributing running time, however it is not possible at the time of this proposal to add all of them due to a lack of information on how some of these runtimes are applied by some software.

  • 0 = segment - this is by far the most common method of distributing running time. If there is a runtime between points A and B with running time periods between 6:00 and 6:29:59 of 5 minutes, and another runtime period between 6:30:00 and 6:59:59 of 6 minutes. A trip departing at point A at 6:29 will receive the running time of 5 minutes. If the trip were to depart at 6:30, then it would receive 6 minutes, this would be the case all trips up to the end of the period at 6:59:59.

  • 1 = build location - this is when all running time periods for a trip are based on a specified point on a trip.

  1. Requires proposed runtime_build_point = 1 in stop_times.txt from issue add runtime_build_point to stop_times.txt #43
  2. Example: f there are 2 running time periods, the first being between 6:00:00 and 6:29:59 and the second between 6:30:00 and 6:59:59 all between segments A, B, C, and D (A > B, B > C, C > D). For the first running time period, all segments receive 5 minutes and for the second period all segments receive 6 minutes. If we set runtime_build_point at point B and the trip passes that point at 6:29, every segment of this trip will receive running time from the first period of run times including segment A > B. So the total trip duration will be 15 minutes. If the trip were to depart at 6:30 at point B, all segments of this trip would receive 18 minutes.
@skyqrose
Copy link
Contributor

skyqrose commented Dec 1, 2023

It should be a stop_id when route_id is present or ops_location_id when is_deadhead = 1
Deadheads can happen to/from revenue stops.

In revenue service, how do the runtimes interact with dwell times? Are the runtimes always between adjacent stops, or could you have a runtime that covers multiple stations including their dwell times? Are the start/end always the arrival at a station, always the departure, or could it be either?

Would this proposal also need a way to describe typical dwell times and turnaround times?

@jeffkessler-keolis
Copy link
Contributor

I realize this is not currently supported in ODS, but I'll reiterate something I brought forth in some of the preliminary working group sessions (to minimize headache in adoption/extension down the road): the rail world often includes a number of non-public locations and/or timepoints on revenue trips.

The broader implication is that, in order for ODS to be adopted in the rail world, we need a mechanism to supplement existing stop_times.txt entries with times at ops_location.txt locations.

The specific implication relevant to this thread, though, is that the rail world requires the ability to have from and to locations reflect a pairing of both a stop_id AND an ops_location_id. Otherwise, as an example, an export from our scheduling system's database would omit standardized runtimes for any pair of subsequent passenger stops for which a switch or signal is located between the two stations.

Likewise, to Sky's point as it applies to default dwells, I think it's worth including standardized dwell times in this file, too. I believe many systems already model dwell as simply a runtime between a location and itself.

@BTollison
Copy link
Collaborator Author

BTollison commented Dec 5, 2023

For dwell times, I think it would be valid to have a runtime between 1 point.

runtimes.txt        
start_time end_time from to runtime
6:00 6:29:59 a b 5
6:00 6:29:59 b b 2
6:00 6:29:59 b c 5

So where to from / to is both B that means that the vehicle should not move for 2 minutes.

For the situation where a runtime is between a service and non-service location, I guess in theory that could work right? The main thing would be the ops_location_id's and stop_id's need to be generated in a way where all values are unique. Is that currently how we think about this? I am definitely for this, that would eliminate the need to have separate deadhead and stop_id fields when looking to assign a from and a to location.

@skyqrose
Copy link
Contributor

skyqrose commented Dec 5, 2023

deadhead_times.txt already has separate stop_id and ops_location_id columns, so I wouldn't mind this file, having four from_ops_location_id | from_stop_id | to_ops_location_id | to_stop_id columns, but I think we should also separately note in ops_locations.txt that the ops_location_ids should ("SHOULD"? "MUST"?) be different from stop_ids.

Edit: ops location ids are now going to be added as a _supplement into stops.txt so the column will just be to/from_stop_id now.

@skyqrose
Copy link
Contributor

skyqrose commented Dec 5, 2023

If we represent dwell times as a runtime from a station to itself, is there a way to represent turnaround times at the end of the route? That might be useful for, e.g., generating predictions for when a return trip is going to start.

@skyqrose
Copy link
Contributor

skyqrose commented Dec 5, 2023

Minor idea: If the end_time is exclusive instead of inclusive, then the end_times could be like 07:00:00 instead of 06:59:59, which might be easier to deal with and prevent bugs. (E.g. if someone looks up the current runtime when it's 06:59:59.581.)

@BTollison
Copy link
Collaborator Author

Yeah, I see how stop_id and ops_location_id have been incorporated into the other files, it feels like more of a workaround because there's no explicit "they must all be unique" clause. So, I am fully agreed that this would be the best approach.

We currently represent turnaround times that way. So long as the scheduling team has deadheads (ideally with distance), that should work.

I like the idea of exclusive, :) although I have never encountered a scheduling team that goes beyond seconds I could see how a real-time system may get tripped up!

@jeffkessler-keolis
Copy link
Contributor

To follow up on my earlier comment (#42 (comment)) which perhaps foreshadowed the supplemental GTFS concept (#55), we should be all set here with the caveat that from and to must now always equal a stop_id in the ODS-supplemented GTFS data (i.e. public GTFS after processing the _supplement files).

For dwells, I support treating them as runtime from x to x (akin to how most scheduling systems support it). Should the need ever arise to define turnaround times, I'd suggest those just be modeled as runtimes from a1 to a2 where a1 and a2 are children of the same parent (presumably a in this example) in the ODS-supplemented GTFS, even if modeled to the same stop in the public GTFS.

And yes, I very much like @skyqrose's suggestion of exclusive for end_time, even if most scheduling systems are currently inclusive.

@safrazier17
Copy link
Contributor

@BTollison do you agree with @skyqrose and @jeffkessler-keolis 's comments above on handling?

@BTollison
Copy link
Collaborator Author

@safrazier17 Agreed.

@jeffkessler-keolis Turnaround times are often modeled as runtimes between two children of a parent stop, so this indeed is covered (although perhaps different for rail due to collision avoidance needs?)

@BTollison
Copy link
Collaborator Author

BTollison commented Aug 28, 2024

Revised for TODS 2.0

service_Id
From calendar.txt or calendar_dates.txt, runtimes.txt entries are tied to a service_id to ensure that they are up to date and relevant for the selected route and trips.

  • Required

route_id
From routes.txt, route_id is used to tie the entry back to a route if relevant. When it is left blank it is assumed to be global.

  • Conditionally required when shape_id or direction_id has a value.
  • Where no route_id is supplied, it is assumed this is the default runtime for any service in this segment and is only superseded by an entry that has a route_id for the same segment and overlapping start_time and end_time.

direction_id
From trips.txt, direction_id is required when route_id is present to differentiate runtime direction.

shape_id
Shape_id is used to tie a runtime to a particular route_id and shape_id. If shape_id is present then route_id and direction_id should have values.

from
The from location that the runtime applies to.

  • stop_id from either stops.txt or stops_supplement.txt
  • To be valid for a trip, in stop_times.txt timepoint does not need to = 1, but then should instead be interpreted as if timepoint = 1 then a timepoint is public, but if timepoint = 0 then that timepoint is for internal use.

to
The to location that the runtime applies to.

  • stop_id from either stops.txt or stops_supplement.txt
  • To be valid for a trip, in stop_times.txt timepoint does not need to = 1, but then should instead be interpreted as if timepoint = 1 then a timepoint is public, but if timepoint = 0 then that timepoint is for internal use.

start_time
The start time of the period of which the runtime applies.

  • if this is blank, it is for the entire service day.

end_time
The end time of the period of which the runtime applies.

  • if this is blank, it is for the entire service day.

runtime
The amount of time it takes to travel from one point to another in seconds.

is_revenue
Denotes if the runtime applies to in service trips or only non-revenue trips.

  • boolean, 0 = in-service, 1 = non-revenue

runtime_style
Enum value for types of runtime. There are various methods for distributing running time, however it is not possible at the time of this proposal to add all of them due to a lack of information on how some of these runtimes are applied by some software.

  • 0 = segment - this is by far the most common method of distributing running time. If there is a runtime between points A and B with running time periods between 6:00 and 6:29:59 of 5 minutes, and another runtime period between 6:30:00 and 6:59:59 of 6 minutes. A trip departing at point A at 6:29 will receive the running time of 5 minutes. If the trip were to depart at 6:30, then it would receive 6 minutes, this would be the case all trips up to the end of the period at 6:59:59.

  • 1 = build location - this is when all running time periods for a trip are based on a specified point on a trip.

  1. Requires proposed runtime_build_point = 1 in stop_times_supplement.txt from issue add runtime_build_point to stop_times.txt #43
  2. Example: f there are 2 running time periods, the first being between 6:00:00 and 6:29:59 and the second between 6:30:00 and 6:59:59 all between segments A, B, C, and D (A > B, B > C, C > D). For the first running time period, all segments receive 5 minutes and for the second period all segments receive 6 minutes. If we set runtime_build_point at point B and the trip passes that point at 6:29, every segment of this trip will receive running time from the first period of run times including segment A > B. So the total trip duration will be 15 minutes. If the trip were to depart at 6:30 at point B, all segments of this trip would receive 18 minutes.

@BTollison
Copy link
Collaborator Author

@jeffkessler-keolis has a concern about running times that are regardling vehicles that are intended to stop and vehicles that are inteded to pass through locations. not_stopping as a boolean value could be a solution, where 0 = stopping and 1 would mean that the vehicle does not stop. You can have two entries with the opposite boolean value to describe both situations. I shall investigate if this applies to other parts of the world to ensure completeness.

@jeffkessler-keolis
Copy link
Contributor

@BTollison's note is correct; for further context, the distinction that matters is whether something is passing at full-speed or a reduced speed (either stopping at a passenger station or slowing to diverge/"turn" at a switch). The default assumption for all points should be "stopping," unless otherwise designated. Since this parameter is dependent on the condition at both the start and end locations, this could either be Boolean fields of passing_from and passing_to, that each default to 0 ("stopping" / slowing for a reduced speed diverging move), or 1 ("passing" the point at full-speed). Another valid approach, per @BTollison's suggestion, would be to use a single field with an enum, such as:

  • 0: Stopping/slowing at both the "From" and "To" locations.
  • 1: Passing at both the "From" and "To" locations.
  • 2: Stopping/slowing at the "From" location, and passing at the "To" location.
  • 3: Passing at the "From" location, and stopping/slowing at the "To" location.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants