Aller au contenu principal

Architecture de HDDS

HDDS suit une architecture en couches conçue pour la performance, la modularité et la conformité aux standards.

Vue d'ensemble des couches

+---------------------------------------------------------+
| Couche Application |
| (Votre application Rust/C/C++/Python) |
+---------------------------------------------------------+
| Couche DCPS |
| DomainParticipant | Publisher | Subscriber | Topic | QoS|
+---------------------------------------------------------+
| Couche RTPS |
| Discovery (SPDP/SEDP) | Writers | Readers | History |
+---------------------------------------------------------+
| Couche Transport |
| UDP Multicast | UDP Unicast | Shared Memory |
+---------------------------------------------------------+

Couche DCPS (Data-Centric Publish-Subscribe)

La couche DCPS fournit l'API DDS avec laquelle les applications interagissent :

EntitéRole
DomainParticipantPoint d'entrée, possède toutes les autres entités
PublisherRegroupe les DataWriters, applique des QoS communes
SubscriberRegroupe les DataReaders, applique des QoS communes
TopicCanal de données nommé avec un type
DataWriterÉcrit des échantillons sur un Topic
DataReaderLit des échantillons depuis un Topic

Hiérarchie des entités

DomainParticipant
+-- Publisher
| +-- DataWriter<SensorData>
| +-- DataWriter<Command>
+-- Subscriber
| +-- DataReader<SensorData>
| +-- DataReader<Status>
+-- Topic
+-- "SensorTopic"
+-- "CommandTopic"

Couche RTPS (Real-Time Publish-Subscribe)

La couche RTPS implémente le protocole filaire pour l'interopérabilité :

RTPS Writers et Readers

+------------------+     Protocole RTPS      +------------------+
| RTPS Writer | ----------------------> | RTPS Reader |
| | | |
| +------------+ | DATA, HEARTBEAT | +------------+ |
| | History | | ---------------------> | | History | |
| | Cache | | | | Cache | |
| +------------+ | ACKNACK, GAP | +------------+ |
| | <--------------------- | |
+------------------+ +------------------+

History Cache

Chaque Writer et Reader maintient un History Cache :

  • Writer History : Stocke les échantillons jusqu'à l'acquittement
  • Reader History : Stocke les échantillons reçus jusqu'à leur consommation
use hdds::QoS;

// History depth controlled by QoS
let qos = QoS::reliable().keep_last(100);

Architecture de la découverte

La découverte utilise deux protocoles s'exécutant sur des endpoints intégrés :

+---------------------------------------------------------+
| DomainParticipant |
+----------------------------+----------------------------+
| SPDP (Participants) | SEDP (Endpoints) |
| | |
| BuiltinParticipant | BuiltinPublications |
| Writer/Reader | Writer/Reader |
| | |
| Multicast: 239.255.x.x | BuiltinSubscriptions |
| Port: 7400 + offset | Writer/Reader |
+----------------------------+----------------------------+

Flux de découverte

1. Annonce SPDP (multicast)
Participant A --> 239.255.0.1:7400 --> Participant B

2. Échange SEDP (unicast)
A.Publications ------> B (infos endpoints)
A <------ B.Publications (infos endpoints)

3. Appariement
A.Writer apparié avec B.Reader (QoS compatibles)

4. Flux de données utilisateur
A.Writer --> DATA --> B.Reader

Couche Transport

HDDS supporte plusieurs transports :

TransportCas d'usageLatence
UDP MulticastDiscovery, multi-SubscriberMoyenne
UDP UnicastPoint à point, WANMoyenne
Shared MemoryMême hôte, haute performanceFaible (~1 us)

Sélection du transport

let config = ParticipantConfig::default()
.transport(Transport::UdpMulticast) // Default
.transport(Transport::SharedMemory); // Add SHM

Modèle de threading

HDDS utilise un runtime async avec des threads dédiés :

+---------------------------------------------------------+
| Threads utilisateur |
| (write(), take(), create_reader(), etc.) |
+---------------------------------------------------------+
| Runtime HDDS |
| +-------------+ +-------------+ +------------------+ |
| | Discovery | | Pool I/O | | Timer/Scheduler | |
| | Thread | | (tokio) | | | |
| +-------------+ +-------------+ +------------------+ |
+---------------------------------------------------------+
  • Threads utilisateur : Les appels applicatifs sont non-bloquants autant que possible
  • Thread Discovery : Gère le protocole SPDP/SEDP
  • Pool I/O : Opérations réseau async (basées sur tokio)
  • Thread Timer : Heartbeats, deadlines, liveliness

Architecture mémoire

Chemin zéro-copy

Pour les scenarios haute performance, HDDS supporte le zéro-copy :

// Standard path (copy)
writer.write(&sample)?;

// Zéro-copy path (loan buffer)
let mut loan = writer.loan_sample()?;
*loan = sample;
loan.write()?; // No copy to internal buffer

Gestion des buffers

+-----------------+    +-----------------+    +-----------------+
| Buffer utilisa-| | History Cache | | Buffer réseau |
| teur | -> | (par Writer) | -> | (par envoi) |
+-----------------+ +-----------------+ +-----------------+

Les limites de ressources empechent une croissance mémoire non bornee :

use hdds::QoS;

let qos = QoS::reliable()
.max_samples(10000)
.max_instances(100)
.max_samples_per_instance(100);

Flux de données

Chemin d'ecriture

1. L'application appelle writer.write(&sample)
2. L'échantillon est sérialisé (CDR2/XCDR2)
3. Ajouté au History Cache du Writer
4. Encapsule dans un sous-message RTPS DATA
5. Envoyé via le transport (UDP/SHM)
6. Acquitté (si reliable)
7. Retiré de l'historique (si acquitté)

Chemin de lecture

1. Le réseau reçoit un paquet RTPS
2. Analyse des sous-messages (DATA, HEARTBEAT, etc.)
3. Désérialisation de l'échantillon
4. Ajout au History Cache du Reader
5. Envoi d'ACKNACK (si reliable)
6. L'application appelle reader.take()
7. L'échantillon est retiré de l'historique

Structure des modules

hdds/
+-- dcps/ # API DDS (Participant, Publisher, etc.)
+-- rtps/ # Implémentation du protocole RTPS
| +-- writer.rs # Machine à états RTPS Writer
| +-- reader.rs # Machine à états RTPS Reader
| +-- discovery/ # SPDP et SEDP
| +-- messages/ # Types de messages RTPS
+-- transport/ # Transports réseau
| +-- udp.rs
| +-- shm.rs
+-- serialization/ # Codecs CDR/XCDR2
+-- qos/ # Implémentations des politiques QoS

Caractéristiques de performance

OperationLatence typique
write() vers le réseau5-50 us
Réseau vers take()10-100 us
Aller-retour Shared Memory1-5 us
Discovery (démarrage à froid)100-500 ms

Prochaines étapes