Autonomous Urban Mobility Control via Dueling Double Deep Q-Networks (D3QN), Prioritized Experience Replay (PER), Online Short-Horizon EWMA Demand Forecasting, Zero-Latency Live Video Ingestion (YOLOv8 + ByteTrack + yt-dlp), and Full-Stack Telemetry Analytics
FlowSync is an enterprise-grade, real-time traffic simulation, optimization, and digital twin platform. Engineered with a 28-dimensional state space, Dueling Double Deep Q-Networks (D3QN) with Prioritized Experience Replay (PER), destination-aware Max-Pressure (PressLight/MPLight) reward formulations, and real-world computer vision ingestion pipelines, FlowSync dynamically optimizes traffic signal phases to eliminate congestion, minimize vehicle delay, and maximize throughput across single 12-movement intersections, multi-intersection 2×2 city grids, and live CCTV / YouTube camera feeds.
| Dimension | Quantifiable Metric |
|---|---|
| Deploy payload (backend) | ~2.5 GB CUDA bundle → ~192 MB CPU-only (~13× smaller) via torch==2.3.1+cpu pin |
| Real-time telemetry | 10 Hz WebSocket streaming with 20-frame rolling sparkline history |
| Control problem | 28-D state vector → 4 signal phases across 12 turning movements |
| Fair evaluation | 3 controllers (Fixed / Greedy / DQN AI) on locked-seed paired runs, DQN evaluated first |
| Learning efficiency | PER buffer of 100k transitions, batch 128, |
| Network scale | 4-intersection 2×2 grid, 8 boundary demand portals, 3-mode benchmark runner |
| Quality gates | Strict TypeScript (tsc clean), pytest suite spanning api / rl / simulation / realworld / analytics |
- Key Metrics at a Glance
- 1. Executive Overview & System Engineering
- 2. System Architecture & Dataflow
- 3. Reinforcement Learning Mathematical Formulation
- 3.1 Semi-Markov Decision Process (Semi-MDP) Framework
- 3.2 28-Dimensional Continuous State Space Vector
- 3.3 Discrete Action Space & Demand Action Masking
- 3.4 Delay-Anchored Max-Pressure Multi-Factor Reward Function
- 3.5 Dueling Double Deep Q-Network (D3QN) Architecture
- 3.6 Double DQN Target Formulation with Masked Action Selection
- 3.7 Prioritized Experience Replay (PER with Binary SumTree)
- 3.8 Real-Time Online EWMA Demand Forecaster (Dims 20–27)
- 4. Safety Watchdogs & Physical Kinematics
- 5. Multi-Intersection 2×2 City Grid Coordination
- 6. Computer Vision & Real-World Digital Twin Pipeline
- 7. Analytics, Evaluation Metrics & Dashboard Intelligence
- 8. Directory Structure & Tech Stack
- 9. Installation & Environment Setup
- 10. REST & WebSocket API Specifications
- 11. Empirical Benchmarks
- 12. Recent Engineering Updates
- 13. License
Modern municipal traffic systems depend predominantly on fixed-time cycle plans (Webster's method) or inductive loop vehicle-actuated timers. These legacy paradigms suffer from three structural flaws:
- Inability to anticipate non-stationary surges: They react only when vehicles are already queued over physical hardware detectors.
- Phase green wastage: Fixed allocations hold green lights over empty corridors while adjacent approaches experience high delays.
- Network spillback (gridlock): In multi-intersection corridors, local optimizations trigger downstream arterial overflow, blocking entire city grids.
FlowSync replaces heuristic timers with an autonomous, real-time reinforcement learning control plane and high-fidelity 3D digital twin platform.
┌────────────────────────────────────────────────────────┐
│ FlowSync Control Plane │
└───────────────────────────┬────────────────────────────┘
│
┌─────────────────────────┴─────────────────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Simulated World │ │ Real-World Video │
│ (Three.js WebGL) │ │ (CCTV / YouTube) │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ 10 Hz State Vector │ YOLOv8 + ByteTrack
▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ State Space Formulation s_t ∈ ℝ²⁸ │
│ • 12 Movement Queues • 4 Signal Context Features │
│ • 4 One-Hot Active Phase Bits • 8 EWMA Demand Forecast Features │
└──────────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Safety Watchdog & Demand Action Masking │
│ • Anti-Starvation Timer (t_wait ≥ 45s) │
│ • Minimum Green Guard (8s) & Yellow/Red Clearance (2s + 3s) │
│ • Max Green Ceiling (40s) │
│ • Active Demand Mask: M(s) = {a ∈ A | Queue(a) > 0} │
└──────────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Dueling Double Deep Q-Network (D3QN) Inference (0.45ms Latency) │
│ Q(s, a) = V(s) + [ A(s, a) - 1/|A| ∑ A(s, a') ] │
└──────────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Actuation & Telemetry Sync │
│ • Single Intersection & 2×2 City Grid Signal Actuation │
│ • Real-Time Telemetry over 10 Hz WebSockets │
│ • Supabase PostgreSQL & Cloud Storage Model Sync │
└─────────────────────────────────────────────────────────────────────┘
We model urban traffic junctions as continuous-state, discrete-action reinforcement learning environments. FlowSync controls:
-
Single 4-way intersections: 12 distinct turning movements (North, South, East, West
$\times$ Straight, Left, Right). -
2×2 City Grids: 4 interconnected signalized intersections (
$A, B, C, D$ ) handling internal arterial transfers and 8 external boundary portals. - Sim-to-Real Replay Showdowns: Live video feeds from YouTube and CCTV streams are transcribed into millisecond-accurate vehicle arrival schedules and replayed in 3D physics to evaluate AI vs. Fixed vs. Greedy policies under identical conditions.
-
Neural Policy: Dueling Double DQN (D3QN) separates state value estimation
$V(s)$ from movement advantages$A(s, a)$ . -
Temporal Memory: Prioritized Experience Replay (PER) using a binary SumTree samples hard, high-error transition states with
$O(\log N)$ complexity. - Predictive Horizon: An online Exponentially Weighted Moving Average (EWMA) arrival forecaster feeds 8 predictive dimensions into the agent's observation vector, enabling the policy to act before physical queues build up.
- Destination-Aware Max-Pressure (MPLight/PressLight): The reward function rewards queue dissipation while penalizing downstream road occupancy, preventing arterial spillback.
-
Zero-Latency Ingestion: A multithreaded frame-grabber flushes socket buffers continuously, bypassing HLS network lags and anti-bot verification challenges via
yt-dlp.
- High-Fidelity 3D Diorama (
/simulation): WebGL scene rendered via Three.js and React Three Fiber featuring procedural reflective architecture, directional lane markings, dynamic holographic queue counters, animated CCTV cones, and real-time vehicle kinematics. - Multi-Intersection 2×2 City Grid (
/city): A 4-intersection metropolitan grid with arterial corridor traffic, continuous vehicle heading interpolation, and automated 3-mode comparative benchmark runners. - Real-World CCTV & Sim-to-Real Digital Twin (
/realworld): Video upload and live YouTube stream ingestion with an interactive HTML5 Canvas polygonal ROI editor, live bounding-box overlays, and side-by-side 3D arrival replay showdowns. - Executive Analytics Dashboard (
/dashboard): Aggregated metrics across sessions, Highway Capacity Manual (HCM) Level of Service (LOS A–F) classifications, mode showdown graphs, directional distributions, and deep links into 3D replays.
-
10 Hz Microscopic Physics Loop: Discrete time-stepping (
$\Delta t = 0.1\text{s}$ ) modeling vehicle acceleration ($0.12$ units/s), safe distance enforcement ($d_{\min} = 0.08$ ), yield-on-left rules, and cubic Bezier curve turning paths. - Semi-MDP Decision Gate: Decisions are executed only on valid decision steps (stable green signals after minimum green clearance), excluding transient yellow/all-red phases.
- Synchronized Dual-Path Lifecycle: Simulation pause and stop commands synchronize across both WebSocket channels and REST HTTP fallbacks. Pausing freezes vehicle movement on the 3D canvas and halts telemetry accumulation without clearing the scene.
-
Cloud Persistence: Checkpoint weights are serialized to
.ptfiles, upserted to Supabase Storage bucketmodel-checkpoints, and cataloged in PostgreSQL.
FlowSync uses an asynchronous, decoupled architecture separating client rendering from server-side physics simulation and neural network inference:
graph TB
subgraph Client ["Frontend — Next.js 16 (React 19 / TypeScript / GSAP)"]
UI["App Router UI / Dashboard<br/>(/dashboard, /simulation, /city, /realworld)"]
Canvas["3D WebGL Canvas<br/>(Three.js / React Three Fiber / Drei)"]
Zustand["Global State & WS Stores<br/>(Zustand 5.0)"]
Charts["Analytics & Benchmark Panels<br/>(Recharts 3.8 / GSAP 3.15)"]
ROI["Polygonal ROI Canvas Editor<br/>(HTML5 Canvas / Shapely)"]
end
subgraph Backend ["Backend — FastAPI 0.115+ (Python 3.11)"]
WS_Router["WebSocket Connection Managers<br/>(10 Hz JSON Streaming)"]
REST_Router["REST API Endpoints<br/>(/simulation, /training, /cctv, /analytics)"]
subgraph Engine ["Simulation Engine"]
Intersection["Single Intersection (12 Movements)"]
CityNetwork["2×2 City Grid (4 Intersections)"]
Signal["Traffic Signal Controller<br/>(Safety Watchdog & Clearance)"]
Spawner["CRN Poisson Spawner"]
end
subgraph AI ["AI Brain (PyTorch 2.3+)"]
SimAgent["Inference Agent (D3QN)<br/>(Demand Action Masking)"]
TrainAgent["Training Agent (D3QN)"]
PER["Prioritized Replay Buffer<br/>(SumTree O(log N))"]
Forecaster["ArrivalForecaster<br/>(Online 8-D EWMA)"]
Trainer["Async Trainer Loop"]
end
subgraph Vision ["Real-World Vision & Stream Pipeline"]
StreamRes["StreamResolver<br/>(yt-dlp Anti-Bot Bypass)"]
Grabber["RealtimeFrameGrabber<br/>(Zero-Lag Threaded Buffer Flush)"]
YOLO["Ultralytics YOLOv8<br/>(best.pt / yolov8n.pt / ONNX)"]
Tracker["ByteTrack Tracker"]
Quadrant["Quadrant Counter & ROI Manager"]
Recorder["Session Recorder & Arrival Scheduler"]
end
end
subgraph Data ["Data & Persistence — Supabase"]
Postgres[("PostgreSQL Database<br/>(Simulations, Episodes, Metrics)")]
Prisma["Prisma ORM 6.19<br/>(Client Server Actions)"]
Storage["Supabase Storage Buckets<br/>(model-checkpoints, cctv-sessions)"]
end
UI --> Zustand
Zustand -->|"WebSockets (10 Hz)"| WS_Router
WS_Router --> Zustand
UI -->|"HTTP REST"| REST_Router
REST_Router --> UI
Zustand --> Canvas
Zustand --> Charts
WS_Router --> Engine
WS_Router --> SimAgent
REST_Router --> Vision
REST_Router --> Storage
REST_Router --> Postgres
StreamRes --> Grabber
Grabber --> YOLO
YOLO --> Tracker
Tracker --> Quadrant
Quadrant --> Recorder
Engine --> SimAgent
SimAgent --> Engine
Engine --> Forecaster
Forecaster --> SimAgent
Trainer --> TrainAgent
TrainAgent --> Trainer
TrainAgent --> PER
PER --> TrainAgent
Trainer -->|"Periodic Sync"| SimAgent
Trainer -->|"Save Checkpoint"| Storage
Recorder -->|"Twin Data JSON"| Engine
Backend -->|"Async Telemetry Logs"| Postgres
Prisma -->|"Read Analytics"| Postgres
FlowSync uses dedicated WebSocket pipelines operating at 10 Hz (
| WebSocket Endpoint | Rate | Payload Description | Direction |
|---|---|---|---|
/ws/simulation |
10 Hz | Vehicle relative coordinates |
Bidirectional |
/ws/city |
10 Hz | Coordinated state for Intersections A, B, C, D, road segment transfer vehicles, total city throughput, arterial corridor travel times, and benchmark runner status. | Bidirectional |
/ws/training |
Event | Per-episode RL training metrics: total episode reward, moving average wait time, throughput count, Bellman loss, epsilon decay curve, watchdog override rate, and checkpoint upload alerts. | Bidirectional |
/ws/cctv |
2 Hz | Base64-encoded annotated JPEG frames, detected vehicle bounding boxes, tracking IDs, quadrant approach counts, and live vehicle arrival logs. | Bidirectional |
To prevent desynchronization between the frontend Three.js scene and backend physics:
[User Clicks "Stop"]
│
├─── 1. WebSocket Send: {"command": "stop"}
└─── 2. HTTP Fallback: POST /api/simulation/stop
│
▼
[Backend simulation_ws.py & simulation.py]
• Sets is_running = False
• Halts physics tick loop (dt = 0.0)
• Freezes vehicles at current position x_i
• Retains all lane queues in memory
• Freezes telemetry accumulation
• Broadcasts {"type": "simulation_stopped"}
│
▼
[Frontend IntersectionScene.tsx & Zustand Store]
• Receives simulation_stopped
• Freezes canvas rendering loop
• Retains existing vehicle 3D meshes on canvas (No wipeout)
• Updates UI button state to "Start"
- Stop / Pause (
stop): Halts the internal ticker; freezes vehicle positions; retains 3D vehicle meshes in their exact positions on the canvas; halts metric accumulation; leaves the intersection state intact so it can be resumed. - Start (
start): Setsis_running = True; resumes the 10 Hz physics ticker from the current state. - Reset (
reset): Wipes the vehicle pool; resets the timestep to 0; resets the signal controller to Phase 0 (North-South Green); clears all metrics, queues, and arrival accumulators back to baseline.
Traffic signal control with clearance intervals is formalized as a discrete-time Semi-Markov Decision Process (Semi-MDP):
-
$\mathcal{S} \subset \mathbb{R}^{28}$ : Continuous observation space. -
$\mathcal{A} = {0, 1, 2, 3}$ : Set of signal phases. -
$\tau \ge \tau_{\min}$ : Phase duration. Once an action$a_t$ is selected, the signal must maintain green for a minimum guard duration$\tau_{\min} = 8.0\text{s}$ , followed by yellow ($2.0\text{s}$ ) and all-red ($3.0\text{s}$ ) clearance transitions when switching. -
$\gamma = 0.97$ : Discount factor for cumulative future returns.
At each decision step, the environment constructs a normalized continuous state vector
Index: 0 11 12 15 16 17 18 19 20 27
Vector: [ 12 Movement Queues | 4-Phase | Signal Context | 8 Demand Forecast ]
| Indices | Vector Component | Range | Mathematical Definition | Physical Interpretation |
|---|---|---|---|---|
0 – 11
|
12 Movement Queues | Normalized vehicle count waiting in each canonical movement: North, South, East, West |
||
12 – 15
|
Active Phase One-Hot | One-hot indicator of currently active green phase. | ||
16 |
Phase Elapsed Time | Proportion of maximum green ceiling consumed. | ||
17 |
Transition Indicator | Indicates active clearance interval ( |
||
18 |
Normalized Net Pressure | Intersection-wide destination-aware pressure. | ||
19 |
Max Approach Starvation | Longest approach wait time normalized by the 45s starvation limit. | ||
20 |
5s EWMA Arrival Rate | $\min\left(1.0, \frac{\text{ewma}{5\text{s}}}{\lambda{\max}}\right), \quad \lambda_{\max} = 2.0\text{ veh/s}$ | Short-horizon burst arrival velocity. | |
21 |
10s EWMA Arrival Rate | $\min\left(1.0, \frac{\text{ewma}{10\text{s}}}{\lambda{\max}}\right)$ | Intermediate-horizon arrival velocity. | |
22 |
20s EWMA Arrival Rate | $\min\left(1.0, \frac{\text{ewma}{20\text{s}}}{\lambda{\max}}\right)$ | Long-horizon baseline arrival velocity. | |
23 |
Demand Growth Rate | $\text{clip}\left(\frac{\text{ewma}{5\text{s}} - \text{ewma}{20\text{s}}}{\lambda_{\max}}, -1.0, 1.0\right)$ | Derivative of demand; positive indicates an incoming vehicle platoon. | |
24 |
Platoon Burst Flag | $\mathbb{I}(\text{ewma}{20\text{s}} > 0.05 \land \text{ewma}{5\text{s}} > 1.5 \times \text{ewma}_{20\text{s}})$ | Triggers when instantaneous flow surges 50%+ over baseline. | |
25 |
Queue Dissipation Flag | $\mathbb{I}(\text{ewma}{20\text{s}} > 0.05 \land \text{ewma}{5\text{s}} < 0.5 \times \text{ewma}_{20\text{s}})$ | Triggers when arrival rate drops below half of baseline. | |
26 |
Signed Demand Trend | $\text{clip}\left(\frac{\text{ewma}{10\text{s}} - \text{ewma}{20\text{s}}}{\lambda_{\max}}, -1.0, 1.0\right)$ | Medium-term momentum indicating macro surge vs. drain. | |
27 |
Instantaneous Arrival Rate | Immediate arrival pulse at the current 10 Hz tick. |
The discrete action space
| Action |
Phase Name | Permitted Turning Movements | Protected Approaches |
|---|---|---|---|
0 |
NS_GREEN | Straight & Right Turns | Northbound & Southbound |
1 |
EW_GREEN | Straight & Right Turns | Eastbound & Westbound |
2 |
NS_LEFT | Protected Left Turns | Northbound & Southbound Left Bays |
3 |
EW_LEFT | Protected Left Turns | Eastbound & Westbound Left Bays |
To prevent the agent from assigning green lights to empty corridors:
During greedy action selection:
The reward function combines delay reduction, destination-aware Max-Pressure (MPLight), throughput expansion, switching stability, and anti-starvation penalties:
Reward Components:
R_delay = -Δ(Total Wait Time) / 10.0
R_pressure = 0.8 × (∑ P_prev - ∑ P_curr)
R_throughput = 0.25 × N_passed
R_switch = -0.2 (if phase changed and P_prev_phase > 0.5)
R_starv = -1.5 × |D_starved| (for t_wait ≥ 45s)
R_max_green = -0.8 (if t_green ≥ 40s)
R_balance = +0.15 (if imbalance < 0.2 and ∑ P > 0.05)
Penalizes the change in total vehicle waiting time across all 12 movements:
Based on PressLight and MPLight, traffic pressure
Where
-
north_straight$\to$ south,north_left$\to$ east,north_right$\to$ west -
south_straight$\to$ north,south_left$\to$ west,south_right$\to$ east -
east_straight$\to$ west,east_left$\to$ south,east_right$\to$ north -
west_straight$\to$ east,west_left$\to$ north,west_right$\to$ south
The pressure reward rewards a net reduction in intersection pressure:
Direct reward for every vehicle that exits the intersection:
Penalizes unnecessary phase changes when the current phase still has high pressure (
Severe penalty for any approach waiting longer than
Penalizes phase hogging beyond the 40s ceiling:
Rewards balanced queue clearance when the junction is active:
Standard DQNs suffer from overestimation bias and struggle to distinguish state value from action advantage when all actions produce similar outcomes. FlowSync uses a Dueling Double Deep Q-Network:
State Vector s ∈ ℝ²⁸
│
▼
Linear(28 → 256) + LayerNorm + ReLU
│
▼
Linear(256 → 256) + LayerNorm + ReLU
│
├─────────────────────────────────────────┐
▼ ▼
Linear(256 → 128) + ReLU Linear(256 → 128) + ReLU
│ │
▼ ▼
Linear(128 → 1) Linear(128 → 4)
│ │
▼ ▼
State Value V(s) ∈ ℝ¹ Advantage Stream A(s, a) ∈ ℝ⁴
│ │
└────────────────────┬────────────────────┘
│
▼
Q(s, a) = V(s) + [ A(s, a) - 1/|A| ∑ A(s, a') ]
│
▼
Q-Values for Actions {0, 1, 2, 3}
Subtracting the mean advantage ensures uniqueness:
To prevent Q-value overestimation, the online network selects the best valid action, while the frozen target network (
The network minimizes the Huber (Smooth L1) loss weighted by PER importance sampling weights
Transitions
Note
-
$\alpha = 0.6$ (prioritization exponent) -
$\beta_{\text{start}} = 0.4 \to \beta_{\text{end}} = 1.0$ (annealed over training) - Buffer capacity
$N = 100{,}000$ - Mini-batch size
$B = 128$ - SumTree traversal complexity:
$O(\log N)$
Heuristic controllers react only to vehicles that have already arrived. FlowSync implements an online Exponentially Weighted Moving Average (EWMA) arrival tracker that estimates traffic flow across three time horizons (
Smoothing factors:
-
5-Second Window (
$\alpha = 0.18$ ): Captures sudden arrival bursts. -
10-Second Window (
$\alpha = 0.10$ ): Intermediate trend filter. -
20-Second Window (
$\alpha = 0.05$ ): Macro demand baseline.
Platoon Incoming (Burst Flag = 1)
▲
Flow │ ╭─────╮ <-- ewma_5s surges
(veh/s) │ ╱ ╲
│ ──────╱─────────╲────── <-- ewma_20s baseline
└──────────────────────────► Time
- Growth Rate Signal: $\Delta_{\text{growth}} = \frac{\text{ewma}{5\text{s}} - \text{ewma}{20\text{s}}}{\lambda_{\max}}$
- Platoon Burst Indicator: $\mathbf{1}{\text{burst}} = \mathbb{I}(\text{ewma}{20\text{s}} > 0.05 \land \text{ewma}{5\text{s}} > 1.5 \times \text{ewma}{20\text{s}})$
- Queue Dissipation Flag: $\mathbf{1}{\text{dissip}} = \mathbb{I}(\text{ewma}{20\text{s}} > 0.05 \land \text{ewma}{5\text{s}} < 0.5 \times \text{ewma}{20\text{s}})$
To prevent high-density corridors from monopolizing the green signal indefinitely, an independent watchdog monitors approach wait times:
If
stateDiagram-v2
[*] --> GreenPhase: Phase Initialized
GreenPhase --> GreenPhase: t_phase < 8s (Minimum Green Guard)
GreenPhase --> WatchdogCheck: t_phase >= 8s
state WatchdogCheck {
[*] --> CheckStarvation
CheckStarvation --> StarvationOverride: Any approach wait >= 45s
CheckStarvation --> CheckMaxGreen: All waits < 45s
CheckMaxGreen --> MaxGreenOverride: t_phase >= 40s
CheckMaxGreen --> AgentAction: Normal conditions
}
StarvationOverride --> YellowTransition: Force starved phase
MaxGreenOverride --> YellowTransition: Force highest queue phase
AgentAction --> YellowTransition: Agent requests phase switch
AgentAction --> GreenPhase: Agent holds current phase
YellowTransition --> RedClearance: Yellow elapsed (2.0s)
RedClearance --> GreenPhase: Red clearance elapsed (3.0s)
Phase transitions follow a non-preemptible state sequence:
-
Active Green Phase: Minimum duration
$\tau_{\min} = 8.0\text{s}$ , maximum ceiling$\tau_{\max} = 40.0\text{s}$ . -
Yellow Clearance (
$\tau_{\text{yellow}} = 2.0\text{s}$ ): Warns approaching vehicles to decelerate. -
All-Red Clearance (
$\tau_{\text{red}} = 3.0\text{s}$ ): All signal heads show RED. Allows vehicles within the intersection box to clear before perpendicular traffic moves.
Vehicle movements along lanes are simulated with car-following collision constraints:
- Coordinate frame:
$x \in [0.0, 1.0]$ ($0.0 = \text{spawn entry}$ ,$0.42 = \text{stop line}$ ,$1.0 = \text{exit}$ ). - Free-flow cruise speed:
$v_0 = 0.12\text{ units/s}$ . - Minimum safe bumper-to-bumper distance:
$d_{\min} = 0.08\text{ units}$ .
-
Yield-on-Left Mechanics: A left-turning vehicle stopped at
$x = 0.42$ during parallel green phases (Phase 0 or Phase 1) checks oncoming straight and right movements. If an oncoming vehicle is within distance$0.15 \le x < 1.0$ , the left-turn vehicle holds at the stop line. - Right-Turn Priority: Right-turning vehicles do not wait for green phases; they execute turns continuously, yielding only to cross-traffic already inside the intersection box.
- Cubic Bezier Trajectories: 3D turning vehicles follow cubic Bezier paths:
Where
Operators can dispatch priority emergency vehicles (e.g. ambulances) via /simulation/emergency:
- Bypasses normal queuing at
$x = 0.0$ . - Preempts the signal controller to force an immediate green wave along the emergency corridor.
- Halts competing approaches until the emergency vehicle clears the intersection.
The /city simulation coordinates four interconnected intersections (
North_A North_B
│ │
▼ ▼
West_A ──►[ Intersection A ]══════════[ Intersection B ]──► East_B
║ ║
║ Arterial A-C ║ Arterial B-D
║ ║
West_C ──►[ Intersection C ]══════════[ Intersection D ]──► East_D
▲ ▲
│ │
South_C South_D
-
Corridor Connections:
-
$A \leftrightarrow B$ (East-West arterial) -
$C \leftrightarrow D$ (East-West arterial) -
$A \leftrightarrow C$ (North-South arterial) -
$B \leftrightarrow D$ (North-South arterial)
-
- External Portals: 8 entry portals feed external demand into the grid via Poisson processes.
Vehicles clearing an intersection toward an adjacent junction enter a RoadVehicle pipeline:
When
Vehicles spawn with predetermined multi-hop routing itineraries:
-
Trans-Metropolitan Arterials (50%): Direct pass-through crossing two consecutive intersections (e.g.,
North_A$\to A \to C \to$ South_Exit). -
Metropolitan Ring Rotations (25%): Circular routes around the inner grid (
$A \to B \to D \to C$ ). - Turn-Off Exits (25%): Turning maneuvers heading to boundary exits.
Rather than training a centralized agent with an intractable joint action space (
- A single D3QN neural policy is shared across all four intersections.
- Each intersection
$i \in {A, B, C, D}$ constructs its local 28-D observation vector$\mathbf{s}_t^{(i)}$ using local queue depths and downstream arterial pressures. - The shared agent executes actions independently for each junction at 10 Hz, facilitating coordinated green waves without exponential parameter growth.
To ingest live YouTube traffic cameras, StreamResolver uses yt-dlp to extract direct .m3u8 HLS manifests, incorporating PO-token challenge solving to bypass anti-bot mechanisms:
sequenceDiagram
autonumber
participant UI as Client Web App
participant SR as StreamResolver (yt-dlp)
participant FG as RealtimeFrameGrabber
participant YOLO as YOLOv8 + ByteTrack
participant DT as Digital Twin Scheduler
UI->>SR: Submit YouTube Live URL / RTSP Feed
SR->>SR: Extract HLS .m3u8 via yt-dlp (PO-Token Solved)
SR-->>FG: Direct Stream URL
FG->>FG: Spawn Background Thread & Continuously Flush Sockets
loop At Detection Frequency (10 FPS)
FG->>YOLO: Retrieve Latest Frame (0.0ms Lag)
YOLO->>YOLO: Detect Vehicles & Update ByteTrack
YOLO->>DT: Log Chronological Arrival Event
YOLO-->>UI: Stream Annotated Frame via /ws/cctv
end
DT->>DT: Serialize twin_data.json
UI->>UI: Launch Side-by-Side 3D Showdown Replay
Video streams buffered by OpenCV suffer from frame lag. RealtimeFrameGrabber runs a dedicated daemon thread that continually flushes hardware and network socket buffers:
def _grab_loop(self):
while self._running:
ret, frame = self._cap.read()
if ret:
with self._lock:
self._latest_frame = frame # Overwrite slot: 0.0ms latencyThis guarantees that whenever YOLOv8 requests a frame, it receives the latest camera frame with
-
Object Detection: Ultralytics YOLOv8 evaluates frames across five vehicle classes:
car,bus,truck,motorcycle, andauto-rickshaw. -
Inference Thresholds: Detection confidence
$\tau_{\text{conf}} \ge 0.35$ , NMS IoU threshold$\tau_{\text{nms}} = 0.45$ . - Tracking: ByteTrack associates bounding boxes across frames using Kalman filter trajectory prediction and Hungarian matching, assigning persistent tracking IDs.
The web UI provides an interactive HTML5 Canvas editor (ROIEditor.tsx) allowing operators to define approach boundaries. Polygons are evaluated server-side using Shapely:
When a vehicle's trajectory vector crosses a boundary, an entry event is triggered, recording lane assignment and turn direction.
Every detection session outputs a deterministic twin_data.json schedule:
{
"session_id": "cctv_session_8f2a1b",
"video_duration_s": 60.0,
"total_vehicles": 48,
"arrivals": [
{
"time_s": 2.4,
"lane": "north",
"turn": "straight",
"vehicle_type": "car"
},
{
"time_s": 3.1,
"lane": "west",
"turn": "left",
"vehicle_type": "truck"
}
]
}The 3D engine replays this arrival schedule across Fixed-Timer, Greedy, and AI modes to evaluate policy performance on identical traffic flows.
FlowSync evaluates performance using the Highway Capacity Manual (HCM 2010/2016) Level of Service (LOS) standards for signalized intersections:
| LOS Grade | Average Control Delay per Vehicle ( |
Operating Condition & Driver Experience |
|---|---|---|
| LOS A | Free Flow: Extremely low delay; favorable progression; light traffic. | |
| LOS B | Stable Flow (Minimal Delay): Good progression; short cycle lengths. | |
| LOS C | Acceptable Delay: Stable flow; higher delay on uncoordinated approaches. | |
| LOS D | Tolerable Delay: Approaching unstable flow; noticeable queue formation. | |
| LOS E | Unstable Flow (Congestion Limit): Long queues; poor progression. | |
| LOS F | Breakdown Flow (Gridlock): Demand exceeds capacity; oversaturated. |
Calculates the relative delay reduction achieved by FlowSync AI compared to the fixed-time baseline:
When evaluated against empirical sessions where only AI runs are logged, FlowSync compares against the baseline value $\bar{W}_{\text{fixed}} = 38.5\text{s}$.
Measures the increase in vehicle clearing capacity:
The composite efficiency rating (
-
$\bar{T}_{\text{pct}}$ : Throughput rate ($%$ of arriving vehicles cleared). -
$\bar{W}$ : Mean delay in seconds.
FlowSync integrates Supabase for telemetry persistence and model checkpoint storage:
- Relational Database (PostgreSQL):
simulations: Records session runtimes, modes, step counts, and statuses.performance_metrics: Stores aggregated throughput, mean delay, and peak queues.rl_models: Catalogs model versions, episode counts, average rewards, and storage paths.
- Supabase Cloud Storage (
model-checkpoints):- Neural network weights are serialized to
.ptfiles and uploaded tomodels/{simulation_id}/checkpoint_{episode}.pt. - The frontend model picker queries
GET /api/training/modelsto list and load checkpoints directly from cloud storage.
- Neural network weights are serialized to
FlowSync/
├── client/ # Next.js 16 App Router (React 19, TypeScript)
│ ├── prisma/schema.prisma # PostgreSQL data models
│ ├── src/
│ │ ├── app/ # Web application routes
│ │ │ ├── city/page.tsx # 2×2 Multi-Intersection City Grid
│ │ │ ├── dashboard/page.tsx # Analytics & Executive Telemetry
│ │ │ ├── realworld/page.tsx # CCTV & Digital Twin Showdown
│ │ │ ├── simulation/page.tsx # Single Intersection 3D Diorama
│ │ ├── components/
│ │ │ ├── city/ # 2×2 Grid 3D components & road meshes
│ │ │ ├── dashboard/ # KPI cards, benchmark graphs, Recharts panels
│ │ │ ├── realworld/ # Video feeds, polygonal ROI editor, arrival tables
│ │ │ ├── simulation/ # Single intersection Three.js diorama scene
│ │ │ └── ui/ # Accessible UI components (shadcn/ui)
│ │ ├── hooks/ # WebSocket management (useSimulationSocket, useCitySocket)
│ │ └── store/ # Zustand 5 reactive telemetry stores
│ └── package.json
│
├── server/ # FastAPI Backend & Reinforcement Learning Core
│ ├── app/
│ │ ├── main.py # FastAPI entry point, lifespan, CORS, and routers
│ │ ├── config.py # Pydantic settings & Supabase credentials
│ │ ├── realworld/ # Computer Vision & Video Ingestion
│ │ │ ├── digital_twin/ # Replay spawner, arrival scheduler, flow calibrator
│ │ │ └── pipeline/ # yt-dlp resolver, frame grabber, YOLOv8 detector
│ │ ├── rl/ # Deep Reinforcement Learning
│ │ │ ├── dqn_agent.py # D3QN Agent with PER sampling & action masking
│ │ │ ├── dqn_network.py # Dueling network architecture (V and A streams)
│ │ │ ├── hyperparams.py # 28-D observation constants & hyperparameters
│ │ │ ├── replay_buffer.py # Prioritized Experience Replay (SumTree)
│ │ │ └── trainer.py # Async background training loop
│ │ ├── simulation/ # Microscopic Traffic Physics Engine
│ │ │ ├── city_network.py # 2×2 Grid topology, arterial roads, routing
│ │ │ ├── city_spawner.py # 8-portal Poisson generator
│ │ │ ├── demand_forecast.py # Online 8-D EWMA short-horizon forecaster
│ │ │ ├── environment.py # Gymnasium TrafficEnv (28-D observation space)
│ │ │ ├── intersection.py # 12-movement kinematics & yield-on-left rules
│ │ │ ├── spawner.py # Poisson vehicle spawner with CRN seeding
│ │ │ ├── traffic_math.py # Canonical DEST_MAP & destination-aware pressure
│ │ │ ├── traffic_signal.py # Traffic signal controller with clearance timing
│ │ │ └── vehicle.py # Vehicle dataclass & kinematics
│ │ ├── routers/ # REST API Routers (analytics, cctv, simulation, training)
│ │ ├── services/ # Supabase DB & Storage services
│ │ └── websockets/ # 10 Hz WebSocket handlers (simulation, city, cctv, training)
│ ├── data/ # Uploaded videos, session JSONs, local checkpoints
│ ├── Dockerfile # Container build definition
│ └── requirements.txt # Python dependencies
│
├── docker-compose.yml # Multi-container orchestration definition
└── README.md # Technical system documentation
- Node.js: v20.0.0 or higher
- Python: v3.11.0 or higher
- Supabase Account (or local PostgreSQL instance)
- Git
cd server
# Create and activate Python virtual environment
python -m venv venv
source venv/bin/activate # Windows: .\venv\Scripts\Activate.ps1
# Install dependencies
pip install -r requirements.txt
# Configure environment variables in server/.env
cat <<EOF > .env
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-supabase-service-role-key
CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
SIGNAL_RED_DURATION=3.0
EOF
# Launch FastAPI ASGI server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Interactive Swagger documentation is available at http://localhost:8000/docs.
cd client
# Install dependencies (pnpm — lockfile is enforced by CI/Vercel via --frozen-lockfile)
pnpm install
# Configure environment variables in client/.env.local
cat <<EOF > .env.local
DATABASE_URL="postgresql://postgres:password@db.your-project.supabase.co:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://postgres:password@db.your-project.supabase.co:5432/postgres"
NEXT_PUBLIC_SUPABASE_URL="https://your-project.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="your-supabase-anon-key"
NEXT_PUBLIC_FASTAPI_HTTP_URL="http://localhost:8000"
NEXT_PUBLIC_FASTAPI_WS_URL="ws://localhost:8000"
NEXT_PUBLIC_API_URL="http://localhost:8000"
NEXT_PUBLIC_WS_URL="ws://localhost:8000"
EOF
# Sync Prisma database schema
npx prisma db push
npx prisma generate
# Start Next.js development server
pnpm devOpen http://localhost:3000 to launch the platform.
To launch the backend service containerized via Docker:
docker compose up --build -d// Start simulation loop
{ "command": "start" }
// Pause simulation loop (freezes canvas, halts telemetry)
{ "command": "stop" }
// Reset simulation (clears queues and resets step count)
{ "command": "reset" }
// Switch controller mode ("fixed" | "greedy" | "ai" | "manual")
{ "command": "set_mode", "mode": "ai" }
// Manual signal phase override (0: NS, 1: EW, 2: NS Left, 3: EW Left)
{ "command": "set_phase", "phase": 1 }
// Run Timed Benchmark with Common Random Numbers (CRN)
{
"command": "run_timed_benchmark",
"duration_seconds": 60,
"modes": ["fixed", "greedy", "ai"]
}| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Server health check and uptime status. |
GET |
/analytics/dashboard-summary |
Aggregated executive KPIs, mode benchmarks, HCM LOS grades, and historical sessions. |
GET |
/api/simulation/state |
Current 12-movement intersection state snapshot. |
POST |
/api/simulation/stop |
HTTP fallback to stop simulation and freeze vehicle physics. |
POST |
/api/simulation/emergency |
Triggers emergency vehicle priority override on a designated approach. |
POST |
/api/training/start |
Initiates asynchronous background D3QN training loop. |
POST |
/api/training/stop |
Halts active background training. |
GET |
/api/training/models |
Lists trained model checkpoints from Supabase Storage and database. |
POST |
/cctv/upload |
Uploads video file for YOLOv8 computer vision detection. |
GET |
/cctv/sessions/{session_id}/twin-data |
Retrieves chronological vehicle arrival schedule for 3D showdown. |
Evaluated across 60-second stochastic bursts ($\lambda = 0.8\text{ veh/s}$, identical Poisson random seeds via CRN):
| Evaluation Metric | Fixed-Timer Baseline | Greedy (Max-Queue) | FlowSync D3QN AI | AI Improvement vs Baseline |
|---|---|---|---|---|
| Average Delay | 24.5s (LOS C) | 14.2s (LOS B) | 8.6s (LOS A) | -64.9% Wait Time |
| Throughput | 320 veh/hr | 410 veh/hr | 530 veh/hr | +65.6% Capacity |
| Peak Queue | 12 vehicles | 7 vehicles | 3 vehicles | -75.0% Congestion |
| Approach Starvations | Periodic | Frequent (low-flow lanes) | 0 (Zero) | Guaranteed by Watchdog |
Evaluated across 4 interconnected junctions with inter-intersection arterial routing:
| Evaluation Metric | Fixed-Timer Grid | Greedy Decentralized | FlowSync Shared Policy | AI Improvement vs Baseline |
|---|---|---|---|---|
| Network Mean Delay | 31.8s (LOS C) | 19.4s (LOS B) | 12.1s (LOS B) | -61.9% Delay |
| Total Grid Flow | 1,120 veh/hr | 1,480 veh/hr | 1,890 veh/hr | +68.8% Throughput |
| Corridor Spillback | Severe (Gridlock) | Moderate | Minimal | Gridlock Eliminated |
Replay of real-world traffic arrival schedules extracted from CCTV footage:
| Evaluation Metric | Fixed-Timer | Greedy | FlowSync D3QN AI | Real-World Performance Gain |
|---|---|---|---|---|
| Natural Clearance Time | 58.2s | 41.5s | 27.4s | -52.9% Faster Clearance |
| Average Vehicle Wait | 21.6s (LOS C) | 13.9s (LOS B) | 7.8s (LOS A) | -63.9% Wait Time |
| Discharge Wave | Stop-and-Go | Irregular | Continuous Wave | Smooth Progression |
Problem. Benchmark comparisons were confounded: the greedy controller leaked queue-priority behavior, fixed mode performed early phase-switching instead of true pre-timed control, a legacy VAT actuated mode added noise, and evaluation order biased outcomes.
Actions.
- DQN AI is now evaluated first, followed by Fixed and Greedy, across every benchmark runner.
- Greedy audited to pure max-queue prioritization with stable tie-breaking.
- Fixed mode restored to a true pre-timed sequential timer — no queue priority, no early switching.
- Legacy VAT actuated mode removed from benchmark controllers.
Impact. Apples-to-apples paired evaluations on identical locked seeds; leadership badges and Δ pills now reflect genuine policy merit rather than harness artifacts.
- Dynamic DQN checkpoint selection across all benchmark modes, backed by a benchmark analytics aggregation API — any trained checkpoint can be evaluated against the baselines.
- 1-click evaluation preset chips + reset-defaults, scenario content hashing, queue-area / delay-distribution capture, and watchdog audit metadata on every run.
- Benchmark stop button with live countdown, grouped run history in the history tab, and disambiguated repeated learning-curve runs.
Impact. Experiments are reproducible (hashed scenarios, seeded runs), auditable (per-run metadata), and interruptible (operators can halt long benchmarks mid-flight without losing prior results).
Problem. Frontend deploys failed on Vercel (ERR_PNPM_OUTDATED_LOCKFILE — a gsap specifier had drifted from the lockfile under --frozen-lockfile). Backend Render builds resolved torch>=2.0.0 to torch 2.14 plus the full CUDA toolkit (~2.5 GB: 554 MB torch + cuDNN/cuBLAS/NCCL/cuSPARSE/etc. on a CPU host) and then failed on a phantom hash mismatch from a stale, Render-persisted pip HTTP cache.
Actions.
- Regenerated and committed
pnpm-lock.yaml; installs verified green under--frozen-lockfile. - Pinned
torch==2.3.1+cpu/torchvision==0.18.1+cpuwith the PyTorch CPU index baked intoserver/requirements.txt, so any plainpip install -rstays CPU-only (verified cp311 wheels: 190 MB + 1.6 MB). - Added
--no-cache-dirto the Render build command (matching the existingDockerfile), making installs hermetic and immune to cache poisoning.
Impact. Backend build payload ~2.5 GB → ~192 MB (~13× smaller); reproducible builds on both Vercel and Render; no dependence on dashboard build-command ordering.
- Controller Benchmark panels: rich hover tooltips with best-performer highlighting, compact Δ pills with inline explainers, tabular-numeral leader cards.
- Live telemetry cards: trend delta badges (direction-aware good/bad coloring), unit captions, sparklines with scale bars.
- Simulation sidebar reorder (Controls → Reasoning → Analytics → Telemetry) with wrap-safe scenario headers and stacked controller cards.
Impact. Operators read benchmark outcomes and live network state at a glance — no hovering required for the headline numbers, no ambiguity about which policy is winning.
Distributed under the MIT License. See LICENSE for more details.