A conditional-priority signal controller runs a fixed two-phase cycle (North–South vs. East–West) with protected minimum green times. Buses on the N–S route carry a virtual check-in detector 35 m before the stop line:
on check-in:
if phase == NS_GREEN:
need = (stopDist / busSpeed) + clearance
if need > timeLeftInPhase:
extend = min(maxExtension - used, need - timeLeftInPhase)
greenEnd += extend // green-extension
elif phase == EW_GREEN and elapsed(EW_GREEN) >= minGreenEW:
truncate EW_GREEN now // early-green / red-truncation
Every vehicle obeys simple kinematics: it accelerates toward a cruise speed and brakes for a red stop line only once its kinematic stopping distance v²/2a exceeds the remaining distance to the line, with a car-following rule that keeps a safe gap behind the vehicle ahead. This is the same two mechanisms — green-extension and early-green — used by real active-TSP controllers (Opticom/GTT-style emitters, transit signal priority in NTCIP-based cabinets), traded off against a protected minimum green so cross-street traffic is never starved indefinitely.
- TSP toggle — turn conditional priority off to see the intersection run a plain fixed-time cycle instead.
- Bus headway — how often a bus enters the route; shorter headways mean more priority requests per cycle.
- Max green extension — the controller's hard cap on how long it will hold or pull forward the N–S green for one bus.
- E–W volume — cross-street car arrival rate; higher volume makes the delay trade-off from priority more visible.
- Strip chart below the map — a scrolling record of which approach has green (top band NS, bottom band EW) and when a priority grant fires (blue tick), so you can see the extension or truncation happen in real time.