# BATL CARLA Dashboard Architecture This document outlines the architecture, data flow, and inner workings of the BATL CARLA Dashboard (GUI Orchestrator). It is designed to be easily digestible for both human maintainers and AI assistants iterating on the codebase. ## 1. High-Level Overview The BATL CARLA Dashboard is a web-based GUI that replaces manual CLI interactions. It allows users to: 1. Select scenarios intuitively. 2. Override configuration parameters (frames, weather, etc.). 3. Spawn the simulation as a background process. 4. Stream real-time standard output (stdout) directly from the simulation to the browser. The system is split into three main layers: - **Frontend (Browser):** HTML/CSS/JavaScript located in `dashboard/templates` and `dashboard/static`. - **Backend (Web Server):** A Flask application defined in `dashboard/app.py`. - **Execution Engine (CLI Pipeline):** The pre-existing `run.bat` wrapper and `src/main.py` Python script. --- ## 2. Component Breakdown ### A. The Launcher (`dashboard.bat`) This simple batch script is the entry point for the user. It activates the appropriate Python environment and executes `dashboard/app.py`, launching the Flask development server on port 5000. ### B. The Web Server (`dashboard/app.py`) Flask acts as the bridge between the user's browser HTTP requests and the host operating system's command line. - **API Endpoints:** It serves `/api/config` and `/api/scenario_params/` to dynamically inform the UI about available scenarios, config limits, and tunable parameters. - **Process Orchestration:** When a user clicks "Run" on the UI, the frontend sends a `POST` request to `/api/run` containing the selected options. Flask parses this JSON payload and heavily formats a CLI command array. ### C. The Frontend (`dashboard/static/app.js`) The JavaScript logic handles state management. It: 1. Fetches scenarios on load and populates dropdowns. 2. Intercepts the "Run" form submission to prevent page reloads. 3. Opens a standard **Server-Sent Events (SSE)** connection via the built-in `EventSource` API to receive real-time text streams from Flask. --- ## 3. How the Dashboard Interacts with `run.bat` The most critical interface in this architecture is how Flask triggers and monitors the underlying CARLA simulation. When the `/api/run` endpoint is hit: 1. **Command Construction:** Flask builds the command array. A payload of `{"scenario": "showcase", "frames": 50}` translates to the equivalent of typing: `cmd.exe /c run.bat showcase --frames 50` *Note: `run.bat` supports **Smart Argument Detection**. It intelligently determines if CLI flags (like `-s` or `--scenario`) are already present in the command array to prevent redundant prefixing.* 2. **Subprocess Spawning:** Flask leverages Python's `subprocess.Popen` to spawn a detached child process running the constructed command. - `cwd=PROJECT_ROOT`: Ensures `run.bat` is executed contextually from the root workspace so relative imports inside `src/main.py` do not break. - `stdout=subprocess.PIPE` / `stderr=subprocess.STDOUT`: Captures both standard and error console outputs, merging them into a single pipe that Flask can read dynamically. 3. **Stream Unbuffering (Crucial Step):** By default, Python buffers stdout when piping it to another program, causing massive delays (the GUI appears to "freeze"). To fix this, Flask injects `env["PYTHONUNBUFFERED"] = "1"` into the sub-environment, and `run.bat` also calls `set PYTHONUNBUFFERED=1`. This forces the downstream Python simulation (`src/main.py` and its dependencies) to emit logs instantly, allowing real-time progress bar renders in the GUI console. 4. **Event Streaming (Yield):** Instead of waiting for the process to return an exit code, Flask uses a specific Python generator (`def generate():`) paired with a standard `Response(mimetype="text/event-stream")`. As `process.stdout.readline()` pulls new text from the unbuffered stream, Flask yields it to the browser. **Visual Feedback Tags:** The dashboard JS (`app.js`) specifically listens for bracketed tags to drive UI components: - `[FRAME X/Y]`: Drives the primary simulation progress bar. - `[SHENRON_INIT]`: Sends hardware specs (GPU, VRAM) to the Telemetry HUD. - `[SHENRON_STEP]`: Drives the secondary "Synthesis" progress bar and real-time signal metrics (SNR, Pts). - `[AUTO-MCAP]`: Signals the transition to the final data serialization phase. - `[PROCESS_COMPLETED]`: Triggers the final cleanup and re-enables the "Launch" button. --- ## 5. Simulator Lifecycle & GPU Control The dashboard now incorporates active management of the `CarlaUE4.exe` process and its hardware utilization. ### A. Lifecycle Monitoring - **Polling:** The backend uses `psutil` to detect if the simulator process is active. - **Initialization:** If offline, a one-click "Initialize CarlaUE4" button allows the user to launch the simulator directly from the browser. - **Ping Validation:** The dashboard "Ready" state is only achieved once the backend successfully pings the CARLA server (localhost:2000) and receives a valid version response. ### B. Graceful Stop Protocol (IPC) Instead of killing the simulation process—which can lead to corrupted radar/lidar data—the "Stop Simulation" button triggers an Inter-Process Communication (IPC) signal: 1. Dashboard writes an empty flag file to `tmp/stop.flag`. 2. The orchestrator (`src/main.py`) checks for this file's existence at the start of every frame tick. 3. If detected, the orchestrator breaks the main loop, allowing all `finally` cleanups, recorder closures, and MCAP conversions to finish elegantly. ### C. GPU Resource Control (Idle Mode) To prevent CARLA from consuming 100% GPU while waiting for user interaction or during Shenron radar post-processing: - **Synchronous Throttling:** The dashboard can toggle CARLA into `synchronous_mode`. - **Idle State:** Without a `world.tick()` call from the client, Unreal Engine pauses its rendering and physics loop, dropping GPU usage to ~0%. - **Auto-Idle:** The dashboard incorporates a 30-second inactivity timer that automatically pauses the simulator to save power.