Browse Source

feat(dashboard): UX Optimization & Smart Auto-Idle Toggle

main
RUSHIL AMBARISH KADU 1 month ago
parent
commit
8ead034373
  1. 2
      dashboard/app.py
  2. 21
      dashboard/static/app.js
  3. 34
      dashboard/static/style.css
  4. 2
      dashboard/templates/index.html
  5. 2
      intel/CHRONICLES.md

2
dashboard/app.py

@ -112,7 +112,7 @@ def simulator_status():
try: try:
import carla import carla
client = carla.Client('localhost', 2000) client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
client.set_timeout(5.0)
client.get_server_version() # Will raise if not ready client.get_server_version() # Will raise if not ready
status = "ready" status = "ready"
world = client.get_world() world = client.get_world()

21
dashboard/static/app.js

@ -23,6 +23,7 @@ document.addEventListener('DOMContentLoaded', () => {
let currentEventSource = null; let currentEventSource = null;
let idleTimer = null; let idleTimer = null;
let manualIdleOverride = false;
let isSimulatorRunning = false; let isSimulatorRunning = false;
let isSimulationActive = false; // user currently running a scenario let isSimulationActive = false; // user currently running a scenario
@ -43,8 +44,8 @@ document.addEventListener('DOMContentLoaded', () => {
// Auto Idle Tracker // Auto Idle Tracker
function resetIdleTimer() { function resetIdleTimer() {
if (idleTimer) clearTimeout(idleTimer); if (idleTimer) clearTimeout(idleTimer);
// If simulation is not active and simulator is ready but NOT paused
if (!isSimulationActive && isSimulatorRunning && gpuIdleToggle && !gpuIdleToggle.checked) {
// If simulation is not active and simulator is ready but NOT paused AND no manual override
if (!isSimulationActive && isSimulatorRunning && gpuIdleToggle && !gpuIdleToggle.checked && !manualIdleOverride) {
idleTimer = setTimeout(() => { idleTimer = setTimeout(() => {
console.log("Auto-idling simulator due to 30s inactivity..."); console.log("Auto-idling simulator due to 30s inactivity...");
gpuIdleToggle.checked = true; gpuIdleToggle.checked = true;
@ -56,11 +57,23 @@ document.addEventListener('DOMContentLoaded', () => {
if (gpuIdleToggle) { if (gpuIdleToggle) {
gpuIdleToggle.addEventListener('change', (e) => { gpuIdleToggle.addEventListener('change', (e) => {
const isIdle = e.target.checked; const isIdle = e.target.checked;
// If manual, toggle the override flag based on the NEW state
if (e.isTrusted) {
// OFF position (isIdle: false) means Manual Wake.
// ON position (isIdle: true) means Auto-Idle enabled.
manualIdleOverride = !isIdle;
console.log(`Auto-Idle system: ${manualIdleOverride ? 'DISABLED (Manual Wake)' : 'ENABLED (Auto mode)'}`);
}
const endpoint = isIdle ? '/api/simulator/idle' : '/api/simulator/wake'; const endpoint = isIdle ? '/api/simulator/idle' : '/api/simulator/wake';
fetch(endpoint, { method: 'POST' }); fetch(endpoint, { method: 'POST' });
if (!isIdle) { if (!isIdle) {
// If we woke it up, we only start the timer if override is not active
resetIdleTimer(); resetIdleTimer();
} else { } else {
// If we paused it, clear any existing timers
if (idleTimer) clearTimeout(idleTimer); if (idleTimer) clearTimeout(idleTimer);
} }
}); });
@ -132,6 +145,10 @@ document.addEventListener('DOMContentLoaded', () => {
if (killSimBtn) { if (killSimBtn) {
killSimBtn.addEventListener('click', () => { killSimBtn.addEventListener('click', () => {
if (confirm("Are you sure you want to FORCE KILL CarlaUE4?\n\nThis will terminate the engine immediately. Any unsaved simulation data or unsynced frames will be lost.")) { if (confirm("Are you sure you want to FORCE KILL CarlaUE4?\n\nThis will terminate the engine immediately. Any unsaved simulation data or unsynced frames will be lost.")) {
// Immediate UI Feedback
simStatusText.textContent = 'Terminating...';
simStatusDot.className = 'dot yellow';
fetch('/api/simulator/kill', { method: 'POST' }) fetch('/api/simulator/kill', { method: 'POST' })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {

34
dashboard/static/style.css

@ -711,18 +711,42 @@ input:checked + .slider:before {
} }
.small-switch { .small-switch {
width: 34px;
height: 18px;
width: 46px;
height: 20px;
} }
.small-switch .slider:before { .small-switch .slider:before {
height: 12px;
width: 12px;
height: 14px;
width: 14px;
bottom: 3px; bottom: 3px;
left: 3px; left: 3px;
} }
.small-switch input:checked + .slider {
background-color: var(--success);
}
.small-switch input:checked + .slider:before { .small-switch input:checked + .slider:before {
transform: translateX(16px);
transform: translateX(26px);
}
.small-switch .slider::after {
content: "AUTO";
position: absolute;
right: 22px;
top: 50%;
transform: translateY(-50%);
font-size: 7px;
font-weight: 500;
font-family: 'JetBrains Mono', monospace;
color: white;
opacity: 0;
transition: opacity 0.2s;
letter-spacing: 0.5px;
pointer-events: none;
}
.small-switch input:checked + .slider::after {
opacity: 1;
} }

2
dashboard/templates/index.html

@ -38,7 +38,7 @@
<button id="launch-sim-btn" class="btn btn-secondary btn-small" style="width: 100%; margin-top: 10px; padding: 0.6rem;">Initialize CarlaUE4</button> <button id="launch-sim-btn" class="btn btn-secondary btn-small" style="width: 100%; margin-top: 10px; padding: 0.6rem;">Initialize CarlaUE4</button>
<!-- Idle Toggle --> <!-- Idle Toggle -->
<div id="idle-toggle-container" class="idle-toggle-container" style="display: none;"> <div id="idle-toggle-container" class="idle-toggle-container" style="display: none;">
<span class="idle-label">GPU Idle Mode</span>
<span class="idle-label">Auto-Idle</span>
<label class="switch small-switch"> <label class="switch small-switch">
<input type="checkbox" id="gpu-idle-toggle"> <input type="checkbox" id="gpu-idle-toggle">
<span class="slider round"></span> <span class="slider round"></span>

2
intel/CHRONICLES.md

@ -129,6 +129,8 @@ After 30 iterations of parameter tuning, we identified the fundamental reason fo
- **Calibration**: Finalized the **Antenna Gain LUT Integration** (Separable Az/El patterns) in `Sceneset.py`. - **Calibration**: Finalized the **Antenna Gain LUT Integration** (Separable Az/El patterns) in `Sceneset.py`.
- **Organization**: Reorganized the `intel/radar` directory into structured subfolders (`core`, `research`, `diagnostics`, `archive`) to maintain documentation scalability. - **Organization**: Reorganized the `intel/radar` directory into structured subfolders (`core`, `research`, `diagnostics`, `archive`) to maintain documentation scalability.
- **Physics**: Validated the pure physical $1/R^4$ power law and removed all legacy scaling multipliers. - **Physics**: Validated the pure physical $1/R^4$ power law and removed all legacy scaling multipliers.
- **Dashboard**: Implemented a **Smart Auto-Idle Toggle** with clear visual feedback (Success-Green background and 'AUTO' text overlay). Redefined toggle logic to serve as a master switch that immediately pauses CARLA when enabled and disables the auto-timer when disabled.
- **UX Optimization**: Resolved a critical 10s UI hang during simulator shutdown by reducing the backend status ping timeout from 10.0s to 5.0s and implementing immediate frontend feedback for the 'Kill' action.
### **April 14** ### **April 14**
- **Task**: Physics "De-Hacking" & Root Cause Analysis. - **Task**: Physics "De-Hacking" & Root Cause Analysis.

Loading…
Cancel
Save