High-level Python wrapper around the upstream cosma-tech/kogger_acousticAntenna
driver. Configures a Kogger acoustic antenna as a permanent slave transponder
in a single start() call: address filter, echo filter, optional TDMA sync slot,
permanent response window, and Python callbacks for each ping received.
No modification to the upstream driver — only composes existing public methods
in the right order. Snapshot of upstream driver included read-only under driver/
for reference.
Includes:
- transponder_continu.py (302 lines): the wrapper class + CLI
- examples/auv_slave.py (79 lines): usage example with logging
- README.md: design rationale, usage, multi-AUV TDMA, watchdog, hardware wiring
- driver/: snapshot of cosma-tech/kogger_acousticAntenna at commit 1b539f9
('Add index slot for multi pinger', 2025-03-11)
Built for Cosma context (USV master + N AUVs slaves) following the design
conversation in Discord #ping-pong-ping (2026-04-27). See poulpe/ping-pong-ping
on Gitea for the interactive demo of the protocol.
Kogger USBL — mode transpondeur continu
Wrapper Python de haut niveau autour du driver Kogger kogger_acousticAntenna (cosma-tech) qui configure une antenne acoustique en slave transpondeur permanent : elle écoute en continu les pings adressés à son ID, répond automatiquement, ignore les autres, et expose un callback Python pour chaque ping reçu.
Pas de re-armement par ping. Une seule init. Le device répond tant que le process tourne.
Construit pour le contexte Cosma (USV master + N AUVs slaves), suite à la conversation Discord #ping-pong-ping du 2026-04-27 sur les schémas SS-TWR + écoute passive OWR.
Pourquoi ce wrapper
Le driver Kogger upstream (kogger_protocol_driver.KoggerSBPDevice) expose toutes les commandes bas niveau nécessaires pour le mode transpondeur :
| Commande | Rôle |
|---|---|
set_usbl_transponder(enable) |
Ouvre/ferme la fenêtre de réponse acoustique. True = always (timeout 0xFFFFFFFF µs). |
set_usbl_request_address_filter([...]) |
Liste 8 adresses (0-7 ou 0xFF=désactivé) pour lesquelles le device doit répondre. |
set_usbl_monitor_config(enable, echo_filter_response_us, echo_filter_request_us) |
Active la surveillance + le filtre d'écho (évite l'auto-déclenchement par réverbération). |
set_sync_mode(slot_total, slot_index, slot_duration, enable_delay) |
Enrôle le device dans un slot TDMA (utile en multi-slave). |
register_callback(ID_USBL_SOLUTION, fn) |
Branche un callback Python sur les frames USBL solution reçues. |
Mais il faut les composer dans le bon ordre, gérer les callbacks, et idéalement avoir un watchdog qui ré-applique la config si le device a redémarré ou que le master a été silencieux trop longtemps.
C'est exactement ce que ContinuousTransponder fait — un appel start() configure tout et le device entre en mode permanent.
Architecture
.
├── README.md # ce fichier
├── transponder_continu.py # ★ wrapper haut niveau (zéro modif du driver)
├── examples/
│ └── auv_slave.py # exemple AUV slave avec logging
└── driver/ # snapshot read-only du driver upstream
├── kogger_protocol_driver.py (1509 lignes, 78 KB)
├── communication.py
├── interface.py
├── simulation_kogger.py
├── README.md
└── ...
Aucune modification du driver Kogger d'origine. Tout passe par les méthodes publiques. Quand cosma-tech publie une nouvelle version du driver, il suffit de remplacer le contenu de driver/ — ce wrapper continue de fonctionner.
Usage minimal
from transponder_continu import ContinuousTransponder
t = ContinuousTransponder(port="/dev/ttyUSB0", my_address=2,
vehicle_name="AUV-2")
t.on_ping_received(lambda solution: print("ping →", solution))
t.start()
try:
t.run_forever()
finally:
t.stop()
CLI directement
python3 transponder_continu.py --port /dev/ttyUSB0 --address 2
Options utiles :
--vehicle AUV-2 # étiquette pour les logs CSV du driver
--watchdog-s 15 # ré-applique la config si silence > 15 s
--slot-total 4 --slot-index 1 --slot-duration 2.0 # enrôle en TDMA
--echo-filter-us 400000 # 400 ms (défaut)
Contenu de la trame transpondeur
Chaque fois que le master USV envoie un ping ciblé sur l'adresse de cet AUV :
- Le hardware Kogger filtre par adresse (configuré par
set_usbl_request_address_filter). - Si l'adresse correspond, le hardware répond automatiquement (le pong est généré par l'antenne, pas par Python — c'est rapide et déterministe).
- Le driver émet une frame
ID_USBL_SOLUTION(0x65) sur la sortie UART contenant la distance hardware-computed, le SNR, l'ID source. - Le wrapper appelle votre callback
on_ping_received(message). - Le state interne (
t.state.last_distance_m,last_snr,last_ping_id,pings_received) est mis à jour.
Tout cela en boucle, sans intervention.
Multi-AUV en TDMA
Si N AUVs partagent le canal et que le master scanne en round-robin, configurer chaque slave dans son propre slot évite les collisions de pong :
ContinuousTransponder(
port="/dev/ttyUSB0",
my_address=2,
sync=SyncSlot(slot_total=4, slot_index=1, slot_duration=2.0),
)
→ AUV-2 ne répond que pendant son slot (slot_index=1, durée 2 s, cycle complet 8 s).
Convention proposée : slot_index = my_address - 1.
Watchdog
Si on n'a rien reçu depuis watchdog_timeout_s secondes (et qu'on a au moins reçu un ping au démarrage), le wrapper ré-applique set_usbl_transponder(enable=True). Couvre le cas où l'antenne Kogger reboot silencieusement et perd sa config.
ContinuousTransponder(..., watchdog_timeout_s=15.0)
Off par défaut. Activer en prod si le master est censé pinger en continu.
Hardware
Câblage Kogger côté antenne (recopié du README upstream pour référence) :
| Couleur | Signal |
|---|---|
| Brown | +V supply |
| Blue | GND |
| Green | UART RX (USBL ← host) |
| Yellow | UART TX (USBL → host) |
| Pink | GND (relié au bleu interne) |
| Gray | TRIGGER_IN |
| White | TRIGGER_OUT |
Connexion typique : Pi4B → USB-UART converter → antenne Kogger. Baudrate par défaut 921600.
Limites / TODO
- Pas testé sur hardware réel (uniquement statique). Cf. test sur AUV-2 cosma au prochain déploiement.
- Pas de gestion de reconnexion USB-UART. Si le port disparaît, le process meurt — relancer côté systemd.
- Pas de support multi-port (un wrapper = une antenne). Pour multi-antennes sur un même Pi, instancier N
ContinuousTransponderindépendants. - L'écoute passive OWR (calcul de distance par non-ciblés à partir de
T_recv − T_send) n'est pas dans ce wrapper — elle nécessite une référence temporelle synchronisée USV↔AUVs et l'extraction deT_senddepuis la trame du ping (pas exposé proprement par le driver upstream pour l'instant). À ajouter quand le besoin se présente. - Ajouter un
start()idempotent (actuellement appeler 2× réenroule les callbacks).
Références
- Driver upstream :
git@github.com:cosma-tech/kogger_acousticAntenna.git - Page démo USBL DS-TWR + SS-TWR + OWR : https://laboratoire.freeboxos.fr/ping-pong-ping/
- Repo demo :
poulpe/ping-pong-pingsur Gitea - Conversation Discord d'origine :
#ping-pong-ping(2026-04-27)