Skip to content

Speedometer: Distance calculation breaks depending on routing/sign logic (station switches) #8

@StonDragon

Description

@StonDragon

Description

The current speedometer distance calculation is inconsistent and breaks depending on routing decisions made by TrainCarts, especially around station switches and junctions.

Observed behavior:

  • Some routes (e.g. BFS1 → BFS3) work correctly
  • Others (e.g. BFS3 → BFS2) stop calculating at junctions
  • Some (e.g. BFS2 → BFS1) stop immediately after leaving the station (before reaching the central junction)

This happens even when all blockers are removed, so the issue is not caused by blockers alone.


Expected Behavior

Distance calculation should:

  • Follow the actual rail path
  • Be independent of routing/sign logic
  • Work consistently for all directions between stations

Actual Behavior

Distance calculation currently:

  • Depends on handleRouting(...) and PathNode.findRoute(...)

  • Stops early when:

    • routeEvent.isBlocked() == true
    • no lastSetNode is found
  • Produces asymmetric results depending on direction and station logic


Root Cause (Analysis)

The current implementation relies on TrainCarts routing:

provider.handleRouting(...)
PathNode.findRoute(...)

This causes issues because:

  • Station switches contain logic like:

    • "if no destination → return to station"
    • "if empty train → different route"
  • Routing logic is interpreted as blocked paths

  • This affects distance calculation, even though the physical rail path exists

Result:

  • Distance calculation is tied to control logic, not track topology

Why This Is a Problem

The speedometer is intended to measure:

Remaining distance along the track

But currently measures:

Distance along allowed routing paths

These are not the same.


Proposed Solutions

✅ Option A (Recommended): Decouple from routing (Walker-based calculation)

Implement distance calculation using raw track traversal:

  • Use TrackWalkingPoint / TrackMovingPoint

  • Walk along rails step-by-step

  • Ignore routing decisions (handleRouting)

  • Stop when:

    • station is reached
    • destination marker is found

Advantages:

  • Stable
  • Direction-independent
  • Matches physical track layout

⚙️ Option B: Hybrid fallback

Keep current routing-based calculation, but add fallback:

double distance = getDistanceFromRouting(...);

if (distance == -1) {
    distance = getDistanceByTrackWalk(...);
}

This ensures:

  • existing logic stays intact
  • failures are handled gracefully

⚠️ Option C: Adjust routing environment (Not recommended)

Attempt to:

  • modify station switch logic
  • create routing-neutral context
  • adjust signals/blockers

Drawbacks:

  • fragile
  • complex
  • tightly coupled to TrainCarts internals

Additional Issues Found

1. Incorrect execution order in constructor

calcDistance(train);
calcVelocity(train);

Should be:

calcVelocity(train);
calcDistance(train);

Otherwise distance calculation uses incorrect velocity assumptions.


2. Early termination condition too aggressive

if (!walker.hasNext() || routeEvent.isBlocked() || routeEvent.getLastSetNode() == null) {
    return -1;
}

This causes premature termination in valid track scenarios.


Suggested Next Steps

  • Add debug logging for:

    • routeEvent.isBlocked()
    • lastSetNode
    • walker position
  • Confirm failure points (station switch vs junction)

  • Implement walker-based fallback

  • Gradually remove dependency on routing for distance


Summary

The speedometer currently depends on TrainCarts routing, which is influenced by station logic and signals. This causes inconsistent and direction-dependent distance calculations.

Solution: base distance calculation on actual track traversal, not routing decisions.


Wenn du willst, kann ich dir im nächsten Schritt direkt eine konkrete getDistanceByTrackWalk(...) Implementierung schreiben, die du 1:1 einbauen kannst.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions