Due to problems with the terminology, I would like to mention the English translations again here:
- RBL-Server ==> ITCS server
- Strecke ==> Route
- Route/Weg ==> Way
- Fahrt ==> Trip
- Linie/Kurs ==> Line/Course
- Umlauf(plan) ==> Tour (plan)
2 In the vehicle
This is about the AVLC on-board device, i.e. the IBIS device (tram or former in buses) or the "printer" (in buses), getting access to various data of the timetables.
- The ID of the stations in the PIS file must match the PIS ID of the track or - if none has been entered separately - the PIS ID of the station, or - if nothing has been entered here either - the internal name of the station.
- Routes/ways of the timetables are labelled with an PIS line and an PIS route, which must match the line and route information of the associated route in the PIS file.
If this is adhered to, then appropriately scripted AVLC on-board units can on the one hand access the information of the PIS file (e.g. various strings), but in parallel also access the information of the timetable (e.g. whether the vehicle is on the correct route).
2.1 Separation of disposition and AVL
And it is equally important to realise that, first of all, a strict distinction is made between:
- the LOTUS disposition: the tour on which you "actually" drive, i.e. which you have selected in advance or during the game via the corresponding menus in the single-player game or which the game leader has assigned to you in multiplayer, and
- the AVLC server of the transport company, to which one can log on with the AVL on-board computer [function not yet available] and the timetable data of all kinds stored on the on-board computer.
Just because you have selected a trip or a tour in LOTUS does not mean that you are registered on the AVLC server and appear in the corresponding places linked by the AVLC server - and vice versa it is not enough to simply register via AVLC - you only "officially" drive the tour (with all the consequences such as trip evaluation [function not yet available] ) when you have selected it in LOTUS or assigned it to one of the game leaders.
With your AVLC device, you therefore have no access to the current status of the scheduling in LOTUS (actual delays, vehicle positions, etc.)! The only thing you have access to is the planning timetable data, as it is assumed that this is already stored on the device.
2.2 Numbers vs. Strings
In order for the system to be as open as possible, strings are used for lines, routes, etc. to identify them. The "usual" devices (especially those from the standard content) use pure integers for this. Of course, this means that it is often necessary to convert given integer values (e.g. from the input of the on-board computer) into string values (e.g. for the timetable functions listed below).
The following applies: Do not use leading zeros! Even if the input is "001" on the on-board computer, the leading zeros must still not be transferred internally!
2.3 Functions for routes only
function TimetableGetWayIndex(self: integer; itcsServer: string; line: string; route: string): integer This function returns the internal index of the route queried by line and route code and specifying the AVLC server name. It returns "-1" if there is no route with this line and route code in the timetable data.
function TimetableAtSectionOfWay(self: integer; wayindex: integer): integer This function can be used to determine whether the vehicle is currently on the route designated with "wayindex". If so, the so-called "section" is transmitted. This counts up station by station, whereby the distances between the stations are also counted separately. So:
- 0: at the departure station
- 1: between first and second station
- 2: at the second station
- 3: between second and third station
If the vehicle is off the track, a -1 will be returned. Attention again! It is completely irrelevant whether and on which tour the vehicle was actually registered in LOTUS! The output works completely independent of this!
function TimetableAtBusstopOfWay(self: integer; wayindex, sectionindex: integer; out stnID: string): boolean This function returns (specifying route index and section) whether the vehicle is at a station and then transmits via stnID the PIS ID of the track or - if this is empty - the PIS ID of the station or - if this is also empty - the internal name of the station.
function TimetableDistBetweenStns(self: integer; wayindex: integer; startStn, endStn: string): single Returns along the route "wayindex" the distance between the named stations, measured along the route in metres.
Functions for trips
procedure TimetableGetTripAndTourIndexByLineCourseDate(self: integer; date: single; time: single; itcsServer: string; line: string; course: string; out iTimetable, iTrip, iTourplan, iTour, iTourtrip: integer) Returns timetable index, (timetable-wide) trip index and the indices that define the tour (i.e. index of the tour plan, of the tour within the tour plan and of the trip index within the tour). The function requires the date and time of the query, the name of the associated AVLC computer as well as the line and course.
procedure TimetableGenerateTempTripListByTour(self: integer; timetableIndex: integer; iTourplan, iTour: integer) Creates a temporary list of the trips of this tour, specifying the timetable, tour and tour index (to be determined, for example, by the previous procedure). This list remains until this procedure is executed again (or the visible object in which the script is working is removed).
function TimetableGetTempTripListCount(self: integer): integer Returns the count of elements in this list.
procedure TimetableGetTripInfoByTempListIndex(self: integer; templistindex: integer; out line: string; out course: string; out route: string; out tripIndex: integer; out depTime: single) Returns further information from the trip from the temporary list:
- Line: Line as string
- Course: Course as string
- Route: Route id as string
- Tripindex: Timetable-wide index of the trip, i.e. not within the tour, but tour-independent!
- DepTime: Departure time in days. If the tour started on the previous day, it is also calculated relative to 00:00 hours relative to the previous day. The number is then greater than 1.0.
procedure TimetableGenerateTempStnListByTrip(self: integer; timetableIndex: integer; tripIndex: integer) Creates a temporary list of stops of the trip identified by trip index (e.g. "tripindex" from the previous procedure) and index of the schedule. This list exists until this procedure is called again.
function TimetableGetTempStnListCount(self: integer): integer Returns the count of elements in this list.
procedure TimetableGetInfoByTempStnListIndex(self: integer; templistindex: integer; out FIS_ID: string; out arrTime: single; out depTime: single) Returns the PIS ID (corresponds to the ID in the PIS file), the scheduled arrival time and departure time from the stop in the temporary list.
2.4 Control centre interactions
2.4.1 Text Message Control Centre to Vehicle
To be able to receive control centre messages, the procedure ReceiveFromITCS(id, value: string) must be defined in the script, which is then called as soon as a message arrives. It does not matter whether this procedure is defined in the vehicle and/or module script, as both vehicle and all modules receive the message. The variable value contains the actual message, id contains additional information - at the moment "MSG_INFO" is always transmitted here, "MSG_CONFIRM" is also firmly planned for messages that must be actively confirmed. It is possible that further control centre functions will be realised via additional IDs in the future.
3 On the road
3.1 Signal box vs. AVL
On the road, there is now already the possibility to access the LOTUS-internal dispatching.
To this end, it is necessary to briefly explain how things work very roughly in reality:
- For buses and trams, "everything", i.e. also real-time displays, the setting of switches (if not via line identification or similar), the control centre, etc., runs via the AVLC; if you do not register here, you have "lost" and have to do everything manually.
- On underground, suburban and railways, on the other hand, you can also register "somewhere", but for the crucial things (dispatching and thus setting switches and signals, platform displays, etc.) the train is identified by its train number and accompanied "from the outside". Regardless of whether it's an ICE, a steam locomotive or a trolley, the traffic controllers know who you are. The whole thing works regardless of whether you log on somewhere with your on-board equipment
While one or more AVLC servers are simulated in LOTUS for the first case, which are managed independently of the internal LOTUS dispatching, the interlockings and platform displays (of the railway) are directly connected to the internal dispatching in LOTUS. In our opinion, it would be excessive to add another intermediate level, at least at this stage.
Accordingly, there is a distinction in the following commands as to whether the data originates from the AVLC computer or from the internal disposition.
3.2 Scripting functions
The following functions are used to supply data to e.g. dynamic stop indicators:
procedure StatPIS_Login(Self: integer; stationname, trackname: string) Registers the object at a station and a track. The internal designations are expected in each case. If an empty string is passed as the track, then all tracks are taken into account for all following procedures and functions.
procedure StatPIS_GenerateTempDataList(Self: integer; timespan_d: single) Generates a temporary list of trips that take place or should take place within the coming period of the length "timespan_d" (calculated in days). The data (delays, cancellations, ...) of the LOTUS-internal disposition are used here. The temporary list remains until one of the four procedures mentioned here is executed again.
procedure StatPIS_GenerateTempDataListWholeStation(Self: integer; timespan_d: single) Generates a temporary list of the trips of all tracks (i.e. even if a specific track was specified during login). The data (delays, cancellations, ...) of the LOTUS-internal disposition are used here. The temporary list remains until one of the four procedures mentioned here is executed again.
procedure StatPIS_GenerateTempITCSDataList(Self: integer; timespan_d: single; itcsServer: string) and procedure StatPIS_GenerateTempITCSDataListWholeStation(Self: integer; timespan_d: single; itcsServer: string) These two procedures correspond to the two previously mentioned, but the difference is that here the delays, cancellations, etc. are taken from the data available to the AVLC server. The decisive factor here is therefore not that the corresponding vehicles have been "officially" assigned to a tour by LOTUS, but that they have logged on to the AVLC server via the AVLC on-board device. [Since the AVLC servers have not yet been fully implemented, the LOTUS data are also currently used as a basis here].
function StatPIS_GetTempDataCount(Self: integer): integer returns the number of entries in the temporary list created with the previous procedures.
procedure StatPIS_SortTempList(Self: integer; by: byte) sorts the elements of the temporary list. "by" indicates the sorting criterion, currently there is only "0", which sorts the list according to the actual departure time.
function StatPIS_GetTempListData(Self: integer; templistindex: integer): TStatPISTrip returns a data set from the temporary. This is of the type "TStatPISTrip", which is declared as follows:
- TStatPISTrip = record
- Index: integer;
- TourIndex: integer;
- Category: integer;
- Name: string;
- Line: string;
- Start, Terminus: string;
- AT_Plan, AT_Curr, AT_Delta, DT_Plan, DT_Curr, DT_Delta, Delay: single;
- TrainLoggedIn: boolean;
- RemainingLegs: integer;
- Track_Plan, Track_Curr: string;
- First, Last: boolean;
The elements have the following meanings:
- Index: Index of the dispositional trip (the same trip on different days has different indices).
- TourIndex: Index of the dispositional tour (the same tour on different days has different indices).
- Category: Train type index
- Name: "Name" of the trip, usually it should just be the train/trip number
- Line: Line that is deposited in the associated path/route
- Start, Terminus: PIS designation of start and destination (first or last station with passenger stop)
- AT's und DT's: Arrival and departure times in days, each scheduled and actual as an absolute number ( < 1.0, i.e. 25 o'clock becomes 1 o'clock, etc.) and the actual time relative to the current time.
- Delay: " + " = late, " – " = early
- TrainLoggedIn: If the source is the AVLC, then this variable indicates that a vehicle has registered on the AVLC computer, specifying the associated line and course, otherwise the variable indicates that a journey and a round trip have been assigned to a vehicle in LOTUS.
- RemainingLegs: How close is the vehicle already to the station that was logged into? 0 = has already entered, -1 = has already left, +1 = has left previous station, +2 = in previous station etc.
- Track_Plan, Track_Curr: Public name of the scheduled and actual track
- First, Last: is the logged-in station the first and/or last (passenger stop) station of the trip?
function StatPIS_GetViaStationsOfTripTabSep(Self: integer; tripindex: integer; count: integer): string Indicates separately in tab stops the series of next stations of the train. Thereby:
- corresponds "tripindex" of the variable "Index" in the record TStatPISTrip
- a maximum of as many stops are listed as specified by "count"
- the selection (not order!) is chosen depending on the priority of the individual stations. If in doubt, the higher priority stations will be listed completely before lower priority stations are added. If not all stations of a priority can be listed, preference is given to the closer stations over the more distant ones.
- the list is sorted according to the order of the stops, the next stop first, the last stop last and
- neither the current nor the last station are listed under any circumstances.
function StatPIS_GetInfotext(Self: integer): string; Returns the info text (e.g. scrolling text) sent, for example, by the control centre to the assigned stop.
3.3 Script Example
- $Station: string;
- $Track: string;
- Output: string;
- NotFirstRun: boolean;
- function TimeToStr(time: single): string;
- result := IntToStr(Trunc(time * 24 * 60));
- procedure SimStep;
- i, n: integer;
- traindata: TStatPISTrip;
- if not NotFirstRun then
- NotFirstRun := true;
- StatPIS_Login(Self, $Station, $Track);
- StatPIS_GenerateTempDataList(Self, 0.25); // 0.25: a quarter of a day = departures of the next 6 hours
- n := IntMin(StatPIS_GetTempDataCount(Self), 4); // display max. four departures
- StatPIS_SortTempList(Self, 0);
- Output := '';
- for i := 0 to n-1 do
- traindata := StatPIS_GetTempListData(Self, i);
- Output := Output + traindata.Line + ' ' + traindata.Terminus + ' ' + TimeToStr(traindata.DT_Delta) + #13#10;