Dust DDS est une implémentation native Rust des services de distribution de données OMG (DDS) et de l'éditeur-abonné en temps réel (RTPS) développés par S2E Software Systems.
L'objectif de cette caisse est de fournir une implémentation Rust de haute qualité du profil DDS minimum. Par haute qualité, cela signifie que l'implémentation est effectuée en utilisant Rust stable et sans code dangereux et avec une large couverture de code de test unitaire.
DDS est un protocole middleware et une norme API conçus pour la connectivité centrée sur les données. À la base, DDS vise à faciliter le partage transparent de données pertinentes précisément où et quand elles sont nécessaires, même entre éditeurs et abonnés fonctionnant de manière asynchrone dans le temps. Avec DDS, les applications peuvent échanger des informations via la lecture et l'écriture d'objets de données identifiés par des noms (sujets) et des clés définis par l'utilisateur. L'une de ses caractéristiques déterminantes est le contrôle robuste qu'il offre sur les paramètres de qualité de service (QoS), englobant la fiabilité, la bande passante, les délais de livraison et l'allocation des ressources.
La norme DDS « définit à la fois les interfaces d'application (API) et la sémantique de communication (comportement et qualité de service) qui permettent la transmission efficace des informations des producteurs d'informations au consommateur correspondant ». Cette norme est complétée par la spécification DDSI-RTPS, qui définit un protocole filaire d'interopérabilité pour le DDS. Son objectif principal est de garantir que les applications basées sur les implémentations DDS de différents fournisseurs peuvent interopérer. La mise en œuvre de Dust DDS s’articule principalement autour des normes DDS et DDSI-RTPS.
Un exemple de base sur la façon d'utiliser Dust DDS. Le côté éditeur peut être implémenté comme :
use dust_dds :: {
domain :: domain_participant_factory :: DomainParticipantFactory ,
infrastructure :: { qos :: QosKind , status :: NO_STATUS } ,
topic_definition :: type_support :: DdsType ,
} ;
# [ derive ( DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
let domain_id = 0 ;
let participant_factory = DomainParticipantFactory :: get_instance ( ) ;
let participant = participant_factory
. create_participant ( domain_id , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let topic = participant
. create_topic :: < HelloWorldType > ( "HelloWorld" , "HelloWorldType" , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let publisher = participant
. create_publisher ( QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let writer = publisher
. create_datawriter :: < HelloWorldType > ( & topic , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let hello_world = HelloWorldType {
id : 8 ,
msg : "Hello world!" . to_string ( ) ,
} ;
writer . write ( & hello_world , None ) . unwrap ( ) ;
Le côté abonné peut être implémenté comme :
use dust_dds :: {
domain :: domain_participant_factory :: DomainParticipantFactory ,
infrastructure :: { qos :: QosKind , status :: NO_STATUS } ,
subscription :: sample_info :: { ANY_INSTANCE_STATE , ANY_SAMPLE_STATE , ANY_VIEW_STATE } ,
topic_definition :: type_support :: DdsType ,
} ;
# [ derive ( Debug , DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
let domain_id = 0 ;
let participant_factory = DomainParticipantFactory :: get_instance ( ) ;
let participant = participant_factory
. create_participant ( domain_id , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let topic = participant
. create_topic :: < HelloWorldType > ( "HelloWorld" , "HelloWorldType" , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let subscriber = participant
. create_subscriber ( QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let reader = subscriber
. create_datareader :: < HelloWorldType > ( & topic , QosKind :: Default , None , NO_STATUS )
. unwrap ( ) ;
let samples = reader
. read ( 1 , ANY_SAMPLE_STATE , ANY_VIEW_STATE , ANY_INSTANCE_STATE ) ;
if let Ok ( hello_world_samples ) = samples {
println ! ( "Received: {:?}" , hello_world_samples [ 0 ] . data ( ) . unwrap ( ) ) ;
}
Si vous utilisez uniquement Rust, vous pouvez utiliser les macros procédurales pour permettre la transmission d'un type à l'aide de DustDDS. Les champs clés peuvent également être définis dans le cadre de la macro.
use dust_dds :: topic_definition :: type_support :: DdsType ;
# [ derive ( DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
Si vous utilisez différents langages de programmation ou fournisseurs, le type DDS peut être généré à partir d'un fichier OMG IDL à l'aide de la caisse dust_dds_gen.
Dust DDS fournit à la fois une API « sync » et une API « async » pour permettre l'intégration de DDS dans le plus grand nombre d'applications avec des performances maximales. En général, la première option doit consister à utiliser l'API de synchronisation et à utiliser les fonctionnalités spécifiées par DDS, telles que les écouteurs pour les programmes basés sur des événements.
Lors de la mise en œuvre d'applications qui utilisent déjà l'async, l'API async doit être utilisée. En particulier, lors de l'utilisation d'un runtime Tokio, l'utilisation de l'API Sync entraînera une panique due au blocage des appels. Vous pouvez voir un exemple dans le dossier exemples.
Si vous souhaitez interagir avec vos données DDS à l'aide d'une API REST, vous pouvez utiliser notre logiciel Nebula DDS WebLink. Nebula DDS WebLink fournit un serveur implémentant la norme DDS v1.0 Web-Enabled de l'Object Management Group (OMG).
L'interopérabilité DDS est généralement testée à l'aide d'une démonstration de formes. La démo Dust DDS Shapes est disponible sur notre référentiel et peut être démarrée en exécutant cargo run --package dust_dds_shapes_demo
à partir du dossier racine.
Dust DDS ne suit pas de calendrier de publication fixe, mais nous publierons des versions au fur et à mesure que de nouvelles fonctionnalités seront implémentées.
Ce projet est sous licence Apache License Version 2.0.