Dust DDS ist eine native Rust-Implementierung der von S2E Software Systems entwickelten OMG Data Distribution Services (DDS) und Real-time Publisher-Subscriber (RTPS).
Das Ziel dieser Kiste ist es, eine hochwertige Rust-Implementierung des minimalen DDS-Profils bereitzustellen. Mit hoher Qualität ist gemeint, dass die Implementierung mit stabilem Rust und ohne unsicheren Code und mit großer Unit-Test-Codeabdeckung erfolgt.
DDS ist ein Middleware-Protokoll und API-Standard, der für datenzentrierte Konnektivität entwickelt wurde. Im Kern zielt DDS darauf ab, den nahtlosen Austausch relevanter Daten genau dort zu ermöglichen, wo und wann sie benötigt werden, selbst zwischen Herausgebern und Abonnenten, die zeitlich asynchron arbeiten. Mit DDS können Anwendungen Informationen durch Lesen und Schreiben von Datenobjekten austauschen, die durch benutzerdefinierte Namen (Themen) und Schlüssel identifiziert werden. Eines seiner entscheidenden Merkmale ist die robuste Kontrolle über Quality-of-Service (QoS)-Parameter, einschließlich Zuverlässigkeit, Bandbreite, Lieferfristen und Ressourcenzuweisungen.
Der DDS-Standard „definiert sowohl die Anwendungsschnittstellen (APIs) als auch die Kommunikationssemantik (Verhalten und Dienstqualität), die die effiziente Bereitstellung von Informationen vom Informationsproduzenten zum entsprechenden Verbraucher ermöglichen“. Ergänzt wird dieser Standard durch die DDSI-RTPS-Spezifikation, die ein Interoperabilitäts-Drahtprotokoll für DDS definiert. Sein Hauptziel besteht darin, sicherzustellen, dass Anwendungen, die auf DDS-Implementierungen verschiedener Anbieter basieren, interoperabel sind. Die Implementierung von Dust DDS konzentriert sich hauptsächlich auf die Standards DDS und DDSI-RTPS.
Ein einfaches Beispiel für die Verwendung von Dust DDS. Die Herausgeberseite kann wie folgt implementiert werden:
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 ( ) ;
Die Abonnentenseite kann wie folgt implementiert werden:
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 ( ) ) ;
}
Wenn Sie nur Rust verwenden, können Sie die prozeduralen Makros nutzen, um die Übertragung eines Typs mit DustDDS zu ermöglichen. Die Schlüsselfelder können auch als Teil des Makros definiert werden.
use dust_dds :: topic_definition :: type_support :: DdsType ;
# [ derive ( DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
Wenn Sie verschiedene Programmiersprachen oder Anbieter verwenden, kann der DDS-Typ mithilfe der Kiste „dust_dds_gen“ aus einer OMG-IDL-Datei generiert werden.
Dust DDS bietet sowohl eine „synchrone“ als auch eine „asynchrone“ API, um die Integration von DDS in die größte Anzahl von Anwendungen mit maximaler Leistung zu ermöglichen. Im Allgemeinen sollte die erste Option darin bestehen, die Synchronisierungs-API zu verwenden und die von DDS spezifizierten Funktionen wie Listener für ereignisbasierte Programme zu nutzen.
Bei der Implementierung von Anwendungen, die bereits Async nutzen, muss die Async-API verwendet werden. Insbesondere bei Verwendung einer Tokio-Laufzeitumgebung führt die Verwendung der Sync-API zu einer Panik aufgrund blockierender Aufrufe. Ein Beispiel finden Sie im Beispielordner.
Wenn Sie über eine REST-API mit Ihren DDS-Daten interagieren möchten, können Sie unsere Nebula DDS WebLink-Software verwenden. Nebula DDS WebLink bietet einen Server, der den Web-Enabled DDS v1.0-Standard der Object Management Group (OMG) implementiert.
Die DDS-Interoperabilität wird normalerweise mithilfe einer Shapes-Demo getestet. Die Dust DDS Shapes-Demo ist in unserem Repository verfügbar und kann durch Ausführen von cargo run --package dust_dds_shapes_demo
aus dem Stammordner gestartet werden.
Dust DDS folgt keinem festen Veröffentlichungsplan, wir werden jedoch Veröffentlichungen veröffentlichen, sobald neue Funktionen implementiert werden.
Dieses Projekt ist unter der Apache-Lizenz Version 2.0 lizenziert.