fix(anim 1): cycle guard interval + ping2 visual ring

Two fixes for the visual confusion of 'A appears to send two pings back to back':

1. Add 600 ms (sim) guard interval between cycle N's tPing2Recv and cycle N+1's
   tPing1Send. Removes the visual hiccup where ping2 (end of cycle N) and ping1
   (start of cycle N+1) collided as two consecutive A→B cyan pulses.

2. Distinguish ping2 from ping1 visually: ping1 = solid filled circle, ping2 =
   hollow ring (same cyan color). Legend updated. The user can now tell at a
   glance which transmission is which without relying on the small label text.

Reported by Flag 2026-04-27, fixed same day.
This commit is contained in:
2026-04-27 14:40:00 +00:00
parent 65eb7a9dd5
commit ab7140968a

View File

@@ -153,8 +153,9 @@ distance = TOF · c avec c ≈ 1500 m/s en eau de mer
<div style="margin-top:10px;" class="legend">
<span><span class="sw" style="background:#5ad1ff"></span>USBL A (fixe)</span>
<span><span class="sw" style="background:#ff8b5a"></span>USBL B (mobile)</span>
<span><span class="sw" style="background:#5ad1ff"></span>ping (A→B)</span>
<span><span class="sw" style="background:#ff8b5a"></span>pong (B→A)</span>
<span><span class="sw" style="background:#5ad1ff"></span>ping1 (A→B, plein)</span>
<span><span class="sw" style="background:#ff8b5a"></span>pong (B→A, plein)</span>
<span><span class="sw" style="background:transparent;border:2px solid #5ad1ff;border-radius:2px"></span>ping2 (A→B, anneau)</span>
</div>
<canvas id="plot" width="900" height="220" style="margin-top:14px;"></canvas>
<div class="legend" style="margin-top:6px;">
@@ -338,8 +339,13 @@ Ce schéma est exactement celui qu'utilisent les puces UWB <b>DecaWave DW1000 /
const history = [];
let nCycles = 0;
// Guard interval (s sim) between two consecutive cycles, to avoid the visual
// confusion where A's ping2 (end of cycle N) and ping1 (start of cycle N+1)
// look like two back-to-back transmissions from A.
const CYCLE_GUARD = 0.6;
function ensureCycle() {
if (!cycle || simT >= cycle.tPing2Recv) {
if (!cycle || simT >= cycle.tPing2Recv + CYCLE_GUARD) {
if (cycle) {
history.push({
tStart: cycle.tPing1Send,
@@ -352,7 +358,7 @@ Ce schéma est exactement celui qu'utilisent les puces UWB <b>DecaWave DW1000 /
nCycles++;
if (history.length > 600) history.shift();
}
const startT = cycle ? cycle.tPing2Recv : 0;
const startT = cycle ? cycle.tPing2Recv + CYCLE_GUARD : 0;
cycle = buildCycle(startT);
}
}
@@ -405,9 +411,9 @@ Ce schéma est exactement celui qu'utilisent les puces UWB <b>DecaWave DW1000 /
// Pulses for current cycle
if (cycle) {
const pulses = [
{ sendT: cycle.tPing1Send, recvT: cycle.tPing1Recv, fromA: true, color: '#5ad1ff', label: 'ping' },
{ sendT: cycle.tPongSend, recvT: cycle.tPongRecv, fromA: false, color: '#ff8b5a', label: 'pong' },
{ sendT: cycle.tPing2Send, recvT: cycle.tPing2Recv, fromA: true, color: '#5ad1ff', label: 'ping2' },
{ sendT: cycle.tPing1Send, recvT: cycle.tPing1Recv, fromA: true, color: '#5ad1ff', label: 'ping1', shape: 'solid' },
{ sendT: cycle.tPongSend, recvT: cycle.tPongRecv, fromA: false, color: '#ff8b5a', label: 'pong', shape: 'solid' },
{ sendT: cycle.tPing2Send, recvT: cycle.tPing2Recv, fromA: true, color: '#5ad1ff', label: 'ping2', shape: 'ring' },
];
for (const p of pulses) {
if (t < p.sendT || t > p.recvT) continue;
@@ -421,8 +427,14 @@ Ce schéma est exactement celui qu'utilisent les puces UWB <b>DecaWave DW1000 /
const x = xs + (xe - xs) * frac;
ctx.beginPath();
ctx.arc(x, yLine, 7, 0, Math.PI * 2);
if (p.shape === 'ring') {
ctx.strokeStyle = p.color;
ctx.lineWidth = 2.5;
ctx.stroke();
} else {
ctx.fillStyle = p.color;
ctx.fill();
}
// trail
const trailLen = 60;
const dir = (xe > xs) ? -1 : 1;