Dust DDS é uma implementação nativa do Rust dos OMG Data Distribution Services (DDS) e Real-time Publisher-Subscriber (RTPS) desenvolvidos pela S2E Software Systems.
O objetivo desta caixa é fornecer uma implementação Rust de alta qualidade do perfil DDS mínimo. Para alta qualidade significa que a implementação é feita usando Rust estável e sem código inseguro e com grande cobertura de código de teste de unidade.
DDS é um protocolo de middleware e um padrão de API projetado para conectividade centrada em dados. Em sua essência, o DDS visa facilitar o compartilhamento contínuo de dados pertinentes precisamente onde e quando são necessários, mesmo entre editores e assinantes que operam de forma assíncrona no tempo. Com o DDS, as aplicações podem trocar informações através da leitura e escrita de objetos de dados identificados por nomes (Tópicos) e chaves definidos pelo usuário. Uma de suas características definidoras é o controle robusto que oferece sobre os parâmetros de qualidade de serviço (QoS), abrangendo confiabilidade, largura de banda, prazos de entrega e alocações de recursos.
O padrão DDS “define tanto as Interfaces de Aplicação (APIs) quanto a Semântica de Comunicação (comportamento e qualidade de serviço) que permitem a entrega eficiente de informações dos produtores de informações ao consumidor correspondente”. Complementando este padrão está a especificação DDSI-RTPS, que define um protocolo de interoperabilidade para DDS. Seu objetivo principal é garantir que aplicativos baseados em implementações de DDS de diferentes fornecedores possam interoperar. A implementação do Dust DDS gira principalmente em torno dos padrões DDS e DDSI-RTPS.
Um exemplo básico de como usar o Dust DDS. O lado do editor pode ser implementado 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 ( ) ;
O lado do assinante pode ser implementado 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 ( ) ) ;
}
Se estiver usando apenas Rust, você pode usar as macros procedurais para permitir que um tipo seja transmitido usando DustDDS. Os campos-chave também podem ser definidos como parte da macro.
use dust_dds :: topic_definition :: type_support :: DdsType ;
# [ derive ( DdsType ) ]
struct HelloWorldType {
# [ dust_dds ( key ) ]
id : u8 ,
msg : String ,
}
Se estiver usando diferentes linguagens de programação ou fornecedores, o tipo DDS pode ser gerado a partir de um arquivo OMG IDL usando a caixa dust_dds_gen.
Dust DDS fornece uma API "sincronizada" e "assíncrona" para permitir a integração do DDS no maior número de aplicações com desempenho máximo. Em geral, a primeira opção deve ser usar a API de sincronização e fazer uso da funcionalidade especificada pelo DDS, como ouvintes para programas baseados em eventos.
Ao implementar aplicações que já fazem uso de assíncrono, então a API assíncrona deve ser utilizada. Em particular, ao usar um tempo de execução Tokio, usar a API Sync resultará em pânico devido ao bloqueio de chamadas. Você pode encontrar um exemplo na pasta de exemplos.
Se quiser interagir com seus dados DDS usando uma API REST, você pode usar nosso software Nebula DDS WebLink. Nebula DDS WebLink fornece um servidor que implementa o padrão DDS v1.0 habilitado para Web do Object Management Group (OMG).
A interoperabilidade DDS normalmente é testada usando uma demonstração de formas. A demonstração do Dust DDS Shapes está disponível em nosso repositório e pode ser iniciada executando cargo run --package dust_dds_shapes_demo
na pasta raiz.
Dust DDS não segue um cronograma de lançamento fixo, mas faremos lançamentos à medida que novos recursos forem implementados.
Este projeto está licenciado sob a Licença Apache Versão 2.0.