# 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` 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 wrapped in `data: ... \n\n` syntax. The JS EventSource catches these fragments and appends them to the `
` log box. --- ## 4. Extension Guidelines for AI When asked to extend the Dashboard, observe the following patterns: - **Adding new CLI flags:** Update the `POST /api/run` payload parser in `app.py`, extend the `cmd.extend()` builder, and add the corresponding HTML `` in `index.html`. - **Adding new data streams:** The SSE generator currently pipes raw text. To parse structured data (like active ego speed) for live graphs, consider formatting the intermediate Python prints as JSON and having `app.js` parse the `event.data` payload conditionally. - **Pathing:** Remember that `app.py` lives in a sub-folder. Operations manipulating the CARLA simulation *must* be rooted up two levels using the `PROJECT_ROOT` pointer established in the file.