// challenge ministère des armées · juin 2025
COHOMA.
Transmission de cartes 3D voxelisées depuis un drone vers un serveur central, en environnement contraint.
// Contexte
Le Challenge COHOMA (Collaborative Human/Robot Machine Awareness) est organisé par le Ministère des Armées. L'objectif : transmettre des cartes 3D de l'environnement depuis un drone vers un serveur central en temps réel, via des réseaux contraints (Wi-Fi dégradé, UDP). Le projet couvre toute la chaîne : génération OctoMap, compression, transmission, réassemblage et stockage.
// Server UDP · C++ / ASIO
Serveur C++ utilisant Boost.ASIO pour recevoir des cartes OctoMap fragmentées via UDP. Pipeline : réception → réassemblage → décompression zlib → extraction des voxels → insertion PostgreSQL.
flowchart LR
D["Drone (ROS 2)"] --> OM["OctoMap Server\npointcloud → octomap binaire"]
OM --> MW["Middleware C++\ncompression zlib, envoi UDP"]
MW --> NG["Net Guard\ncontrôle RSSI Wi-Fi\n(suspend si signal < seuil)"]
NG -->|UDP fragments| SV["server_udp (C++ / ASIO)"]
SV --> RE["Réassemblage blobs"]
RE --> DC["Décompression zlib"]
DC --> PV["Parsing voxels"]
PV --> PG["INSERT PostgreSQL\nON CONFLICT UPDATE"]
// Middleware · ROS 2 + C++
Le middleware embarqué écoute le topic ROS 2 /octomap_binary,
compresse l'OctoMap avec zlib et l'envoie en UDP. Un système de Net Guard
surveille le RSSI Wi-Fi et suspend l'envoi si le signal est trop faible.
// Topics ROS 2
- /depth/points → PointCloud2
- /octomap_binary → Octomap
// Variables d'env
- DRONE_ID (ex: DT1)
- TRANSPORT_URL (udp://...)
- RSSI_MIN (ex: -75 dBm)
- WIFI_IFACE (ex: wlan0)
// Schéma DB
CREATE TABLE spatial_points ( x INT, y INT, z INT, color_r SMALLINT, color_g SMALLINT, color_b SMALLINT, color_a SMALLINT, timestamp BIGINT, nb_records INT, PRIMARY KEY (x, y, z) ); CREATE INDEX sp_xyz_gist ON spatial_points USING gist (point(x, y, z));
// INSERT ... ON CONFLICT ... UPDATE pour les mises à jour de voxels existants
// Refonte Python → C++
La version précédente (Python, stage IG4) était monolithique : middleware ROS 2 et insertion BDD dans le même nœud, sans séparation des responsabilités. Elle présentait des latences importantes (complexité O(n²) sur >10k voxels) et aucune logique réseau.
La refonte en C++17 + ASIO sépare middleware embarqué et serveur, avec thread-pool natif, zéro dépendance ROS côté serveur, et une fragmentation MTU-aware avec protocole d'entête binaire structuré (16 octets).
// Entête UDP — 16 octets (packé, little-endian) struct UdpHeader { uint32_t seq; // ID snapshot (drone_id + seq) uint32_t total_size; // Taille totale du blob compressé uint32_t offset; // Offset du fragment courant uint16_t payload_len;// Longueur utile du fragment uint8_t flags; // Flags (START, END...) uint8_t drone_id; // Identifiant numérique du drone };
// Points techniques
// Réseau contraint
UDP pour le temps réel, fragmentation des OctoMap, Net Guard avec contrôle RSSI.
// Multithreading
Serveur ASIO multithreadé : paquets en parallèle du réassemblage et de l'insertion DB.
// Compression
zlib niveau 1 pour réduire la taille des OctoMap avant transmission UDP.
// Index spatial
Index GiST sur point(x,y,z) pour des requêtes spatiales rapides sur les voxels 3D.