5.7 KiB
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:
- Select scenarios intuitively.
- Override configuration parameters (frames, weather, etc.).
- Spawn the simulation as a background process.
- 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/templatesanddashboard/static. - Backend (Web Server): A Flask application defined in
dashboard/app.py. - Execution Engine (CLI Pipeline): The pre-existing
run.batwrapper andsrc/main.pyPython 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/configand/api/scenario_params/<name>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
POSTrequest to/api/runcontaining 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:
- Fetches scenarios on load and populates dropdowns.
- Intercepts the "Run" form submission to prevent page reloads.
- Opens a standard Server-Sent Events (SSE) connection via the built-in
EventSourceAPI 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:
-
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 50Note:
run.batsupports Smart Argument Detection. It intelligently determines if CLI flags (like-sor--scenario) are already present in the command array to prevent redundant prefixing. -
Subprocess Spawning: Flask leverages Python's
subprocess.Popento spawn a detached child process running the constructed command.cwd=PROJECT_ROOT: Ensuresrun.batis executed contextually from the root workspace so relative imports insidesrc/main.pydo 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.
-
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, andrun.batalso callsset PYTHONUNBUFFERED=1. This forces the downstream Python simulation (src/main.pyand its dependencies) to emit logs instantly, allowing real-time progress bar renders in the GUI console. -
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 standardResponse(mimetype="text/event-stream"). Asprocess.stdout.readline()pulls new text from the unbuffered stream, Flask yields it to the browser wrapped indata: ... \n\nsyntax. The JS EventSource catches these fragments and appends them to the<div id="console">log box.
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
psutilto 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:
- Dashboard writes an empty flag file to
tmp/stop.flag. - The orchestrator (
src/main.py) checks for this file's existence at the start of every frame tick. - If detected, the orchestrator breaks the main loop, allowing all
finallycleanups, 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.