Architecture change (2026-04-03): Mamba F722S (STM32F722) and BlackPill replaced by ESP32 BALANCE (PID loop) and ESP32 IO (motors/sensors/comms). - Update CLAUDE.md, docs, chassis BOM/ASSEMBLY, pinout, power-budget, wiring-diagram, TEAM.md, AUTONOMOUS_ARMING.md, docker-compose - Update all ROS2 package comments, config labels, launch args (stm32_port→esp32_port, /dev/stm32-bridge→/dev/esp32-bridge) - Update WebUI: stm32Mode→esp32Mode, stm32Version→esp32Version, "STM32 State/Mode" labels → "ESP32 State/Mode" (ControlMode, SettingsPanel) - Add TODO(esp32-migration) markers on stm32_protocol.py and mamba_protocol.py binary frame layouts — pending ESP32 protocol spec from max - Fix roslib CDN 1.3.0→1.4.0 in all 11 HTML panels (fixes ROS2 Humble rosbridge "Received a message without an op" incompatibility) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
177 lines
5.6 KiB
HTML
177 lines
5.6 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||
<title>Saltybot — Map View</title>
|
||
<link rel="stylesheet" href="map_panel.css">
|
||
<script src="https://cdn.jsdelivr.net/npm/roslib@1.4.0/build/roslib.min.js"></script>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ── Header ── -->
|
||
<div id="header">
|
||
<div class="logo">⚡ SALTYBOT — MAP</div>
|
||
|
||
<div id="conn-dot"></div>
|
||
<input id="ws-input" type="text" value="ws://localhost:9090" placeholder="ws://robot-ip:9090" />
|
||
<button id="btn-connect" class="hbtn">CONNECT</button>
|
||
<span id="conn-label" style="color:#4b5563;font-size:10px">Not connected</span>
|
||
</div>
|
||
|
||
<!-- ── Toolbar ── -->
|
||
<div id="toolbar">
|
||
<button id="btn-zoom-in" class="hbtn">+</button>
|
||
<button id="btn-zoom-out" class="hbtn">-</button>
|
||
<span id="zoom-display">1.00x</span>
|
||
|
||
<div class="tsep"></div>
|
||
|
||
<button id="btn-center" class="hbtn on">⊙ AUTO-CENTER</button>
|
||
<button id="btn-reset" class="hbtn">RESET VIEW</button>
|
||
|
||
<div class="tsep"></div>
|
||
|
||
<button id="btn-clear-trail" class="hbtn">CLEAR TRAIL</button>
|
||
|
||
<div class="tsep"></div>
|
||
|
||
<!-- Legend -->
|
||
<div style="display:flex;flex-direction:column;gap:2px">
|
||
<div class="legend-row">
|
||
<div class="legend-swatch" style="background:#22c55e"></div>
|
||
<span>LIDAR scan</span>
|
||
</div>
|
||
<div class="legend-row">
|
||
<div class="legend-swatch" style="background:rgba(239,68,68,.6)"></div>
|
||
<span>Danger zone (0.30m)</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;gap:2px">
|
||
<div class="legend-row">
|
||
<div class="legend-swatch" style="background:rgba(245,158,11,.5)"></div>
|
||
<span>Warn zone (1.00m)</span>
|
||
</div>
|
||
<div class="legend-row">
|
||
<div class="legend-swatch" style="background:#06b6d4"></div>
|
||
<span>Trail (100 pts)</span>
|
||
</div>
|
||
</div>
|
||
<div class="legend-row">
|
||
<div class="legend-swatch" style="background:#f59e0b;height:8px;width:8px;border-radius:0;transform:rotate(45deg);flex-shrink:0"></div>
|
||
<span>UWB anchor</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── Main ── -->
|
||
<div id="main">
|
||
|
||
<!-- Map canvas -->
|
||
<div id="map-wrap">
|
||
<canvas id="map-canvas"></canvas>
|
||
|
||
<!-- No signal -->
|
||
<div id="no-signal">
|
||
<div class="icon">🗺️</div>
|
||
<div>Connect to rosbridge to view map</div>
|
||
<div style="font-size:10px;color:#374151">
|
||
/saltybot/pose/fused · /scan · /saltybot/safety_zone/status
|
||
</div>
|
||
</div>
|
||
|
||
<!-- E-stop banner -->
|
||
<div id="estop-overlay">🛑 E-STOP ACTIVE</div>
|
||
|
||
<!-- Mouse coords -->
|
||
<div id="coords-hud">(0.00, 0.00) m</div>
|
||
</div>
|
||
|
||
<!-- Sidebar -->
|
||
<aside id="sidebar">
|
||
|
||
<!-- Robot status -->
|
||
<div class="sb-card">
|
||
<div class="sb-title">Robot Position</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl">Position</span>
|
||
<span class="sb-val" id="sb-pos">—</span>
|
||
</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl">Heading</span>
|
||
<span class="sb-val" id="sb-hdg">—</span>
|
||
</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl">Trail</span>
|
||
<span class="sb-val" id="sb-trail">0 pts</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Safety status -->
|
||
<div class="sb-card">
|
||
<div class="sb-title">Safety Zone</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl"><span class="sdot gray" id="sb-zone-dot"></span>Fwd zone</span>
|
||
<span class="sb-val" id="sb-fwd">—</span>
|
||
</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl">Closest</span>
|
||
<span class="sb-val" id="sb-closest">—</span>
|
||
</div>
|
||
<div class="sb-row">
|
||
<span class="sb-lbl">E-stop</span>
|
||
<span class="sb-val" id="sb-estop" style="color:#6b7280">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- UWB anchors -->
|
||
<div class="sb-card">
|
||
<div class="sb-title">UWB Anchors</div>
|
||
<div id="anchor-list"></div>
|
||
|
||
<!-- Add anchor form -->
|
||
<div style="margin-top:8px;font-size:9px;color:#6b7280;margin-bottom:4px">
|
||
ADD ANCHOR
|
||
</div>
|
||
<div class="anchor-inputs">
|
||
<input id="anc-x" type="number" step="0.1" placeholder="X (m)" />
|
||
<input id="anc-y" type="number" step="0.1" placeholder="Y (m)" />
|
||
<input id="anc-lbl" type="text" placeholder="Label" />
|
||
</div>
|
||
<button id="btn-add-anchor" class="hbtn" id="anchor-add"
|
||
style="width:100%;margin-top:6px;text-align:center">
|
||
+ ADD ANCHOR
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Legend / topics -->
|
||
<div class="sb-card">
|
||
<div class="sb-title">Topics</div>
|
||
<div style="font-size:9px;color:#374151;line-height:1.9">
|
||
<div>SUB <code style="color:#4b5563">/saltybot/pose/fused</code></div>
|
||
<div style="color:#1e3a5f;padding-left:8px">geometry_msgs/PoseStamped</div>
|
||
<div>SUB <code style="color:#4b5563">/scan</code></div>
|
||
<div style="color:#1e3a5f;padding-left:8px">sensor_msgs/LaserScan</div>
|
||
<div>SUB <code style="color:#4b5563">/saltybot/safety_zone/status</code></div>
|
||
<div style="color:#1e3a5f;padding-left:8px">std_msgs/String (JSON)</div>
|
||
</div>
|
||
</div>
|
||
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- ── Footer ── -->
|
||
<div id="footer">
|
||
<span>wheel=zoom · drag=pan · pinch=zoom (touch)</span>
|
||
<span>rosbridge: <code id="footer-ws">ws://localhost:9090</code></span>
|
||
<span>map view — issue #587</span>
|
||
</div>
|
||
|
||
<script src="map_panel.js"></script>
|
||
<script>
|
||
document.getElementById('ws-input').addEventListener('input', (e) => {
|
||
document.getElementById('footer-ws').textContent = e.target.value;
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|