How the database is used with auto-generated scripts

1. The TRAINS table

Data item

What its used for

Where it comes from or goes to

Train number 'trno', an integer.

Indexing into this table for data about a particular train. Each train has a number while its running and each running train has an entry in this table.

An unused train number is allocated when a train is first created by the script.

Class, an integer. Each train class (Goods, local, passenger, express etc) is given a numeric value (Goods=1, Local=2 etc.)

The class of a train defines its maximum speed and controls its behaviour. Goods trains do not stop at passenger stations (unless the track ahead is occupied) and passenger trains do not enter goods sidings. Finer control of behaviour is possible using per-train routes.

Allocated by the operator by clicking in CTC2. Loaded and saved by the script.

Minimum speed setting 'minspeed', an integer. The lowest throttle setting that makes this train actually move. Partially obsoleted by use of feedback throttles.

When pulling away from stopped a train is given minspeed with inertia zero, and then maxspeed with acceleration inertia. This avoids long periods of sitting stationary while power is ramped up to sufficient to move the train.

Initially discovered by increasing throttle level until movement is detected (by changing sensors or changing section). Otherwise loaded from LOCOS table, or adjusted by operator using CTC2. Loaded and saved by the script.

Maximum speed setting 'maxspeed', an integer. The throttle setting used to make this train run at a speed suitable for its class.

See above. This is the throttle setting used for normal running, but may be adjusted down by speed limits.

Set some ratio higher than the minimum speed during initial calibration. Otherwise loaded from LOCOS by calculation from locos.speed100

Tail, an integer. The length of the train in your chosen length units from the first pickup to the tail end of the train.

Layouts using DR keep track of where the train is from moment to moment. This value tells us where the tail end of the train is so that track in rear is freed when it is clear.

Can be entered by hand in the trains window, loaded from a saved trains database or calculated by using an optical sensor on the layout. Loaded and saved by the train object.

Head, an integer. The length of the train in your chosen length units from the first pickup to the physical head of the train. Normally very small for trains with a loco at the front.

Allows track sections to be marked occupied before the track circuits trigger.

As above

DR calibration coefficient 'cal', an integer.

Used to convert between distance travelled in your chosen distance units and integral as reported by a QTU.

Each time a train passed through a section of known length without stopping a new sample of cal becomes available. These are averaged to produce the value used to stop a train at any point along a track. Loaded and saved by the train object.

Location 'loc', a string. Saves the name of the section where a train stops at the end of a running session.

Allows the script to recover saved data for a train if a TC reports train present by looking for that location in this table.

Loaded and saved by the train object.

2. The STOCK table

Layouts using stock tagging, such as RFID or barcodes allow some or all of the rolling stock to be identified as it passes a tag reader. This information allows, for example train calibration data to be loaded from saved loco calibration data, a trains length to be calculated, a trains class can be deduced, lost rolling stock can be detected and acts as occasional confirmation that the system is keeping track of where each train is. Only a few of these are handled automatically but there is lots of scope for manual scripting.

Data item

What its used for

Where it comes from or goes to

StockType, an integer. Rolling stock is classified if any manner you wish. Stock type zero is used to mean loco.

Allows the script to know whether an item is a wagon, flatbed, boxcar, tanker, short passenger or whatever.

Must be loaded into the database by hand, or assigned by some script.

StockId, an integer. Each item of rolling stock must be assigned a unique number, using any mechanism you desire.

Indexing into this table, and other related tables such as the LOCOS table. This value is loaded into a reader object when a tagged item is scanned successfully.

Must be loaded into the database by hand, or assigned by some script.

Code, a string. This is the value stored in the tag, whether it be an RFID code, or barcode value.

Looked up by Tcc when a tag is read. The stock ID is passed to the script as tags are generally not useful in their own.

Must be loaded into the database by hand, or assigned by some script.

Train number 'trno', an integer. The same value used to index into the TRAINS table.

Identifying which stock is in which train.

Saved when a train (which by definition knows its current running number) passes a tag reader.

Image, a string. Contains the name of the file containing a picture of the stock item.

Can be displayed on a CTC screen to show the makeup or progress of a train.

Must be loaded into the database by hand.

Tag type, an integer.

Allows reliability data of different tag types to be collected. For RFID this could be size of tag, or perhaps mounting orientation.

Must be loaded into the database by hand. Not used by automatically generated script or Tcc.

3. The LOCOS table

This is the only defined per-stocktype table currently. Locos are stock type zero, so all entries in the STOCK table that have type zero should have a corresponding entry here, with locoid matching stockid.

Data item

What its used for

Where it comes from or goes to

Loco ID, an integer. Same value as stock ID in STOCK table.

Indexing into this table.

Must be loaded into the database by hand, or assigned by some script.

Minimum speed setting 'minspeed', an integer. The lowest throttle setting that makes this loco actually move. Partially obsoleted by use of feedback throttles.

Copied to TRAINS.minspeed when a train discovers which loco is pulling it. Multi-heading behaviour not yet defined.

Must be saved from TRAINS.minspeed manually.

Throttle setting to run at 100MPH (or KPH or whatever). An integer.

When a train is given a class and hence a desired speed (in MPH, KPH etc) this value is scaled to generate TRAINS.maxspeed.

Must be generated and saved manually.

Pickup length, an integer.

Used by DR system when a train changes direction. Head and tail lengths are swapped, but the locos electrical length is taken into consideration.

Must be measured and saved manually.

DR calibration coefficient 'cal', an integer.

Used to convert between distance travelled in your chosen distance units and integral as reported by a QTU.

Must be saved from TRAINS.cal manually.


Starting from an empty database and no knowledge of any trains the script starts by looking at the TCs (Track Circuits, or current detectors). Each active TC is considered to be a separate train, so this imposes one of the few constraints on train placement at startup: All pickups of a train must start entirely within one section. This is imposed because no matter what running rules one might impose about train spacing, there are times that trains are in adjacent sections, such as around passing loops.

Ignoring for the moment the possibility of database contents, the train associated with each of the active TCs is given a train number (the lowest free number).

As we have no database contents none of the trains have classes, so sit there waiting. The operator must click once in CTC2 for each train, giving each a class. I used to allow the trains to run classless but that made it error-prone entering the classes for moving trains (look at CTC2 for a train with no class, look on CTC1 to see where it is, look at the layout to find the train, look back to CTC2 and click on the class - sounds easy but its amazing how easy it is to enter the class for the wrong train when they are all moving at once!

Each train is given power, rising gradually until movement is detected. The detection could be by a sensor changing (for a layout using optical sensors), or by a TC triggering (for current-detect only operation, or for DR). The power level at that moment is considered to be minspeed - the lowest level at which the train will move. Strictly speaking I should allow detection when a QTU shows feedback volts, or any feedback throttle should create movement at power level 1, but that change is still future.

Running power level (train.maxspeed, shown in CTC2) is calculated as a fixed offset or a multiple of minspeed, as defined in the tdl file (the default being double minspeed). Both minspeed and maxspeed can be manually adjusted to suit personal preferences.

Changes to class, minspeed and maxspeed are saved to TRAINS table in the database as they occur.

If train objects are used by the script (a DR-based QTU layout) then the following also occurs:

As each train moves around the layout its DR calibration coefficient is being calculated. Once calibrated then that train switches from being operated as current-only to DR. When Tcc exits (or when the reset menu is pressed) this calibration field, the head and tail values and the latest location is saved. Non-QTU scripts could save the location field if required.

If the system is later restarted without moving the trains then everything is restored as it was: Each train object will attempt to reload head, tail, cal and location from the TRAINS table. For each active TC the script asks the train objects which train is at the location of the active TCs, and then the script will reload the class, minspeed and maxspeed.

This restores the system if nothing has changed the the last session. The trains are all calibrated, have classes etc and all start running immediately.

Taking things a little further, what happens if we move trains between sessions? Currently the trains that have 'gone missing' are treated as if they are derailed, and the 'new' trains get new numbers. I am trying to improve this situation something along the following lines:

If a train passes a tag reader and this shows that the train has a different loco then the trains calibration data is changed for that stored in the LOCOS table for the newly discovered loco.

Any rolling stock (including locos) discovered to be in a different train (stock.trno field) is changed to the new train number and a warning message displayed.

This is not sufficient to recover properly yet, I have not figured out what is required. Changing the train number of a moving train might be asking for problems!

Last updated 13 Apr 2008

© Howard Amos 2008-2009