Spaces:
Sleeping
Sleeping
Zhen Ye
Claude Opus 4.5
commited on
Commit
·
d496e6d
1
Parent(s):
7a7588e
Add military-style radar with helicopter demo mode
Browse files- Redesign radar with military tactical aesthetic (green phosphor CRT look)
- Add 4 helicopter tracks with keyframe interpolation for smooth movement
- H01 moves away (triangle points up), H02-H04 approach (triangles point down)
- First frame radar shows static snapshot after Reason clicked
- Live radar shows animated view after Engage clicked
- Remove old unused demo data files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- frontend/data/helicopter_demo_data.js +38 -0
- frontend/data/helicopter_demo_tracks.json +38 -0
- frontend/index.html +0 -1
- frontend/js/core/demo.js +142 -0
- frontend/js/ui/radar.js +13 -0
frontend/data/helicopter_demo_data.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
window.HELICOPTER_DEMO_DATA = {
|
| 2 |
+
"fps": 24,
|
| 3 |
+
"totalFrames": 192,
|
| 4 |
+
"video": "Enhance_Video_Movement.mp4",
|
| 5 |
+
"format": "keyframes",
|
| 6 |
+
"keyframes": {
|
| 7 |
+
"0": [
|
| 8 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 200, "y": 260, "w": 180, "h": 120}, "gpt_distance_m": 800, "angle_deg": -90, "speed_kph": 180},
|
| 9 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 420, "y": 240, "w": 150, "h": 100}, "gpt_distance_m": 900, "angle_deg": 90, "speed_kph": 180},
|
| 10 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 620, "y": 250, "w": 100, "h": 68}, "gpt_distance_m": 1200, "angle_deg": 90, "speed_kph": 185},
|
| 11 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 850, "y": 235, "w": 90, "h": 62}, "gpt_distance_m": 1300, "angle_deg": 90, "speed_kph": 190}
|
| 12 |
+
],
|
| 13 |
+
"48": [
|
| 14 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 150, "y": 280, "w": 200, "h": 130}, "gpt_distance_m": 700, "angle_deg": -90, "speed_kph": 190},
|
| 15 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 400, "y": 255, "w": 160, "h": 105}, "gpt_distance_m": 850, "angle_deg": 90, "speed_kph": 185},
|
| 16 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 640, "y": 255, "w": 115, "h": 78}, "gpt_distance_m": 1050, "angle_deg": 90, "speed_kph": 188},
|
| 17 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 870, "y": 245, "w": 105, "h": 72}, "gpt_distance_m": 1150, "angle_deg": 90, "speed_kph": 192}
|
| 18 |
+
],
|
| 19 |
+
"96": [
|
| 20 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 80, "y": 300, "w": 220, "h": 145}, "gpt_distance_m": 600, "angle_deg": -90, "speed_kph": 200},
|
| 21 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 380, "y": 265, "w": 155, "h": 102}, "gpt_distance_m": 820, "angle_deg": 90, "speed_kph": 182},
|
| 22 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 660, "y": 262, "w": 135, "h": 92}, "gpt_distance_m": 900, "angle_deg": 90, "speed_kph": 190},
|
| 23 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 890, "y": 258, "w": 125, "h": 85}, "gpt_distance_m": 980, "angle_deg": 90, "speed_kph": 195}
|
| 24 |
+
],
|
| 25 |
+
"144": [
|
| 26 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 50, "y": 280, "w": 200, "h": 130}, "gpt_distance_m": 650, "angle_deg": -90, "speed_kph": 195},
|
| 27 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 360, "y": 270, "w": 148, "h": 98}, "gpt_distance_m": 800, "angle_deg": 90, "speed_kph": 178},
|
| 28 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 680, "y": 272, "w": 158, "h": 108}, "gpt_distance_m": 750, "angle_deg": 90, "speed_kph": 192},
|
| 29 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 910, "y": 270, "w": 148, "h": 100}, "gpt_distance_m": 800, "angle_deg": 90, "speed_kph": 198}
|
| 30 |
+
],
|
| 31 |
+
"191": [
|
| 32 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 30, "y": 260, "w": 190, "h": 125}, "gpt_distance_m": 680, "angle_deg": -90, "speed_kph": 190},
|
| 33 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 340, "y": 275, "w": 142, "h": 94}, "gpt_distance_m": 780, "angle_deg": 90, "speed_kph": 175},
|
| 34 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 700, "y": 280, "w": 180, "h": 122}, "gpt_distance_m": 620, "angle_deg": 90, "speed_kph": 195},
|
| 35 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 930, "y": 282, "w": 172, "h": 116}, "gpt_distance_m": 650, "angle_deg": 90, "speed_kph": 200}
|
| 36 |
+
]
|
| 37 |
+
}
|
| 38 |
+
};
|
frontend/data/helicopter_demo_tracks.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"fps": 24,
|
| 3 |
+
"totalFrames": 192,
|
| 4 |
+
"video": "Enhance_Video_Movement.mp4",
|
| 5 |
+
"format": "keyframes",
|
| 6 |
+
"keyframes": {
|
| 7 |
+
"0": [
|
| 8 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 200, "y": 260, "w": 180, "h": 120}, "gpt_distance_m": 800, "angle_deg": -90, "speed_kph": 180},
|
| 9 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 420, "y": 240, "w": 150, "h": 100}, "gpt_distance_m": 900, "angle_deg": 90, "speed_kph": 180},
|
| 10 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 620, "y": 250, "w": 100, "h": 68}, "gpt_distance_m": 1200, "angle_deg": 90, "speed_kph": 185},
|
| 11 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 850, "y": 235, "w": 90, "h": 62}, "gpt_distance_m": 1300, "angle_deg": 90, "speed_kph": 190}
|
| 12 |
+
],
|
| 13 |
+
"48": [
|
| 14 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 150, "y": 280, "w": 200, "h": 130}, "gpt_distance_m": 700, "angle_deg": -90, "speed_kph": 190},
|
| 15 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 400, "y": 255, "w": 160, "h": 105}, "gpt_distance_m": 850, "angle_deg": 90, "speed_kph": 185},
|
| 16 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 640, "y": 255, "w": 115, "h": 78}, "gpt_distance_m": 1050, "angle_deg": 90, "speed_kph": 188},
|
| 17 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 870, "y": 245, "w": 105, "h": 72}, "gpt_distance_m": 1150, "angle_deg": 90, "speed_kph": 192}
|
| 18 |
+
],
|
| 19 |
+
"96": [
|
| 20 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 80, "y": 300, "w": 220, "h": 145}, "gpt_distance_m": 600, "angle_deg": -90, "speed_kph": 200},
|
| 21 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 380, "y": 265, "w": 155, "h": 102}, "gpt_distance_m": 820, "angle_deg": 90, "speed_kph": 182},
|
| 22 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 660, "y": 262, "w": 135, "h": 92}, "gpt_distance_m": 900, "angle_deg": 90, "speed_kph": 190},
|
| 23 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 890, "y": 258, "w": 125, "h": 85}, "gpt_distance_m": 980, "angle_deg": 90, "speed_kph": 195}
|
| 24 |
+
],
|
| 25 |
+
"144": [
|
| 26 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 50, "y": 280, "w": 200, "h": 130}, "gpt_distance_m": 650, "angle_deg": -90, "speed_kph": 195},
|
| 27 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 360, "y": 270, "w": 148, "h": 98}, "gpt_distance_m": 800, "angle_deg": 90, "speed_kph": 178},
|
| 28 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 680, "y": 272, "w": 158, "h": 108}, "gpt_distance_m": 750, "angle_deg": 90, "speed_kph": 192},
|
| 29 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 910, "y": 270, "w": 148, "h": 100}, "gpt_distance_m": 800, "angle_deg": 90, "speed_kph": 198}
|
| 30 |
+
],
|
| 31 |
+
"191": [
|
| 32 |
+
{"id": "H01", "label": "helicopter", "bbox": {"x": 30, "y": 260, "w": 190, "h": 125}, "gpt_distance_m": 680, "angle_deg": -90, "speed_kph": 190},
|
| 33 |
+
{"id": "H02", "label": "helicopter", "bbox": {"x": 340, "y": 275, "w": 142, "h": 94}, "gpt_distance_m": 780, "angle_deg": 90, "speed_kph": 175},
|
| 34 |
+
{"id": "H03", "label": "helicopter", "bbox": {"x": 700, "y": 280, "w": 180, "h": 122}, "gpt_distance_m": 620, "angle_deg": 90, "speed_kph": 195},
|
| 35 |
+
{"id": "H04", "label": "helicopter", "bbox": {"x": 930, "y": 282, "w": 172, "h": 116}, "gpt_distance_m": 650, "angle_deg": 90, "speed_kph": 200}
|
| 36 |
+
]
|
| 37 |
+
}
|
| 38 |
+
}
|
frontend/index.html
CHANGED
|
@@ -533,7 +533,6 @@
|
|
| 533 |
<script src="./js/ui/intel.js"></script>
|
| 534 |
<script src="./js/ui/cursor.js"></script>
|
| 535 |
<script src="./js/ui/trade.js"></script>
|
| 536 |
-
<script src="./data/demo_data.js"></script>
|
| 537 |
<script src="./data/helicopter_demo_data.js"></script>
|
| 538 |
<script src="./js/core/demo.js"></script>
|
| 539 |
<script src="./js/main.js"></script>
|
|
|
|
| 533 |
<script src="./js/ui/intel.js"></script>
|
| 534 |
<script src="./js/ui/cursor.js"></script>
|
| 535 |
<script src="./js/ui/trade.js"></script>
|
|
|
|
| 536 |
<script src="./data/helicopter_demo_data.js"></script>
|
| 537 |
<script src="./js/core/demo.js"></script>
|
| 538 |
<script src="./js/main.js"></script>
|
frontend/js/core/demo.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
APP.core.demo = {};
|
| 2 |
+
|
| 3 |
+
APP.core.demo.data = null;
|
| 4 |
+
APP.core.demo.active = false;
|
| 5 |
+
|
| 6 |
+
APP.core.demo.load = async function () {
|
| 7 |
+
// Demo data is now loaded per-video via loadForVideo()
|
| 8 |
+
// This function is kept for compatibility but does nothing
|
| 9 |
+
};
|
| 10 |
+
|
| 11 |
+
APP.core.demo.getFrameData = function (currentTime) {
|
| 12 |
+
if (!APP.core.demo.data) return null;
|
| 13 |
+
|
| 14 |
+
// Use interpolation for keyframe format
|
| 15 |
+
if (APP.core.demo.data.format === "keyframes") {
|
| 16 |
+
return APP.core.demo.getFrameDataInterpolated(currentTime);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
// Original logic for frame-by-frame data
|
| 20 |
+
const fps = APP.core.demo.data.fps || 30;
|
| 21 |
+
const frameIdx = Math.floor(currentTime * fps);
|
| 22 |
+
|
| 23 |
+
// Get tracks for this frame
|
| 24 |
+
// Handle both string and number keys if needed
|
| 25 |
+
const tracks = APP.core.demo.data.frames[frameIdx] || APP.core.demo.data.frames[frameIdx.toString()];
|
| 26 |
+
|
| 27 |
+
if (!tracks) return [];
|
| 28 |
+
return tracks;
|
| 29 |
+
};
|
| 30 |
+
|
| 31 |
+
APP.core.demo.enable = function (force = true) {
|
| 32 |
+
const { log } = APP.ui.logging;
|
| 33 |
+
APP.core.demo.active = force;
|
| 34 |
+
if (force) {
|
| 35 |
+
log("DEMO MODE ACTIVATED", "g");
|
| 36 |
+
const chipFeed = document.getElementById("chipFeed");
|
| 37 |
+
if (chipFeed) chipFeed.textContent = "MODE:DEMO";
|
| 38 |
+
}
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
// Keyframe interpolation for smooth radar movement
|
| 42 |
+
APP.core.demo._keyframeIndices = null;
|
| 43 |
+
|
| 44 |
+
APP.core.demo.getKeyframeIndices = function() {
|
| 45 |
+
if (!APP.core.demo.data || APP.core.demo.data.format !== "keyframes") return null;
|
| 46 |
+
if (APP.core.demo._keyframeIndices) return APP.core.demo._keyframeIndices;
|
| 47 |
+
|
| 48 |
+
const indices = Object.keys(APP.core.demo.data.keyframes)
|
| 49 |
+
.map(k => parseInt(k, 10))
|
| 50 |
+
.sort((a, b) => a - b);
|
| 51 |
+
|
| 52 |
+
APP.core.demo._keyframeIndices = indices;
|
| 53 |
+
return indices;
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
APP.core.demo.interpolateTrack = function(trackA, trackB, t) {
|
| 57 |
+
const { lerp } = APP.core.utils;
|
| 58 |
+
|
| 59 |
+
return {
|
| 60 |
+
id: trackA.id,
|
| 61 |
+
label: trackA.label,
|
| 62 |
+
bbox: {
|
| 63 |
+
x: lerp(trackA.bbox.x, trackB.bbox.x, t),
|
| 64 |
+
y: lerp(trackA.bbox.y, trackB.bbox.y, t),
|
| 65 |
+
w: lerp(trackA.bbox.w, trackB.bbox.w, t),
|
| 66 |
+
h: lerp(trackA.bbox.h, trackB.bbox.h, t)
|
| 67 |
+
},
|
| 68 |
+
gpt_distance_m: lerp(trackA.gpt_distance_m, trackB.gpt_distance_m, t),
|
| 69 |
+
angle_deg: trackA.angle_deg,
|
| 70 |
+
speed_kph: lerp(trackA.speed_kph, trackB.speed_kph, t),
|
| 71 |
+
depth_valid: true,
|
| 72 |
+
depth_est_m: lerp(trackA.gpt_distance_m, trackB.gpt_distance_m, t),
|
| 73 |
+
history: [],
|
| 74 |
+
predicted_path: []
|
| 75 |
+
};
|
| 76 |
+
};
|
| 77 |
+
|
| 78 |
+
APP.core.demo.getFrameDataInterpolated = function(currentTime) {
|
| 79 |
+
const data = APP.core.demo.data;
|
| 80 |
+
if (!data || data.format !== "keyframes") return null;
|
| 81 |
+
|
| 82 |
+
const fps = data.fps || 24;
|
| 83 |
+
const frameIdx = Math.floor(currentTime * fps);
|
| 84 |
+
const keyframes = APP.core.demo.getKeyframeIndices();
|
| 85 |
+
|
| 86 |
+
if (!keyframes || keyframes.length === 0) return [];
|
| 87 |
+
|
| 88 |
+
// Find surrounding keyframes
|
| 89 |
+
let beforeIdx = keyframes[0];
|
| 90 |
+
let afterIdx = keyframes[keyframes.length - 1];
|
| 91 |
+
|
| 92 |
+
for (let i = 0; i < keyframes.length; i++) {
|
| 93 |
+
if (keyframes[i] <= frameIdx) beforeIdx = keyframes[i];
|
| 94 |
+
if (keyframes[i] >= frameIdx) { afterIdx = keyframes[i]; break; }
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
// Edge cases
|
| 98 |
+
if (frameIdx <= keyframes[0]) return data.keyframes[keyframes[0]] || [];
|
| 99 |
+
if (frameIdx >= keyframes[keyframes.length - 1]) return data.keyframes[keyframes[keyframes.length - 1]] || [];
|
| 100 |
+
|
| 101 |
+
// Interpolation factor
|
| 102 |
+
const t = (beforeIdx === afterIdx) ? 0 : (frameIdx - beforeIdx) / (afterIdx - beforeIdx);
|
| 103 |
+
|
| 104 |
+
const tracksBefore = data.keyframes[beforeIdx] || [];
|
| 105 |
+
const tracksAfter = data.keyframes[afterIdx] || [];
|
| 106 |
+
|
| 107 |
+
// Match by ID and interpolate
|
| 108 |
+
const result = [];
|
| 109 |
+
for (const trackA of tracksBefore) {
|
| 110 |
+
const trackB = tracksAfter.find(tr => tr.id === trackA.id);
|
| 111 |
+
if (trackB) {
|
| 112 |
+
result.push(APP.core.demo.interpolateTrack(trackA, trackB, t));
|
| 113 |
+
}
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
return result;
|
| 117 |
+
};
|
| 118 |
+
|
| 119 |
+
// Video-specific loading for demo tracks
|
| 120 |
+
APP.core.demo.loadForVideo = async function(videoName) {
|
| 121 |
+
const { log } = APP.ui.logging;
|
| 122 |
+
if (videoName.toLowerCase().includes("enhance_video_movement")) {
|
| 123 |
+
// Use global variable injected by helicopter_demo_data.js script tag (CORS-safe)
|
| 124 |
+
if (window.HELICOPTER_DEMO_DATA) {
|
| 125 |
+
APP.core.demo.data = window.HELICOPTER_DEMO_DATA;
|
| 126 |
+
APP.core.demo._keyframeIndices = null; // Reset cache
|
| 127 |
+
log("Helicopter demo tracks loaded (CORS-safe mode).", "g");
|
| 128 |
+
return;
|
| 129 |
+
}
|
| 130 |
+
// Fallback to fetch (works when served from HTTP server)
|
| 131 |
+
try {
|
| 132 |
+
const resp = await fetch("data/helicopter_demo_tracks.json");
|
| 133 |
+
if (resp.ok) {
|
| 134 |
+
APP.core.demo.data = await resp.json();
|
| 135 |
+
APP.core.demo._keyframeIndices = null; // Reset cache
|
| 136 |
+
log("Helicopter demo tracks loaded.", "g");
|
| 137 |
+
}
|
| 138 |
+
} catch (err) {
|
| 139 |
+
console.warn("Failed to load helicopter demo tracks:", err);
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
};
|
frontend/js/ui/radar.js
CHANGED
|
@@ -635,6 +635,12 @@ APP.ui.radar.render = function (canvasId, trackSource, options = {}) {
|
|
| 635 |
APP.ui.radar.renderFrameRadar = function () {
|
| 636 |
const { state } = APP.core;
|
| 637 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 638 |
// In demo mode, use demo data for first frame (time=0) to match video radar initial state
|
| 639 |
let trackSource = state.detections;
|
| 640 |
if (APP.core.demo.active && APP.core.demo.data) {
|
|
@@ -650,6 +656,13 @@ APP.ui.radar.renderFrameRadar = function () {
|
|
| 650 |
|
| 651 |
APP.ui.radar.renderLiveRadar = function () {
|
| 652 |
const { state } = APP.core;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
// Live radar has sweep animation
|
| 654 |
APP.ui.radar.render("radarCanvas", state.tracker.tracks, { static: false });
|
| 655 |
};
|
|
|
|
| 635 |
APP.ui.radar.renderFrameRadar = function () {
|
| 636 |
const { state } = APP.core;
|
| 637 |
|
| 638 |
+
// Only show tracks after Reason has been clicked
|
| 639 |
+
if (!state.hasReasoned) {
|
| 640 |
+
APP.ui.radar.render("frameRadar", [], { static: true });
|
| 641 |
+
return;
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
// In demo mode, use demo data for first frame (time=0) to match video radar initial state
|
| 645 |
let trackSource = state.detections;
|
| 646 |
if (APP.core.demo.active && APP.core.demo.data) {
|
|
|
|
| 656 |
|
| 657 |
APP.ui.radar.renderLiveRadar = function () {
|
| 658 |
const { state } = APP.core;
|
| 659 |
+
|
| 660 |
+
// Only show tracks after Engage has been clicked (tracker running)
|
| 661 |
+
if (!state.tracker.running) {
|
| 662 |
+
APP.ui.radar.render("radarCanvas", [], { static: false });
|
| 663 |
+
return;
|
| 664 |
+
}
|
| 665 |
+
|
| 666 |
// Live radar has sweep animation
|
| 667 |
APP.ui.radar.render("radarCanvas", state.tracker.tracks, { static: false });
|
| 668 |
};
|