RailCommand Blocks (Detection Blocks)

Last updated: August 27, 2026

Concept

A RailCommand detection block is a named run of track that the layout watches for occupancy. On the schematic a block is a single straight segment of cells: exactly 1 cell on its thin axis and at least 2 cells on its long axis, horizontal or vertical — never diagonal. Editors clamp every create and resize to this rule, so a square or 1×1 input resolves to a horizontal 2×1; import keeps a decoded sub-minimum span as-is and warns.

Each block carries a governed config: zero or more sensors that report occupancy, and markers that tell an approaching train where to brake or stop. A current sensor detects a length (drawn as a bar); a point sensor is a momentary IR/reed contact (a dot). Occupancy is the logical OR of the block's sensors — any active sensor recolours the whole block bar. Markers are classified purely by ramp: ramp above zero is a Brake marker, ramp of zero a precise Stop. It serves layout owners and editors configuring RailCommand, and operators reading block state in a session.

The operating engine enforces these markers for automated trains. A train arriving in its destination block no longer brakes at the block boundary: it holds speed until the brake point — a Brake marker's distance, or as late as its calibrated stopping distance allows before a Stop point — then decelerates to stop at the marker. A destination block with no markers keeps the original behaviour (braking begins the moment the block reports occupied), and any unresolvable configuration falls back to that same immediate braking — the safe direction. Markers imported from TrainController with an unconfirmed direction flag are applied in both travel directions until the flag semantics are confirmed, which can only make a train brake earlier, never later.

How To

Prerequisites: an imported or authored layout, and owner/editor access in the organization that owns it.

Review and configure blocks on the Block Editor page:

  1. Open /app/railcommand/layouts/{LayoutId}/blocks. Summary cards count Total, Well Configured, and Missing Detection blocks; filter by Track Class, Completeness, or Detection.
  2. Click a block row to expand its inline editor and set Block Name, Track Class, Direction, Unit and Total Length, Foul End A/B, Max Speed (mph), Restricted Speed, and the Electrified, Terminal, and Critical Section flags.
  3. In the Block Detail panel edit governed Length (inches), each sensor's kind (point, current, flagman, delayed action) with debounce and memory (ms), and each marker's distance and ramp (inches — the fields carry an in suffix and match the Length field's unit; values are stored internally in millimetres). A marker whose distance plus ramp runs past the end of its block is flagged "past end of block". The Block Detail panel is labelled "Changes here save immediately" and auto-persists, unlike the Cancel/Save fields above. Length is a single value: the Block Detail Length and the row's Total Length are the same measurement, kept in step whichever surface you edit (stored governed in centimetres, shown in the block's chosen unit). An imported block's decoded length shows in both without re-entry.
  4. Click Save to persist the row fields.

Edit geometry and per-block settings from the Layout Editor:

  1. Open /app/railcommand/layouts/{LayoutId}/editor. In Edit mode, double-click a block to open its Properties panel, then choose Open advanced settings… for the Block settings modal (tabs: Block, Block Editor, Speed & Rules, Conditions). In Simulate or Live mode, double-click opens the advanced modal directly. The Block Editor tab hosts the same Block Detail view, but changes here are staged with the rest of the modal: OK persists them and Cancel discards them. The Speed & Rules tab carries the block's rule flags — Release Rule, Routing Cost, Min Hold Time, Depart Delay, Permissive working, Out of service, and Dark territory (no detection by design). Drag-resize on the canvas or use the numeric span editor; both clamp to the geometry rule. A turntable or transfer-table cell routes through Properties to its own dedicated editor (tabs: General, Tracks, Connection, Display, Levels), not the block or turnout modal; its General tab also carries the authored physical startup position used by session-start reset. An indicator lamp cell (the band-15 indicator elements) routes the same way to its own small Lamp modal — display name, lens-colour override, and Flash when lit — and Open advanced settings… is the only path to it, because double-click opens the Properties panel rather than the modal.

In Edit mode the element palette is an overlay pinned to the canvas's left edge, so it sits on top of any blocks drawn there. Use the chevron in the editor header to collapse it and reveal those cells, and the same control to bring it back; leaving the editor is a separate Exit editor button, still guarded by the unsaved-changes prompt.

On the Layout Editor canvas, track is drawn at a line weight that follows its Track Class: Main is heaviest, then Branch, Staging, Interchange and Runaround, then Siding, Yard and Lead, with Industry spurs lightest. A cell whose class comes from its block inherits the block's weight, and a cell with no class resolved keeps the standard weight. This is an engineering-drawing convention and it is deliberately limited to the Layout Editor; the CTC dispatch panel keeps a single uniform weight for every class, because a period dispatcher's board draws to its own idiom rather than to a track chart. Changing a block's Track Class therefore changes how its cells are drawn on the editor, and does not change how they are drawn on the CTC panel.

On the canvas, turntable and transfer-table cells render through the same shared cell-producer path as other special cells: the renderer reads each one's saved configuration through the shared resolver, so a turntable's ring and a transfer-table's tracks draw from their stored config rather than a block's geometry. A cell still flagged Needs configuration draws its placeholder until you complete it in that editor.

Worked example: a 4-cell horizontal siding renders as a bar with one full-length current sensor and a Stop marker at its clearance point. Set the marker's ramp to 0 so it reads Stop, save, and confirm the Detection column shows a green check.

Troubleshooting

  • Missing Detection (red ✕) — the block has no resolved sensor. Add or resolve one in Block Detail; an unresolved indicator renders as a "missing sensor config" placeholder, never dropped.
  • "defaulted to current — confirm" — the sensor kind was not imported. Confirm point vs current; an untouched default is never written back.
  • "length not imported" / "positions spaced by order" — those values were not decoded. Set the length; sensor positions stay approximate (order-based).
  • Blocks along the left edge are hidden and panning will not reach them — the element palette is an overlay covering that strip, not a cause of missing blocks. Collapse it with the header chevron.
  • Cannot make a block 1×1 or diagonal — the geometry rule forbids it; the editor normalizes to a horizontal 2×1.
  • "past end of block" on a marker — the marker's distance plus ramp is longer than the block. Usually a unit mistake: these fields take inches, like Length. A TrainController value typed as millimetres lands the glyph at the far left of the bar.
  • Blocks you marked Out of service long ago have suddenly turned grey — expected, and the grey is the correct rendering. The web schematic reader looked for the flag under a different spelling than the editors write, so the Out of service checkbox has been inert on the schematic since it shipped; that mismatch was fixed on 2026-08-14. Any block already ticked out of service starts showing its out-of-service grey on the web schematic at that point without anyone editing it. Untick the flag if the block is back in service.
  • A block shows out-of-service grey on the web schematic but looks unchanged on the Avalonia desktop — expected for now. Only the web schematic draws the out-of-service state today, so the two surfaces disagree on that one block until the desktop grows the same treatment. Nothing is wrong with the block or the flag.
  • A block is out of service and dark territory, and shows grey rather than the dark neutral — out of service wins. The display order is out of service, then occupied, then reserved, then the dark-territory neutral, then free.
  • The Layout Editor modal's Block tab showed "Sensors (0)" and the name "Block" on an imported block — fixed 2026-08-18. That tab read a page-local copy of the block config whose field names did not match the governed ones the importer writes, so sensors, length and name all fell back to defaults. Worse, pressing OK wrote that default name back, renaming the block to "Block". The sibling Block Editor tab was always correct. If a block is currently named "Block" and should not be, rename it; the save path no longer blanks it.
  • Sensor addresses read as flat LocoNet numbers — a General-Input contact on board 109, input 3 shows as 1731 ((board - 1) x 16 + input), the same form BDL168 wiring sheets and JMRI use. The stored value is shown as imported and never recomputed, so a contact whose import did not decode cleanly shows its board rather than an invented address. A Plain-Number contact also shows its board, because its stored value carries a synthetic offset that is not an address on any sheet.
  • A sensor drawn as its own contact cell showed a blank address — fixed 2026-08-27. Those sensors keep their addressing on the drawn cell rather than in the block, and the import used to carry only the board onto that cell, so the address column had nothing truthful to show. The import now writes the board, the input and the flat value onto the cell, and one shared rule renders every sensor, so the Block Editor and the Layout Editor Block tab cannot disagree. An already-imported layout picks this up at its next connected sign-in, when the layout is re-derived from the backend; no re-import and no data migration is needed. A contact TrainController marked Without Connection still shows blank, because its stored address is stale and blank is the honest answer.
  • The flat address shows only when it was imported — a sensor you address by hand shows the board and input you entered, with no flat number beside them. RailScanPro does not calculate one, because the inputs-per-board figure depends on the digital system (14 on an NCE AIU, 16 on LocoNet) and that system is not yet recorded against each contact. Calculating one anyway would print the wrong number for anybody running more than one bus, so the honest answer is to show what was decoded.
  • Flagman sensor — its occupancy is computed by TrainController logic RailScanPro does not decode. Re-author it as a block rule (the panel links to Webb, the rules assistant).

Safety Notes

Blocks are authored and edited only on the web. Neither the web app nor the Avalonia desktop actuates hardware or drives trains — the desktop presents state and forwards operator intent, and the local/UE5 runtime owns all safety-critical execution (occupancy enforcement, interlocking, movement authority). Editing a block in the browser changes how the layout is modeled and displayed; it does not by itself power, move, or stop a train. During operation the occupancy recolour and the train-in-box name are indications, not controls: the head block shows the train name, while trailing straddle and reserved-ahead blocks recolour without it, and reservation is distributed before occupancy. Never treat a cleared block indication as authority to move — confirm with the operating runtime and procedure.