RailCommand Routes: Graph-Derived Paths and TrainController Verification

Last updated: July 8, 2026

Concept

A RailCommand route is a settable path across your layout. The key mental model (ADR-0230) is that the operable route set is DERIVED from the track graph — it is never hand-authored and never imported as source of truth. RouteDerivationService walks the graph from every track Block to every other Block, honoring each turnout's port model, and records the Closed/Thrown turnout positions that path requires. Because the routes come from the graph, they stay correct: any layout edit re-derives them, exactly like signal masts.

When you import a TrainController .yrrg file, RailCommand decodes its 150 route records but does not treat them as the route set. Instead the imported TrainController routes become a per-layout verification corpus — an independent ground truth used to prove the imported connectivity matches what TrainController believed. This is why the product reports things like "113/150 TC routes verified by graph derivation": the derived routes are checked against the imported corpus.

Separately, Interlocking Routes (the /routes page) are the signal-to-signal reservations a dispatcher sets and locks in a live session — with turnout settings, conflict detection, and a lock state.

How To

  1. Import and read the summary. After a TrainController import at /app/railcommand/layouts/import/traincontroller, the result summary reports "N derived routes (M TC verification routes)" and, below it, the conformance line: e.g. 113/150 TC routes verified by graph derivation (37 underivable, 27 derived-but-not-in-TC). The line is green when nothing is underivable, amber when some routes are.
  2. Read the verdicts. Each corpus route carries a verdict: Matched (a derived route confirms that connectivity), Underivable (no derived equivalent — the detail names the exact endpoint blocks and turnout cells), and the informational derived-but-not-in-TC count (routes your graph supports that TrainController's set simply did not list — not a defect).
  3. Manage interlocking routes. Open Interlocking Routes at /app/railcommand/layouts/{LayoutId:guid}/routes. The cards show Total Routes, Active, and Conflicts Detected; filter by All / Active / Inactive. Each row lists Name, Entrance / Exit Signal, Turnouts, Speed, Status, and Lock. Use + New Route to open the builder at .../routes/builder.
  4. Set and lock a route in operate. In a live session from the CTC panel (.../ctc-panel), press Set Route to request-and-lock an interlocking route (a conflict-checked turnout and block lock) and Release to unlock it. The Routes page Lock column reflects the current lock state.

Troubleshooting

  • Conflicts Detected is red / a route has a red dot. Two routes demand incompatible turnout or block states; they cannot be locked together. Edit one route or release the conflicting one.
  • A TrainController route shows Underivable. The graph cannot confirm that path. Check the localized endpoints and turnout cells in the detail — common causes are a severed track ladder at a panel edge or a turntable leg (turntable bridge-to-track routes are a known, honest capability gap, not a bug).
  • Fewer derived routes than expected. Path enumeration is bounded; if a cap was hit, a loud warning names the specific block pair. Re-derive after fixing connectivity, or raise the derivation limits.
  • Set Route fails in the CTC panel. The requested route conflicts with an already-locked route, or the session is not ready (CTC readiness blockers must be cleared first).

Safety Notes

The web app is where you author and verify — derive routes, read conformance, and define interlocking routes. It does not actuate hardware. The Avalonia desktop presents live state and forwards operator intent; it does not drive trains. The local/UE5 runtime owns all safety-critical execution — interlocking conflict enforcement, movement authority, and physical turnout and signal actuation happen there, never in the browser or desktop. Setting or locking a route grants an authority window; it never itself moves a train. Treat a "verified" conformance result as an import-connectivity check, not an operational safety certification: a green verdict does not replace testing routes against your physical hardware before an operating session.