Track Definition Language

My layout uses a tcl (Train Control Language) script that is automatically generated and operates on the following basis:

If this style of operation suits you then you might find this script generator useful.

The script generated is of the following form:

1. Each section of track, or turnout, or crossing is handled by a separate module of code. All identically behaving tracks have a copy of the same module of code. Typically each module represents one track element and it only refers to its immediate neighbours. It might look at its predecessor to see if a train is coming, and at its successor to see if it may forward that train.

Each module 'owns' a group of variables in the tcl script. These are grouped into a structure that is the track element. Thus for example track "L1" (meaning track segment number 1 that is long enough for some trains to stop in) will have the following variables:

Where a track cannot know which real track section is its neighbour (where a turnout is involved) then the turnout provides a pointer so the neighbours can 'see' one another.

2. There are also modules of code for each train, used to route control to the appropriate throttle, and to interact with the CTC panel.

Although the generated scripts are readable and editable, they are not necessarily the easiest things in the world to maintain, because they are not intended to be maintained. Any required changes are made by either updating the .tdl file or (as a last resort) the java program that converts the .tcl file to the .tcl file.

The following types of track element are currently supported:

"Long": A regular track section that is long enough for a train to enter at full speed and slow down and stop before the end of the section. One day I'll extend the definition so that trains can take more than one track section to stop, but currently its one section. A Long track section must have a current detector and can optionally have entry and/or exit optical sensors. The entry sensor is useful for detecting the early arrival of trains where the loco is not in front. The exit sensor (if fitted) is used to stop the train if the next section is unavailable.

"Siding": A long track section connected at only one end. Sidings may be entered forwards or reverse.

"Turnout": Where track diverges (cf. "Turnin")

"Turnin": Where tracks converge

"Crossing": Where tracks cross (a diamond crossing, not a crossover).

"Dummy": A 'track' that isn't yet laid. Can connect to turnouts so that a layout can have room for expansion. No code is generated.

"Short" and "Zero" track sections are historical and not currently maintained. Where sections of track are too short to be classed as "Long" they should be tied (electrically) to a neighbour and ignored in the file. Thus if two turnouts (for example) were joined by a short piece of track, that join is not defined.

"Invisible": Defines sections of track that were ignored in defining the .tdl file (see previous para). Used only to capture CTC locations for auto-creation of .ctc files.

"Button": A push button connected to some input pin. When pressed places a mark in the log which is useful for debugging. Optionally can stop all trains.

"When", "While": Add your own code to the automatically generated code.bu

"Network": A complex interconnection of track elements. A network can have one or more arrival tracks, and one or more departure tracks (which could be the same track as arrival - eg in a siding).

"NetSwitch": A turnout that is part of a network (and not a Turnout or turnin module). NetSwitches may be traversed in either direction if appropriate.

"NetInput": A list of tracks that convey trains into a network.

"NetOutput": A list of departure tracks.

"NetDir": A toggle used to control bi-directional areas.

"NetRoute": One possible path through a network, from one arrival track to one departure track. It may use any number of NetSwitches, and even other tracks.

Note there is no crossover section. This is because crossovers, by their nature imply bi-directional track. All bi-directional track must be controlled by a network, and so the turnouts that make up the crossover will be defined as NetSwitches.

Networks

The basic track elements (Long, Turnin, Turnout, Crossing) are sufficient to create simple layouts with simple functionality, but they are all limited in that all track is uni-directional. This is fine for regular main-lines, but it tends to be somewhat restrictive on sidings. Networks can overcome this restriction.

Another limitation of the simple track elements is in the more complex behaviours. A Turnin can allow the highest priority train to pass the other, but that is limited to just two trains. If you have a set of turnins then prioritised behaviour doesn't work as the turnins do not know about one another. A network prioritises trains on all its arrival tracks.

Class-based routing is a third reason for using a network. Some routes across the network may be restricted to certain classes of train.

A .tdl (Track Definition Language) file defines the nature of a layout so that a .tcl script can be automatically generated.

Naturally only a constrained set of scripts can be generated, and the constraints are:

  1. Trains are driven automatically. No manual driving is currently supported, but can be implemented by adding some simple tcl script to the tdl file.

  2. Trains are routed automatically. No pre-set routes can be defined.

  3. Automation of a track diagram CTC panel is restricted to panel 1, and using colours (in resistor colour code sequence) to illustrate the progress of trains, and animation of points.

  4. Manual control is limited to entering train type (goods, local, passenger, express) and adjusting desired slow and full speeds. Note that full speed is also automatically adjusted if measured sections are used.

  5. Most track is uni-directional. Each track module 'knows' about its predecessor and successor - this requires that train normally drive in a known direction. However it is possible for some (or even all) areas to have bi-directional track.

  6. When the script starts, all the current pickup for a train must be wholly with one track section. No unpowered units (carriages, wagons) may be spanning a turnout ahead of that track section, but may span as many turnouts and track sections as required behind the locos (if optical sensors are being used).

  7. Turnouts are all driven by two outputs each (or a shared direction, plus a pulse for each turnout). This is so turnouts do not all change at startup when a train may be on them.

Full details of each of these elements is below.

Data preparation and Runtime usage

When the script starts each track section that is drawing current is considered to be a separate train. This is why all pickups for a train must be within a single section. Each train is allocated a train number, and those train numbers are associated with a colour, allocated according to the resistor colour code standard (brown for train 1, red for 3 etc). CTC2 is used to display data about each train. Each cell in column 3 from the second row downwards should contain a horizontal section of track. These are coloured as trains are discovered.

CTC2 also gets headings automatically added to columns 4,5,6,7,8 & 10 to list the possible train categories and the calibrated speeds for each train. By default the text is too large and so using the Tracks pallette, select the text button ("abc"), enter some text and select small size and left alignment then click in each of the cells that gets a title. When the script draws the titles the text will retain the size and alignment you give it. I anticipate changing the numbers of categories one day, and probably allow their names to be set in the tdl file, so expect these headings to move some time.

Once each train has started moving its minimum speed and maximum speed values are displayed in CTC2. These can be adjusted on-screen using left and right clicks if the auto-calibration is unsuitable.

CTC3 is used to display and control the inertia settings globally and it has headings on the first row, above values on the second row. These are used as follows:

upMomentum is used when accelerating from slow speed to full speed. This defaults to the maximum of 255. downMomentum is used when decellerating from full speed to slow speed. This currently defaults to 128 to avoid trains overrunning sections. startMomentum is used when starting from stationary (accelerating towards slow speed), defaults to 64 so that excess delays are avoided while the voltage ramps up to enough to just move the train. brakeMomentum is used naturally when braking - the last part of slowing down when the exit sensor or whatever has been reached. This defaults to just 32 so that the train stops very quickly without being too much like a dead stop.

These values can be set in the tdl file using the setVar command, and also adjusted on-screen using left and right clicks. Any errors detected by the script are displayed on CTC3.

If you are using a track diagram then this should be on CTC1, and the coordinates of each section should be in the tdl file. This permits the track diagram to be animated. Each train is shown in its own colour on this diagram. When a train is arriving in a section then just the first segment of the track is coloured, when the train is fully inside the section the whole section is coloured, and when the train is departing the last segment is coloured. Note that currently bi-directional track does not reverse this for the train travelling in reverse. You might like to add text labels to each section on CTC1 to help remember where each section is.

When the script starts and the trains are identified and CTC2 is updated to show the colour codes (one for each train discovered), you need to tell the script what category each train is. Look at CTC1 for each colour, match that to a train on the layout and then click in the CTC2 cell where the row of the train colour intersects with the column of the trains category. The category name should then be displayed in that row. Note that redrawing has problems here and you may want to click twice.

Only when the category of a train has been set will the train move away. This is a 'safety' feature - I found it far to easy to mis-enter categories when the trains were all moving.

The tdl file mostly contains track definition lines of the form:

In addition the following lines exist:

Lines containing '#': The hash and everything after is treated as a comment.

Lines starting with "InStack", "OutStack" and "QtuStack" are used to define where sensors and controls are connected to the interface hardware. This is beyond the scope of this document.

Lines starting with "Default" define options that apply to all sections, unless counteracted.

Lines starting with "SetVar" set the value of variables used in the script generator. These are defined below.

Now to define in more detail each type of line in the .tdl file:

Default <options>

<options> is a space separated list of any number of the following:

example: Default HC nC hP HQ

Defines a layout where each long track section has a dedicated QTU output ("HQ"), there are no power routing relays ("hP") and current detectors are positive logic ("HC nC")

SetVar <assignment list>

MaxTrains <n> Sets how many trains the script can support. Any number upto this limit are OK, but more cannot be handled. Set this as high as you are likely to need. The only 'cost' is script size. CTC2 will need at least this number of track sections in column 3 (coloured to show which train has which colour).

defaultHead <l> defaultTail <l> For QTU systems. Sets the default length of the train measured in your chosen units (see "length" parameter for "Long" track). Head is length from the leading edge of the train to the first pickup and is typically just a couple of centimeters, but could be longer if you are pushing. Tail is the length from the first pickup to the tail end of the train. Together they add up to the total length of the train. This is used to decide where a train should stop and whether the train can enter a siding.

minSpeedRange <min>-<max> maxSpeedRange <min>-<max> Limits the range of min/max speed setting that the auto calibration system will use. If a train moves below <min> speed then the appropriate speed is raised to <min>. If a train hasn't been seen moving before speed reaches <max> then the speed is left at <max>. Maximum (normal) speed is currently set to 10 more than minimum speed.

upMom <m> downMom <m> brakeMom <m> startMom <m> Sets the momentum values used for accelleration, decelleration, braking and starting (going from zero to minimum speed). Values in range 0 to 255.

stopPercentage <pc> For long sections not specifying where the train should stop (using length /s=), This value is the percentage of the length of the track where the leading edge of the train should stop. Defaults to 75%

arrDelay <t> Sets the time (in units of seconds and tenths of seconds) from the time a train is first detected in a section, to slowing down if the next section hasn't become booked for it. Defaults to 1.0 (one second).

stoppingTime <t> Sets the time (same units as arrDelay) that a train runs slowly before stopping. This is only used in current-only mode: sections having no sensors, and no dead-reckoning. The idea is to get the train partially into the section before it stops. This needs to be set by experiment, with a safe value to ensure that trains never overrun the section. defaults to 3.0 seconds.

stoppedTime <t> Sets the time that a train waits when stopped in a station or siding. Defaults to 10.0 seconds. Naturally a train will be stopped longer if the track ahead isn't clear.

solenoidPulse <t> tortoisePulse <t> Sets with of pulses to solenoid and tortoise motors. Default to 0.2 and 4 seconds respectively (can specify these values using 2 and 40 - remember times are in tenths of seconds).

example: SetVar MaxTrains 6

Long <name> <options> <destination> <parameters> <CTC locations>

example: Long L3 -Opt,Stn,Pass to TI3 length 17 12,20/5,20

I suggest a short name (I use L1, L2 etc) as every variable in the script has this name as a prefix. I have never tried "Supercalifragilisticexpialidocious" but I don't know of any reason it shouldn't work.

<options> is a comma separated list (so all options run together as a single word). The following options are supported in addition to those meaningful in the list for defaults:

feed=<stackname> defines where power routing relays are controlled.

cur=<stackname> defines where current detector is connected.

opt this section has an entry optical sensor.

-opt sensor uses negative logic levels.

[-]opt=<stackname> also where it is connected

[-]opto[=<stackname>] ditto for exit sensor

<qtustackname> All connections default to this qtu.

stn This is a station stop.

StopClear Mark section as occupied when train is stopped (use for stopping sections without entry optical sensor)

cal Calibrate train speed on this section

Guide Select throttle based on next turnout or network. Not used for QTU layouts.

sig<n> Has an n-way signal. Not yet implemented.

pass This is a passing section. Must be followed by turnin or network, and have other sections converging.

An explanation of "Guide" is warranted:

Most sections initially select which throttle to use based upon which the train is using in the previous section. If the train (still in the previous section) is using a throttle not available in the next section then the next section will simply not become booked for that train. When the train is in a section then that section will promote the train to use the preferred throttle if possible (if that throttle is not in use by another train!).

A Guided section does not have a fixed 'preferred' section, but will promote the train to whichever throttle the NEXT track section requires. This is essential for example if you have two track loops, each of which have a set of throttles (as in ha1.tdl for example) and a track not in either loop approaches a TurnOut or Network which allows the train to enter either loop. The turnout or network will tell the preceeding section which throttle is required for the train to be able to proceed. The same applies for sidings and reversing platforms where the train will switch loop.

if no options are required then substitute "-"

<destination> is: "to" <sectionname>

Where <sectionname> is the name given to the next section (where the train travels onward to). The predecessor section is not required. Note that neighbours might be turnouts, crossings and networks, and not the track beyond those elements.

<Parameters> may include any combination of:

"length" <length>["/i="<lengthI>]["/o="<lengthO>]["/s="<lengthS>]["/n="<entryGap>]["/x="<exitGap>] "power" <throttle list>

The length fields may be in any units you choose. Pick a unit that will give most tracks a length of over 100 and less than 1000. Train lengths and train positions will be represented in your chosen units.

The first length field is the electrical length of the section and is primarily required for layouts employing dead-reckoning (only implemented on QTUs at present). LengthI and lengthO define where the optical sensors are. Note that a length of zero means undefined so if you have an entry sensor at the beginning of the section, specify length 1 instead of 0. entryGap and exitGap are used to ensure that trains stopped by dead-reckoning are clear of the ends of the track by the specified amount. Useful if a turnout is at an end and a train should move into the electrical length of track by some amount to leave the turnout clear.

If both optical sensors are fitted (and dead-reckoning is NOT in use) and the train fits between the sensors (which are lengthO-lengthI apart) then the train length will be reduced to that distance if it is higher.

If dead-reckoning is being used (you are using QTUs) then the length of the track is used to calculate (and maintain) the feedback integral coefficient which is the relationship between feedback integral and the absolute position of the train.

It is important that the length is fairly accurate as errors here will cause train stops controlled by dead-reckoning to be inaccurate. To counter this problem Tcc outputs a report of dead-reckoning track lengths to the tcc.log file when Tcc exits. This can be useful to find errors in your measurements! If Tcc says that one track is too short and the others are OK, trust it - it is probably correct!

Note that the length (for dead-reckoning) is the electrical length of the section which might include adjacent turnouts and crossings. In fact whatever the length of track is between insulating fishplates.

If your track has different lengths dependant upon which route adjacent turnouts might choose then it is possible to add an excess length value which is defined in the Turnout or Turnin or NetRoute declaration. In such a case define the track to have the shortest of all the possible lengths.

For PCC layouts the throttle list (2 or 3 throttle numbers) identifies which throttles may be routed to this track, and the relays that must be activated to connect them (implied by their ordering). The least preferred throttle is listed first, and the most preferred one last. All sections must support at least the most preferred throttle of all the immediately preceeding sections. This means that if sections A and B converge at a TurnIn to section C then section C must support the most preferred throttles of both A and B (which might be the same or different).

Most sections of a PCC layout probably have two relays to select power - one to select between the two preferred throttles, and an extra relay which can disconnect power - the stop relay. Without the stop relay a train that overruns into the next section will run out of control, but it is possible to run with only the power selection relay. The relays need to be wired to select power from a parameter of "power 1/2/3" thus:

RCx     RSx     power
off     off     off
off     on      first choice (3)
on      on      second choice (2)
on      off     third choice (1) - the stop relay is required here! 

<ctclocations> is a slash "/" separated list of co-ordinates that are comma separated (column "," row). The first coordinate must be the entry end of the track and the last must be the exit. If the list terminates with "/I" then each cell on the CTC panel is activated individually, otherwise they are assumed to be in a block (setup on the CTC panel). Additional coordinates may be used to show the path of the track (which must be defined if "/I" is used) and is used to generate a ctc file from the tdl file.

Siding <name> <options> <destination> <parameters> <CTC locations>

The same as a "Long" definition, but note that the destination is also where the train comes from.

Note that sidings can only be used with networks.

Turnout <name> <options> <neighbours> <parameters> <CTC locations>

<options> include (in addition to those defined for defaults):

Tort (tortoise) slow acting turnout motor (rather than a solenoid action). Implies "lr" (controls are left and right individually).

Pwr Has a relay associated with the turnout control that can be used to feed the adjacent track section if required.

pmd Use non pulsed control wire suitable for PMD or PMR modules.

<neighbours> is "from" <name> "leftto" <name> "rightto" <name> Left and right are as the train sees it. If the train keeps left that that is the left path. It has no bearing on normal and reverse which are not used. If dead-reckoning is being used (you are using QTUs) then the leftto and rightto names can optionally have "="<length> appended where length is the extra track length that that route incurs. Such a length is added to the length of the preceding long track when the turnout is set appropriately.

<parameters> can be the optional: "percent" <number> which defines the probability of choosing to go right (if both routes are free).

<ctclocations> is a single coordinate (<column>","<row>) followed by "/L" or "/R" which defines which direction is which. This flag means that turnouts can be wired up without regard for left and right control. If the turnout gets set the wrong way then change this flag.

Turnin <name> <options> <neighbours> <parameters> <CTC locations>

<options> are as turnouts.

<neighbours> are: "leftfrom" <name> "rightfrom" <name> "to" <name>

If dead-reckoning is being used (you are using QTUs) then the leftfrom and rightfrom names can optionally have "="<length> appended where length is the extra track length that that route incurs. Such a length is added to the length of the following long track when the turnin is set appropriately.

Crossing <name> <options> <neighbours> <CTC location>

There are probably no relevant options, so "-" is normal. Frog control relays will be added as an option soon.

<neighbours> are: "leftfrom" <name> "to" <name> "rightfrom" <name> "to" <name>

The first "to" defines where a train that arrives "fromleft" goes to, the second "to" for trains arriving "fromright". Left and right can mean whatever you want them to mean (until I animate crossings on the CTC panel too).

Button <name> <options>

A regular push button connected to an input line. When pressed the name of the button is added to the log. If you are logging (menu Configure->Logging) then this can be used to mark roughly when some even occurred. Do need to remember what the event is of course (which can be difficult unless you write it down). <options> can include:

"inv" which inverts the button polarity (for normally closed buttons).

"stop" makes the button into a "panic button" and stops all the trains quickly. Useful if you can see a collision approaching, perhaps as a result of a derailment.

When <code>, While <code>

The code is inserted into the generated tcl file. Note that <code> must be on a single line, but that line can be as long as you need. You can add quite interesting functions to your layout that are beyond the normal scope of tdl files. For example look at jax9.tdl for an example of driving trains manually.

WhenNT <code, WhileNT <code>

Same and When and While except the inserted code will not be traced to the log file. Useful for trivial copy functions that execute very frequently such as updating a throttle speed from an analogue input line.

Network <netname> <uses>

<netname> is the name of the network, and is used in combination with the names of tracks that connect to the network.

<uses> is a comma separated list of NetSwitches that are part of this network.

Where the regular track elements form unidirectional track in a fixed configuration a network is rather different: it is a collection of track elements and their software connectivity is dynamic. Obviously the physical connectivity is fixed, but the concepts of next track and previous track are re-wired as required.

As far as the physical layout is concerned, a network con encompass any contiguous block of trackwork.

The reasons for using a network are identified at the beginning of this file. For an example of using a network see below.

A network is a collection that can contain the following items:

  1. NetSwitch: a turnin/turnout unit. Trains may approach and depart in any direction. A NetSwitch can also be a crossing embedded within a network, or even just a dummy resource to connect two tracks (see J14 in ha2.tdl)

  2. NetInput: regular track elements which can feed a train into the network.

  3. NetOutput: regular track elements which can accept a train from a network. Note that a track element could be both NetInput and NetOutput (which is how track is made bi-directional).

  4. NetDir: a flag which can be used to control the direction of a regular long track.

  5. NetRoute: One (of many) routes across (or within) the network.

NetSwitch <netname> <name> <options> <CTC location>

<netname> is the name given to the network this is part of.

<options> include those in defaults, and turnouts and additionally:

nomotor This turnout is not controlled. Used for crossings declared as NetSwitch

ab This turnout has two halves (probably forming a crossover). Two turnouts are defined with "a" and "b" suffixes but controlled as one.

<CTC location> is as per turnouts.

Note that netswitches do not have neighbours defined, nor do they have travel direction (but do have control direction /L or /R). All important information about routing a train across a network (and netswitch) is defined in the netroute.

NetInput <netname> <names>

NetOutput <netname> <names>

<netname> is the name given to the network this is part of.

<names> is a comma separated list of tracks that arrive at (NetInput) or depart from (NetOutput) this network.

NOTE: The tracks must be defined BEFORE use in a NetInput or NetOutput statement.

NetRoute <netname> <id> "from" <name> "to" <name> "uses" <list> <control>

<netname> is the name given to the network that all the items listed here are part of or connected to.

<id> is a number that uniquely identifies the route.

<name> is the name of a section declared as a NetInput (or NetOutput) for this network.

<list> is a comma separated list of NetSwitch and NetDir objects, other tracks and details of how to form the route.

A route cannot be set unless all the items it uses are free. When the route is set then this items are in use.

The direction through a netswitch is specified by appending "L" or "R" to its name.

If a NetDir is used then two letters are appended to its name. The first specifies what direction it must already be set to ("F" or "R") or "-" for don't care. The second defines the direction to set it to if the route is set.

<control> lists train classes that may take this route, and the probabilities of them being accepted. Any train is indicated by "any". Other classes are "goods", "local", "passenger" and "express". The probability can be defined so that the first defined route is not always taken if it is available.

NetDir <name> <control list>

<name> is the name given to the NetDir.

<control list> is a comma separated list of Long track elements whose direction is controlled by this flag.

A NetDir can also be used to restrict route selection.

Example network usage.

1. Three-way turnin

        ----------
            a   i1 \ 
        -------- ---
            b     i2 \
        ----------- -- --------
            c              d 

We have three Long tracks 'a', 'b' and 'c', converging using two points, 'i1' and 'i2', trains departing to 'd'. The network consists of the two points.

This might be declared as (ignoring the CTC co-ordinates):

Network         N1      i1,i2
Long            a       -       to      N1
Long            b       -       to      N1
Long            c       -       to      N1
NetSwitch       N1      i1      - 
NetSwitch       N1      i2      -
NetInput        N1      a,b,c
NetOutput       N1      d 

Note that the destinations for 'a', 'b' and 'c' could be 'N1' or 'i1' (or 'i2'), either is equally valid.

There are three possible routes through this network which are declared as:

NetRoute        N1      1       from a to d uses i1L,i2L
NetRoute        N1      2       from b to d uses i1R,i2L
NetRoute        N1      3       from c to d uses i2R 

These specify which points are used for the particular route, and which way to set them.

This particular network can obviously only handle one train at a time, but a more complex network with more NetOutputs might be able to handle more trains at once.

This example is lifted out of my own layout script ha2.tdl and as such should work well.

When a train enters any of the approach lines, then the network looks to see if any other NetInput is booked for another train of higher priority. Only if the approaching train is the highest priority is it offered to the network.

For a more detailed explanation of network operation, see below.

2. Simple siding.

-------- ------------ -- -----------
     b        a        \ t    d
                        \
                         \ s 

We have a Long approach track 'a', a turnout 't', a departure track 'd' and a siding 's'. Before 'a' there is Long track 'b'. 's' is clearly bi-directional. Trains enter 's' in forward direction. To exit the siding they reverse onto the mainline 'a' and then continue onward to 'd'. Note the implicit constraint that 'a' must be no shorter than 's'.

These might be declared as:

Network N1 t
Long b - to a
Long a - to t
NetSwitch N1 t -
Long d - to <somewhere>
Siding s - to t 

The network consists of just one turnout 't'.

So we have two sources of train approaching the network, and two ways out of the network:

NetInput N1 a,s
NetOutput N1 s,d 

Clearly 'a' and 's' must be reversible, so we need:

NetDir D1 a,s 

This assumes that the wiring for 'a' and 's' both use the same polarity (ie both forwards for a train to enter the siding).

There are three possible routes across this network:

  1. From 'a' left through 't' to 'd' (the main-line path)

  2. From 'a' right throught 't' to 's' (entering siding)

  3. From 's' reverse to 'a' (reverse out of siding)

NetRoute N1 1 from a to d uses tL,D1-F
NetRoute N1 2 from a to s uses tR,D1F-
NetRoute N1 3 from s to a uses tR,D1-R 

If we ignore the D1 portions for a moment these are very simple statements detailing how to get from input to output.

In the third statement D1 is set to 'R' (reverse): The train is reversing out of the siding, back onto the main line.

In the second statement D1 must already be 'F'. This prevents a train that has just reversed out of the siding from going back in.

In the first statement D1 is set to 'F' (forward): clearly this is a route where the train is moving forwards. The reason we are doing this is in case the train has just exited the siding and track power would otherwise still be reversed.

If the siding is intended for just goods trains, then the second route can be qualified by:

NetRoute N1 2 from a to s uses tR,D1F- goods 

As it stands all goods trains will enter the siding if it is free, so to reduce the probability of a train from entering, another qualification might be in order:

NetRoute N1 2 from a to s uses tR,D1F- goods/40 

Which means that if a goods train approaches the network on 'a' and 's' and 't' are free, and D1 is already forwards, then there is a 40% chance of the route 'bidding' for the train.

This example has been extracted from network N2 in ha2.tdl, but that functionality has not been tested recently, so there might be errors in this example.

3. For a more complex network

refer to ha2.tdl (and associated ctc file) and look at N2.

How networks work (scripting perspective).

The NetInput tracks connect as usual to NetInput objects, and NetOutput objects connect conventionally to the NetOutput tracks. You can see variables associated with NetInput and NetOutput objects in the variables window. Variables names <Net name><trackName> are owned by the NetInput object, and <NetName>_<trackName> are owned by the NetOutput objects. When a route is selected, pointers are used to connect the NetInput and NetOutput objects. Intervening NetSwitches play no part in the exchange of data between objects - they are merely set when the route is setup.

How networks work (operating perspective)

When any approach track (declared in a NetInput directive) has a train on it that wishes to proceed into the network (ie the track state is Arriving or Occupied, but not Stopping) then the NetInput looks at the priority of the train and compares it to the priority of trains on, or booked to enter all the other NetInput lines of that network. If the train is (one of) the highest priority then that train is 'offered' to the network.

Many NetInputs may offer trains at the same time, only one is accepted by the network.

If a NetRoute sees a train (that is offered to the network) which matches the routes qualification class (if present), and all the 'uses' list are free and the routes qualification percentage is met then the NetRoute 'bids' for the train.

Many NetRoutes may bid for the train, the last one listed will win. This means that default routes (those with the shortest list of qualifications) should be listed first, and progressively less likely routes listed afterwards.

If a route wins then its NetSwitches are set to the specified direction, its NetInput and NetOutput are connected (by pointers in the script) and the train allowed to proceed. The network is immediately available to route another train if resources permit.

If no route bids then the NetInput will withdraw its bid, thus permitting other trains of equal priority to be offered. The approaching train has been 'rejected' by the network. It is possible that the train will be re-offered and accepted before it has to stop, the only visible effect this has is that the train approaches slowly, whereas if it were accepted immediately it would continue at full speed.

In order to remove the possibility of deadlock, each time a train is rejected its priority (as used by the network for the passage only) is reduced. This allows low priority trains to proceed if the only route available to the higher priority train is blocked.

When the train has fully passed into the destination track then the route is cleared, which means that the arrival track and all the resources used by the route become free.

Behaviours implemented

Collision avoidance

No train is allowed to enter a section that is not clear, and ready to accept that train. If optical sensors are used then trains may be of any length and as many sections as required are held busy while the train passes. If only current detectors are used then trains will slow and stop as soon as they enter a section if the next section is not clear. This means that every section must be long enough to hold the longest train. When calculating permitted train lengths, assume that the train ahead stopped quickly and the one behind stops more gradually.

Station stop

If a long section is flagged as a station stop ("stn") then trains may stop here. Most local trains will stop. Some passenger trains and a few express trains. Goods trains will only stop if the route ahead is blocked (but see passing loops also).

Calibrate

If a long section is flagged calibrate ("cal") then the time it takes for the train to travel the section is measured. The speed of the train may then be adjusted to suit its class (express trains run faster etc).

Passing loop

If a long section is flagged as a passing loop ("pass") then whenever a train arrives then all the parallel passing sections are examined. If any has (or is expecting) a higher priority train, then we will wait for it to pass.

Train priority

Turnins and networks with multiple arrival tracks will handle high priority trains before lower priority trains. Express > passenger > local > goods.

Controlled routing

Networks can define which classes of train can (and associate probabilities) traverse each route through the network. This can prevent goods trains ending up in a passenger terminus, or a passenger train in a goods siding.

Reverse out of sidings or halts.

If a halt (station that is not a terminus) or siding has a crossover behind the train (defined using a network) then a stopped train could either continue on its way, or use the crossover to travel on the other line back the way it came. If a siding has no crossover then the train can reverse out onto the previous section, and then carry on along the main line.

Startup speed calibration

At startup, if a track has an exit optical sensor and a train is drawing current and obscuring the sensor then reverse power will be applied, and increased gradually until the sensor is cleared. This power level is used as the minimum speed setting. It can be adjusted manually on the CTC panel. If the sensor starts clear then the same procedure is used with forward power until the sensor is obscured. If no optical sensors are available then (when the next section is ready) forward power is applied until the next section sees the train. The maxSpeedRange variable can be used to ensure that all train are given power values that are sane for your layout.

Siding length check

At startup all trains default to a length of 999 (any units you choose). As trains progress around the layout their length may be reduced in sections where lengths are defined. No train is allowed in any siding (any track connected at only one end) if it is too long. This implies that no train is allowed into any siding until it has been shown to fit. The value 999 may be changed setting BOTH defaultHead and defaultTail variables to non-zero values. Layouts using QTUs and dead-reckoning measure the length of each train directly as the (already calibrated) train passes over any optical sensor. There has to be at least one optical sensor for this to work.

Manual control panels.

By inserting tcl code in the tdl file you can take some measure of control. This is illustrated in jax9.tdl where a simple despatch panel is used to add new trains to the layout from a given siding. The despatch panel allows you to take manual control of the siding, add a new train, check it runs, request clearance to depart and then drive that train all around the layout until you release it to automatic control.

Planned future features

1. Centering trains in stations.

With dead-reckoning it should be simple to make all trains stop in the centre of a station, regardless of their length. This is a low priority at present, but should be an easy one when I feel keen.

2. More information in this file.

Currently there is no mention of the various stack commands which are used to associate inputs and outputs with connections on the hardware.

3. More configuration options.

Names of train classes. Speeds of each train class. More than 4 train classes.

4. Support for conventional PCC

If routing for more than 3 throttles per section is needed then adding it would be quite easy (and suppressing the automatic promotion to most preferred throttle).

5. Defining a route for a train.

I intend to allow each train to have a next destination. Turnouts and networks will route the train optimally to that destination. No automatically generated code will set the destination however as there are too many variables in how this should be used. Manual code inserts should be used to create your own desired results.

6. Auto-speed adjustment.

Currently non-dead-reckoning systems estimate speed based upon time between sensors, and adjust speed based upon class of train. This wasn't very reliable as the optical sensors often mis-read. I plan to change this to be based upon current detectors which are much more reliable, and to do the same for dead-reckoning systems. Min speed can also be controlled for systems with feedback throttles.

7. Train identification.

It would be nice to be able to know which train was which, from the computers perspective. For example to be able to say the train over there, bring it into this siding. This should be possible either on the glass panel, or on a (possibly portable) manual control panel. Possibilities include clicking on the screen or pressing a button on the appropriate track, or having a train ident displayed somewhere other than the computer screen.

8. Signalling.

Add multi-aspect automated signalling. Naturally this is unlikely to satisfy everyone and standards are different in different countries, railroads and eras, but simple 1, 2, 3 and 4 aspect signals shouldn't be too difficult. Especially now that Tcc supports multi-bit I/O

9. Automatic shunting

Loco run-around, loco replacement, hump sorting. I have proven the possibility with the uncoupling demo, sometime it has to happen on the real layout. Hump sorting might require barcodes, RFID or similar.