JMRI: Block Tracking
Background Information
Model railroad control systems generally can't tell you which train occupies a particular piece of track at any given time.This is unfortunate, because there are lots of reasons you might want to know. For example, you might want to command any train that reaches a particular red signal to stop. But you can't do that unless you know which train it is that is reaching the signal.
Basic Concepts
Imagine a simple loop of track that's been wired with occupancy sensors on individual segments of track, which we'll call "Blocks". Imagine the train is in Block A, and will shortly move to Block B, then C.At first the sensor for Block A is showing active. As the train moves into Block B, the Sensor for B will go active. When the train has completely left A, it's sensor will go inactive etc.
Although a particular Block only knows whether it's active or not (occupied or not), by also looking at the occupancy of the adjacent Blocks it can tell more. In the example above, if the code knew that train 321 was in Block A, when Block B goes active, the program can infer that 321 is now also in Block B.
This doesn't always work, unfortunately. Imagine the case above, where there is both a train in Block A and also a train in Block C. When Block B goes from inactive to active (unoccupied to occupied), which train moved in? The one from A, or the one from C?
Some of this ambiguity can be removed by careful arrangement of the detection Blocks, by accepting limitations on how trains can run (or how short Blocks have to be), and by using more intelligent logic that thinks about the direction and priority of trains. But it's clear that even straight track poses some problems.
JMRI Block Tools
The Block table entries include a Value field. The contents of the field will be copied to the next block using block tracking. The content of the value field can come from several sources.
- Text is entered directly in the Block table.
- Double clicking on a Block Contents icon on a Panel Editor or Layout Editor panel and entering text.
- Using a script or LogixNG to set a value.
- Use the Dispatcher options to place names or roster entries in the starting block.
- If a Reporter is assigned to the block, it can provide a value.
- Use the SetBlockValues.py script to request block values as needed. Note: There is setup work needed to enable this feature. The details are in the script comments.
blockvalues.xml
Block values are not stored with the rest of the layout data. The blockvalues.xml file is used to provide persistence of the block values between PanelPro sessions.
During the PanelPro shutdown, the current values of occupied blocks is written to the blockvalues.xml file.
After PanelPro startup and layout data loading is complete, the values are read from the blockvalues.xml file and applied to the blocks based on a set of rules. The rules are based on the Block Table Values menu.
Block Tracking Messages
There are two messages displayed on the JMRI system console when block tracking is paused.
WARN - count of 2 ACTIVE neighbors with proper direction can't be handled for block B-Alpha-Main but maybe it can be determined when another block becomes free
INFO - Block B-Alpha-Main gets LATE new value from B-Alpha-Left, direction= East
As described above, a block becoming occupied between two occupied blocks can be a problem. Which block should provide the block value? There are two scenarios based on the current direction for each block. Note: Block directions are compass directions.
- Same Direction
-
Both blocks have the same general direction, ±45°. The new value comes from the following block. The messages are not displayed.
- Different Direction
-
The new value comes from whichever neighbor block becomes unoccupied. This is treated as the train has finished arriving. Note: This does not work when two trains are chasing each other in a circle with a limited number of blocks. At least eight blocks are required with no more than 45° per block.
Issues
- Doesn't handle a train pulling in behind another well:
- When the 2nd train arrives, the Sensor is already active, so the value is unchanged (but the value can only be a single object anyway)
- When the 1st train leaves, the Sensor stays active, so the value remains that of the 1st train
- The assumption is that a train will only go through a set turnout. For example, a train could come into the turnout Block from the main even if the turnout is set to the siding. (Ignoring those layouts where this would cause a short; it doesn't do so on all layouts)
- Does not handle closely-following trains where there is only one electrical Block per Signal. To do this, it probably needs some type of "assume a train doesn't back up" logic. A better solution is to have multiple sensors and Block objects between each signal head.
- If a train reverses in a Block and goes back the way it came (e.g. b1 to b2 to b1), the Block that's re-entered will get an updated direction, but the direction of this Block (b2 in the example) is not updated. In other words, we're not noticing that the train must have reversed to go back out.