OpenLCB: Train Control Protocol

This document defines a protocol for the control of model trains.

Environment of Protocol

Requirements

Preferences

Design Points

Trains will be addressed using a well-known addressing scheme. See TODO

All communications will be point-to-point, between a controller and a train.

A controller is any OpenLCB Node that might need to control a train; controllers includes hand-held cabs, computer control systems, or decentralized control units (such as auto-reversers for automated operation, or ATC systems).

A train is any model that runs on rails (i.e. is not steerable; thus, a train might include vehicles using the Faller or Tomix car systems). A train might be a single locomotive, a locomotive with carriages (e.g. passenger cars with interior lighting or markerlights that can be digitally controlled), a consist of multiple locomotives, a multiple unit, etc. Take, for example a model of the Usui Pass in Japan, ca. 1970. Electric multiple units that wished to traverse the pass (either up or down) needed to be assisted by a matched pair of EF63 electric locomotives. In this scenario, there are several potential train objects: The EMU by itself (being permanently consisted, the individual carriages would not count as trains in the sense being used here), each individual EF63, the EF63s in a paired consist, and the entire EF63+EF63+EMU consist are all train objects.

The head of a train is the node with control. In the case of a single locomotive, that train is its own head. In the case of a consist of multiple trains, the train at the very front in the forward direction of travel is the head.

Protocol

NodeIDs for Legacy Train Control Systems

Train Command Stations designed to act as a bridge between an OpenLCB network and a train control network, and hence that provides proxy OpenLCB Nodes to stand in for Trains unable to represent themselves, should adhere to the following schema for generating OpenLCB NodeIDs, as existing trains are unable to generate or provide these addresses for themselves. See OpenLCB Standard "OpenLCB Unique Identifiers", §5.5 for additional details.

byte 1 byte 2 byte 3 byte 4 byte 5 byte 6
0x06 [TCS ID] [DCS ID1] [DCS ID2] [Train ID1] [Train ID2]

Where:

Command Summary

All communications via the Train Control Protocol use the Datagram transport method. Each datagram consists of an PTI (protocol type identifier) byte, which is 0x30 for the Train Control Protocol, a command identifier byte, and zero or more bytes of command-specific data:

Command

Command Identifier Byte

Arguments

Emergency Stop

0x00

Set Train Speed

0x01

direction and speed (16-bit float)

Inquire Train Speed

0x03

kind of speed (8-bit flags)

Report Train Speed

0x02

kind of speed (8-bit flags)

direction and speed (16-bit float)

Set Train FX

0x11

FX address (16-bit uint)

FX setting (16-bit uint)

Inquire Train FX

0x13

FX address (16-bit uint)

Report Train FX

0x12

FX address (16-bit uint)

FX setting (16-bit uint)

Request Attach to Train

0x21

Attach Permitted

0x22

Attach Denied

0x24

Train Release

0x23

Controller Dropped

0x26

Create Consist

TODO

TODO

Add to Consist

TODO

TODO

Set Consist Head

TODO

TODO

Remove from Consist

TODO

TODO

Destroy Consist

TODO

TODO

Train Movement

Summary: Commands for controlling the movement of trains.

Notes on the table columns:

Command Direction Controlled? Protocol Identifier Byte Command Identifier Byte Arguments
Byte 1 Byte 2 Byte 3 Byte 4 Byte 5

Emergency Stop

C→T

yes

0x30

0x00

Set Train Speed

C→T

yes

0x30

0x01

direction and speed (float16)

Inquire Train Speed

C→T

no

0x30

0x03

kind of speed (8-bit flags)

Report Train Speed

T→C

n/a

0x30

0x02

kind of speed (8-bit flags)

direction and speed (float16)

Emergency Stop

Bring the train to an immediate halt, without regard to any physical simulation of momentum. Notice that this command is supplementary to the more general OpenLCB commands TODO, with the difference being primarily one of scope.

Set Train Speed

The speed and direction to set is encoded as a half-precision floating point number (aka 'float16'), with positive numbers indicating forward direction, negative indicating reverse, and zero indicating full (non-emergency) stop. The value specifies a speed in scale meters per second (scale-m/s).

Rationale: The use of a 16-bit floating point permits relatively precise speed commands, especially at lower speeds; such fine granulatity ensures not just fine-grained control over the locomotive, but helps avoid aliasing issue that arise during the conversion to lower resolution system-specific speed commands (i.e. DCC's 14 or 28-step commands).

The use of meters per second is somewhat arbitrary, and reflects standard velocity units used throughout the metric-speaking world. By standardizing on m/s, we avoid any future unit conversion issues.

The use of scale meters per second has two distinct advantages. First, it permits us to transmit speed commands in a scale-independent way. Second, and because of this, it reduces the number of parameters that must be estimated when controlling a locomotive that has not yet been speed-calibrated (which, for new users using existing digital control systems, will be all of their models). For example, on a DCC system, if I issue a command to proceed at 30mph, the command station must convert the value in the speed command from 30mph to an interger in the range [0-26] (for 28-speed-step control). The command station need only estimate what a reasonable top speed for a locomotive might be: Let us say, 100mph. Thus, the command station could reasonably estimate that 30mph translates to speed step 8.

The alternative possibilities considered to date are absolute speed using real units (as opposed to scale units), and relative speed units. The difficulty with relative speed units (i.e., percentage of full throttle), is that TODO. The difficulty with using real (as opposed to scale) units is that it requires the estimation of an additional parameter for uncalibrated locomotives, specifically the train's scale. If I issue a command to a DCC locomotive to proceed at 0.1 (real)m/s, the command station must not only understand what a reasonable top speed for a train is, but how to scale the speed appropriately, as 0.1 m/s might be quite fast for Z scale, but quite slow for G. As there is really no reasonable scale to use as a default, users must configure their digital command station to set the scale for either the entire layout, or on a per-model basis—an additional configuration step that is easily avoided by the mechanism for scale units described above.

Inquire Train Speed

This is a request for a train to report its speed. Any OpenLCB node may make inquiries about a train's state without requesting permission first (see Security Commands below), although the train is under no particular obligation to respond. This command takes no additional arguments.

Of course, a request for a train's speed is itself ambiguous. The controller might be interested in knowing any of a number of possible measures: What speed the train has been commanded to take; what speed the train is attempting to reach; what speed the train is actually travelling at. Thus, a speed inquiry requires a parameter to indicate the interests of the controller:

Speed Kindcommand argument
Commanded speed0x00
Intended speed0x01
Actual speed0x03

Report Train Speed

This is a response to the Inquire Train Speed command, and combines the arguments to the Set Speed and Inquire Speed commands, returning both the kind of speed being reported using the same flags as above, and the speed itself as a float16.

Train FX

Summary: Commands for controlling a train's special effects, including lighting and sound.

Notes on the table columns:

Command Direction Controlled? Protocol Identifier Byte Command Identifier Byte Arguments
Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6

Set Train FX

C→T

yes

0x30

0x11

FX address (uint_16)

FX value (uint_16)

Inquire Train FX

C→T

no

0x30

0x13

FX address (uint_16)

Report Train FX

T→C

n/a

0x30

0x12

FX address (uint_16)

FX value (uint_16)

Set Train FX

Many trains offer independent control of various special effects (FX, sometimes called "functions") such as lighting or sound. This command permits a controller to control these effects directly. The first argument is the address of the FX to control as a 16-bit unsigned integer. This protocol does not define a semantics for FX addresses; that is, there is no particular address that is singled out as represenging headlights or the airhorn. Instead, the addresses are deliberately abstract, permitting the user to decide how to map addresses to FX for each train.

Additionally, each FX can take a 16-bit value. Current technology only permits binary FX; thus 0x00 should be interpreted as "off" for a binary FX, and any non-zero value as "on". Analog (non-binary) FX should treat the 16-bit value as an unsigned integer.

Rationale: Most digital systems offer multiple FX, each of which is numbered. Although currently most DCC throttles only permit access to 12 or 29 functions, DCC (TODO to my knowledge!) technically permits as many as 32796* different binary FX (see RP-9.2.1: Function Group One Instruction, Function Group Two Instruction, and Feature Expansion Command Instruction especially the Binary State Control Subcommand). For this reason, it seems prudent to go ahead and use a 16-bit value.

Likewise, although current DCC decoders only permit binary FX, some (for example SoundTraxx Tsunami sound decoders) actually permit a kind of analog control of FX by combining multiple DCC Functions. Thus, it seems likewise prudent to permit a wide range of values, and not simply a binary on and off.

One problem that faces the decision to use a single command with a numerical FX addressing system is that any kind of standardized assignment of FX addresses to particular FX is impossible in practice. DCC, for example, makes no such prescription, although by convention function F0 controls direction-sensitive headlights. Beyond this lies only manufacturers' conventions. Thus, any kind of mapping is best handled on a per-train basis, by configuring the mapping between particular FX (e.g. headlights, airhorn) to FX addresses for each train.

One way to mitigate this problem is to not make fixed FX address assignments, but to map them directly onto the addressing scheme used by the various control systems, that is, to leave each address in the OpenLCB FX addres space uninterpreted. In this way, the default behavior of each address will map directly onto the default behavior of the decoder in the train, giving some degree of predictability to the system, and permitting a digital command station the make reasonable guesses about the possible address-to-FX mappings. Nevertheless, users will often need to be exposed to this implementational detail, which is deeply unfortunate, but necessary given the ultimate flexibility of current train control systems.

Thus, it is recommended that the FX address space be mapped directly to the particular control system's address space; thus DCC F0 becomes FX address 0x0000, F1 becomes 0x0001, etc. The DCC Binary State addresses should be mapped to 0x8000 to 0xFFFF (i.e., to the 15-bit range beginning with 0b1000.0000.0000.0000). Other systems should be handled analogously.

*RP-9.2.1 defines the following:
Function Group One: 5 (F0-F4)
Function Group Two: 8 (F5-F12)
Binary State Control: 32767 (15bits) (note: different address space!)
Feature Expansion Command 11110: 8 (F13-F20)
Feature Expansion Command 11111: 8 (F21-F28)
And in the future, perhaps even more. Possibly a lot more. There are just under 20bit of address space available in the Feature Expansion Comman Instruction for the potential manipulation of Binary State Controls.

Inquire Train FX

Any node may inquire the state of a train's FX. The only argument is the address of the FX to query.

Notice that, because the semantics for the FX address space may vary from train to train, this command does not provide a useful way to query the state of a particular FX, e.g. the headlights.

Report Train FX

This command is for trains to report the state of a particular FX in response to an Inquire FX command. The format of the parameters is the same as for the Set Train FX command.

Consisting

TODO Create Consist Add To Consist Remove From Consist Destroy Consist Consisting Acknowledged Consisting Denied

Train Access Control

Optional. Trains may restrict communications from controllers using the following packet kinds.

TODO Attach Request Attach Acknowledged Attach Denied Command Denied?