Expand description
A pure Rust implementation of Data Distribution Service (DDS).
DDS is an object-oriented API specified by the Object Management Group.
DDS communicates over the network using the RTPS protocol, which by default runs over UDP/IP.
This implementation does not attempt to make an accurate implementation of the DDS object API, as it would be quite unnatural to use in Rust as such. However, we aim for functional compatibility, while at the same time using Rust techniques and conventions.
Additionally, there is a ROS2 interface, that is simpler to use than DDS
when communicating to ROS2 components. See package ros2-client.
Note: Do not use module ros2
contained within RustDDS. It is no longer
being developed.
§DDS usage summary
- Create a
DomainParticipant
. You have to choose a domain id. The default value is zero. - Create or find a
Topic
from theDomainParticipant
. Topics have a name and a type. - Create a
Publisher
and/orSubscriber
from theDomainParticipant
. - To receive data, create a
DataReader
fromSubscriber
andTopic
. - To send data, create a
DataWriter
fromPublisher
andTopic
. - Data from
DataReader
can be read or taken. Taking removes the data samples from the DataReader, whereas reading only marks them as read.
§Concepts
- Data is sent and received in consecutive samples. When read, a sample is
accompanied with
SampleInfo
, which contains DDS-generated metadata. - Topics are either With_Key or No_Key.
- With_Key topics are like map data structures, containing multiple instances (map entries), identified by a key. The key must be something that can be extracted from the data samples. Instances can be created (published) and deleted (disposed).
- No_Key topics have always only one instance, which cannot be disposed.
- Many types and traits in RustDDS have both with_key and no_key versions. This is because with_key communication must be able to access keys from data samples, so it is required in type signatures. Such requirement makes no sense for no_key communication, so signature must be different.
§Interfacing Rust data types to DDS
- DDS, as specified, takes care of data serialization and deserialization. In order for RustDDS to do this, the payload data must be Serde serializable/deserializable.
- If your data is to be communicated over a WithKey topic, the payload data
type must implement
Keyed
trait from this crate. - If you are using CDR serialization
(specification, Section 15.3) , which
is the DDS default, then use
CDRSerializerAdapter
andCDRDeserializerAdapter
when such adapters are required. If you need to use another serialization format, then you should find or write a Serde data format implementation and wrap it as a (De)SerializerAdapter.
§Polling multiple DataReaders
There are three alternative methods to poll DataReaders (and DataWriters): mio-0.6, mio-0.8, and async. Use only one of these!
§mio-0.6
RustDDS is designed to used with mio version 0.6.x. DataReaders
implement Evented
so that they can be directly
registered to a poll
. See example shapes_demo
.
§mio-0.8
RustDDS DataReaders implement mio_08::event::Source
for registering with
mio-0.8. See example shapes_demo_mio_08
§async
DataReader and DataWriter can do Rust async I/O by converting themselves to
futures::stream::Stream
s.
crate::dds::with_key::DataReader::async_sample_stream
to get datacrate::dds::with_key::DataReader::async_bare_sample_stream
to get bare datacrate::dds::with_key::BareDataReaderStream::async_event_stream
orcrate::dds::with_key::DataReaderStream::async_event_stream
to get data status events
See exampe async_shapes_demo
.
§Usage Example
use rustdds::*;
use rustdds::no_key::{DataReader, DataWriter, DataSample}; // We use a NO_KEY topic here
use serde::{Serialize, Deserialize};
// DomainParticipant is always necessary
let domain_participant = DomainParticipant::new(0).unwrap();
let qos = QosPolicyBuilder::new()
.reliability(policy::Reliability::Reliable { max_blocking_time: rustdds::Duration::ZERO })
.build();
// DDS Subscriber, only one is necessary for each thread (slight difference to
// DDS specification)
let subscriber = domain_participant.create_subscriber(&qos).unwrap();
// DDS Publisher, only one is necessary for each thread (slight difference to
// DDS specification)
let publisher = domain_participant.create_publisher(&qos).unwrap();
// Some DDS Topic that we can write and read from (basically only binds readers
// and writers together)
let some_topic = domain_participant.create_topic("some_topic".to_string(), "SomeType".to_string(), &qos, TopicKind::NoKey).unwrap();
// Used type needs Serialize for writers and Deserialize for readers
#[derive(Serialize, Deserialize, Debug)]
struct SomeType {
a: i32
}
// Creating DataReader requires type and deserializer adapter (which is recommended to be CDR).
// Reader needs to be mutable if any operations are used.
let mut reader = subscriber
.create_datareader_no_key::<SomeType, CDRDeserializerAdapter<SomeType>>(
&some_topic,
None)
.unwrap();
// Creating DataWriter required type and serializer adapter (which is recommended to be CDR).
let writer = publisher
.create_datawriter_no_key::<SomeType, CDRSerializerAdapter<SomeType>>(
&some_topic,
None)
.unwrap();
// Readers implement mio Evented trait and thus function the same way as
// std::sync::mpcs and can be handled the same way for reading the data
let some_data = SomeType { a: 1 };
// This should send the data to all who listen "some_topic" topic.
writer.write(some_data, None).unwrap();
// ... Some data has arrived at some point for the reader
let data_sample = if let Ok(Some(value)) = reader.take_next_sample() {
value
} else {
// no data has arrived
return;
};
// Getting reference to actual data from the data sample
let actual_data = data_sample.value();
Re-exports§
pub use serialization::RepresentationIdentifier;
Modules§
- dds
- DDS interface - Most commonly needed items should be re-exported directly to
crate top level and modules
no_key
andwith_key
. - no_key
- Components used to access NO_KEY Topics
- policy
- Contains all available QoSPolicies
- qos
- DDS Quality of Service policies
- ros2
Deprecated - ROS2 interface using DDS module - DO NOT USE - Use ros2-client instead.
- rpc
- serialization
- Helpers for (De)serialization and definitions of (De)serializer adapters
- with_
key - Components used to access WITH_KEY Topics
Structs§
- CDRDeserializer
Adapter - This type adapts CdrDeserializer (which implements serde::Deserializer) to
work as a
with_key::DeserializerAdapter
andno_key::DeserializerAdapter
. - CDRSerializer
Adapter - This type adapts
CdrSerializer
(which implementsserde::Serializer
) to work as ano_key::SerializerAdapter
andwith_key::SerializerAdapter
. - CdrDeserializer
- Deserializer type for converting CDR data stream to Rust objects.
- CdrSerializer
- a CDR serializer implementation
- Domain
Participant - DDS DomainParticipant
- Domain
Participant Builder - Duration
- Duration is the DDS/RTPS representation for lengths of time, such as
timeouts. It is very similar to
std::time::Duration
. See alsoTimestamp
. - Endpoint
Description - This is a summary of SubscriptionBuiltinTopicData / PublicationBuiltinTopicData from discovery. The original is not used to avoid circular dependency between participant and discovery.
- GUID
- DDS/RTPS GUID
- NotAlive
Generation Counts - A double counter for counting how many times an instance as become Alive.
- Participant
Description - This is a rewrite/summary of SpdpDiscoveredParticipantData from discovery.
- Publisher
- DDS Publisher
- QosPolicies
- Describes a set of RTPS/DDS QoS policies
- QosPolicy
Builder - Utility for building QosPolicies
- Read
Condition - This is used to specify which samples are to be read or taken from
a
Datareader
- Sample
Info - SampleInfo is metadata attached to each received data sample. It exists only at the receiving end of DDS, and is (mostly) generated by DDS.
- Sequence
Number - RTPS Specification v2.3 Section “8.3.5.4 SequenceNumber”
- Subscriber
- DDS Subscriber
- Timestamp
- Representation of time instants in DDS API and RTPS protocol. Similar to
std::time::Instant
. - Topic
- DDS Topic
- Type
Desc - Description of the type of a Topic
- Write
Options - Type to be used with write_with_options. Use WriteOptionsBuilder to construct this.
- Write
Options Builder
Enums§
- Data
Reader Status - Data
Writer Status - Domain
Participant Status Event - Instance
State - Is this data instance alive or not and why.
- Lost
Reason - Why some remote entity is considered to be no longer with us.
- Sample
State - indicates whether or not the corresponding data sample has already
been read by this
DataReader
. - Select
ByKey - Parameter for reading Readers data with key or with next from current key.
- Topic
Kind - Type for DDS Topic (With Key or No key)
- View
State - Indicates if this data instance has been seen (viewed).
Traits§
- CdrEncoding
Size - Helper trait to compute the CDR-serialized size of data Trait used to statically gauge the size of serialized instance keys.
- Key
- Trait for instance lookup key in a WITH_KEY topic.
- Keyed
- Data sample must implement
Keyed
to be used in a WITH_KEY topic. - RTPS
Entity - Trait for things that have a
GUID
. - Status
Evented - This trait corresponds to set_listener() of the Entity class in DDS spec. Types implementing this trait can be registered to a poll and polled for status events.
- Topic
Description - Trait approximation of DDS 2.2.2.3.1 TopicDescription Class
Derive Macros§
- CdrEncoding
Size - Helper trait to compute the CDR-serialized size of data Derive macro for implementing CdrEncodingSize trait.