saltylab-firmware/ui/map_panel.html
sl-webui 88e9bf94ba fix: upgrade roslib CDN 1.3.0→1.4.0 across all HTML panels
roslib@1.3.0 is incompatible with ROS2 Humble rosbridge_server — it sends
messages without an 'op' field, causing "Received a message without an op"
errors that break all ROS topic subscriptions including the GPS tracker.

Fixes 10 panels: sultee-tracker, index, can_monitor, diagnostics,
event_log, gamepad, gimbal, map, settings, vesc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 23:09:45 -04:00

177 lines
5.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>