Dust DDS es una implementación nativa de Rust de los servicios de distribución de datos (DDS) de OMG y del editor-suscriptor en tiempo real (RTPS) desarrollados por S2E Software Systems.
El objetivo de esta caja es proporcionar una implementación Rust de alta calidad del perfil DDS mínimo. Por alta calidad se entiende que la implementación se realiza utilizando Rust estable y sin código inseguro y con una gran cobertura de código de prueba unitaria.
DDS es un protocolo de middleware y un estándar API diseñado para la conectividad centrada en datos. En esencia, DDS tiene como objetivo facilitar el intercambio fluido de datos pertinentes precisamente donde y cuando se necesitan, incluso entre editores y suscriptores que operan de forma asincrónica en el tiempo. Con DDS, las aplicaciones pueden intercambiar información mediante la lectura y escritura de objetos de datos identificados por nombres definidos por el usuario (Temas) y claves. Una de sus características definitorias es el control sólido que ofrece sobre los parámetros de calidad de servicio (QoS), que abarca confiabilidad, ancho de banda, plazos de entrega y asignaciones de recursos.
El estándar DDS "define tanto las Interfaces de Aplicación (API) como la Semántica de Comunicación (comportamiento y calidad de servicio) que permiten la entrega eficiente de información desde los productores de información al consumidor correspondiente". Complementando este estándar está la especificación DDSI-RTPS, que define un protocolo de cable de interoperabilidad para DDS. Su objetivo principal es garantizar que las aplicaciones basadas en implementaciones de DDS de diferentes proveedores puedan interoperar. La implementación de Dust DDS se centra principalmente en los estándares DDS y DDSI-RTPS.
Un ejemplo básico de cómo utilizar Dust DDS. El lado del editor se puede implementar como:
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 ( ) ;
El lado del suscriptor se puede implementar como:
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 usa solo Rust, puede utilizar las macros de procedimiento para permitir que un tipo se transmita usando DustDDS. Los campos clave también se pueden definir como parte de la macro.
use dust_dds :: topic_definition :: type_support :: DdsType ;
# [ derive ( DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
Si utiliza diferentes lenguajes de programación o proveedores, el tipo DDS se puede generar a partir de un archivo OMG IDL utilizando la caja Dust_dds_gen.
Dust DDS proporciona una API "sincronizada" y "asincrónica" para permitir la integración de DDS en la mayor cantidad de aplicaciones con el máximo rendimiento. En general, la primera opción debería ser utilizar la API de sincronización y hacer uso de la funcionalidad especificada de DDS, como escuchas para programas basados en eventos.
Al implementar aplicaciones que ya utilizan async, se debe utilizar la API async. En particular, cuando se utiliza un tiempo de ejecución de Tokio, el uso de la API de sincronización provocará pánico debido al bloqueo de llamadas. Puede encontrar un ejemplo en la carpeta de ejemplos.
Si desea interactuar con sus datos DDS utilizando una API REST, puede utilizar nuestro software Nebula DDS WebLink. Nebula DDS WebLink proporciona un servidor que implementa el estándar DDS v1.0 habilitado para web del Object Management Group (OMG).
La interoperabilidad de DDS normalmente se prueba mediante una demostración de formas. La demostración de Dust DDS Shapes está disponible en nuestro repositorio y se puede iniciar ejecutando cargo run --package dust_dds_shapes_demo
desde la carpeta raíz.
Dust DDS no sigue un calendario de lanzamiento fijo, pero realizaremos lanzamientos a medida que se implementen nuevas funciones.
Este proyecto tiene la licencia Apache License Versión 2.0.