# Ping-Pong-Ping
Interactive HTML demo + reference notes for **acoustic distance ranging** between USBL nodes (USV master ↔ AUV slaves). Built collaboratively between Flag and Poulpe on 2026-04-27 from a single design conversation.
**Live demo** : https://laboratoire.freeboxos.fr/ping-pong-ping/
---
## What this archives
A self-contained `index.html` (no framework, no external assets) that explains and animates two acoustic ranging schemes used in underwater positioning:
1. **DS-TWR** (Double-Sided Two-Way Ranging) — symmetric ping/pong/ping where **both** sides learn the distance without clock synchronization. Used when the two nodes are peers (mobile-mobile, swarm coopératif).
2. **SS-TWR + passive OWR** (Single-Sided Two-Way Ranging + One-Way Ranging by passive listeners) — asymmetric scheme used when **only the master needs the distance**, with the bonus that any other AUV in acoustic range can compute its own distance to the master from the same single ping.
Both animations run continuously, with realistic AUV operating parameters (1–2 kt cruise speed, 5–700 m range, c = 1500 m/s).
## The protocol — short version
### DS-TWR (animation 1)
```
A → B : ping1
B → A : pong (B encodes turnaround_B in the pong frame)
A → B : ping2 (A encodes turnaround_A in the ping2 frame)
A side : TOF = (round_trip_A − turnaround_B) / 2
B side : TOF = (round_trip_B − turnaround_A) / 2
distance = TOF · c
```
No clock sync required. Each side measures only local deltas.
### SS-TWR + passive OWR (animation 2)
```
USV → AUVi (addressed) : ping (frame carries target ID 0xAi + send timestamp)
AUVi receives → match ID → responds:
AUVi → USV : pong (encodes turnaround_AUVi)
All other AUVj receive the same ping (medium is shared):
AUVj computes distance passively : (T_recv_local − T_send_USV) · c
USV side (active TWR for AUVi) : TOF = (round_trip − turnaround_AUVi) / 2
AUVj side (passive OWR) : TOF = T_recv_local − T_send_USV
```
**One ping → N range fixes.** The medium remains free between cycles.
### Required infrastructure for OWR
The passive AUVs must share a **time reference** with the USV. Two practical options:
- **GPS-disciplined oscillators** synchronized at the surface before mission launch, with bounded drift (typically < 1 µs over a few hours for OCXO-grade clocks).
- **Send-timestamp embedded in the ping frame** : the USV writes its clock value `T_send` in the ping payload, every receiver reads it and compares to its own `T_recv`. Subject to the same clock-drift caveat.
DS-TWR (animation 1) does **not** need this — that's its main feature. SS-TWR + passive OWR (animation 2) trades the synchronization requirement for much faster scan rates.
## Design decisions taken in the conversation
These reflect the iterative refinement during the conversation, summarized so the rationale isn't lost:
| Decision | Why |
|---|---|
| **Two animations, not three** | Initially the multi-AUV section had a Broadcast (BC-DS-TWR) mode with N pongs in staggered slots. Flag judged it "relou" — addressed sequential is conceptually simpler, no slot collisions, and combined with passive OWR it's faster anyway. Dropped. |
| **SS-TWR (not DS-TWR) for multi-AUV** | In the iUSBL setup (USV tracks AUVs), only the USV needs the distance. The third leg (ping2) is dead weight. Switched the multi-AUV animation to SS-TWR, kept DS-TWR for the principle demo where the symmetry matters. |
| **Passive OWR for non-target AUVs** | Originally non-target AUVs were drawn as "✗ ignore". Flag pointed out they can use the ping passively. Each ping now produces N range fixes (1 active + N−1 passive). |
| **Realistic AUV speeds (1–2 kt) and ranges (5–700 m)** | First version had AUVs moving at ~140 kt over 5 km — physically impossible. Recalibrated to typical coastal AUV ops. |
| **No DS-TWR-vs-SS-TWR speedup table** | Removed cycle-time comparison readouts to avoid clutter. The "fluidity" is visible directly. |
| **No ID match alarm** | Replaced "✗ ignore" red alert with "📡 passive OWR" cyan badge, since non-target AUVs are useful, not ignored. |
## File structure
```
ping-pong-ping/
├── index.html # self-contained demo (HTML + CSS + JS, no externals)
├── README.md # this file
└── deploy.sh # one-shot push to Core Caddy webroot
```
`index.html` contains two `