DDS Overview

The Data Distribution Service (DDS) is a middleware protocol and API standard for data-centric connectivity from the Object Management Group (OMG). It provides a publish-subscribe pattern for real-time, scalable, and high-performance data exchange.

What is DDS?

DDS enables applications to communicate by publishing and subscribing to data samples identified by topics. It provides:

  • Decoupling: Publishers and subscribers don't need to know about each other
  • QoS Control: Fine-grained control over reliability, durability, latency, and resource usage
  • Discovery: Automatic discovery of participants, topics, and endpoints
  • Type Safety: Strongly-typed data model with type propagation
  • Scalability: From small embedded systems to large distributed systems

DDS Architecture

graph TB
    subgraph "Domain Participant"
        P1[Publisher]
        S1[Subscriber]
        T1[Topic: Temperature]
        T2[Topic: Pressure]

        P1 --> DW1["DataWriter
        Temperature"]
        P1 --> DW2["DataWriter
        Pressure"]
        S1 --> DR1["DataReader
        Temperature"]
        S1 --> DR2["DataReader
        Pressure"]

        DW1 -.publishes.-> T1
        DR1 -.subscribes.-> T1
        DW2 -.publishes.-> T2
        DR2 -.subscribes.-> T2
    end

Key Components

Domain Participant

The entry point for DDS applications. Represents a participant in a DDS domain (isolated communication space).

auto participant = astutedds::dcps::DomainParticipantFactory::create_participant(
    domain_id,
    PARTICIPANT_QOS_DEFAULT
);

Topic

Named data channel typed by a specific data structure. Topics are the foundation of DDS communication.

auto topic = participant->create_topic<SensorData>(
    "SensorTopic",
    TOPIC_QOS_DEFAULT
);

Publisher and DataWriter

Publishers create DataWriters that publish samples on topics.

auto publisher = participant->create_publisher();
auto writer = publisher->create_datawriter(topic, DATAWRITER_QOS_DEFAULT);

SensorData data;
data.temperature = 25.5;
writer->write(data);

Subscriber and DataReader

Subscribers create DataReaders that receive samples from topics.

auto subscriber = participant->create_subscriber();
auto reader = subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);

std::vector<SensorData> samples;
reader->take(samples);

Communication Flow

Simple Publish-Subscribe

sequenceDiagram
    participant Publisher
    participant DDS
    participant Subscriber

    Publisher->>DDS: Create DataWriter
    Subscriber->>DDS: Create DataReader

    Note over DDS: Discovery Protocol
    Note over DDS: (SPDP/SEDP)

    DDS-->>Publisher: Reader discovered
    DDS-->>Subscriber: Writer discovered

    Publisher->>DDS: write(sample)
    DDS->>Subscriber: DATA submessage
    Subscriber-->>DDS: ACKNACK (if RELIABLE)

    Note over Subscriber: Process sample

Discovery Process

DDS uses automatic discovery to match publishers and subscribers:

sequenceDiagram
    participant App1 as Application 1
    participant App2 as Application 2

    Note over App1,App2: SPDP: Simple Participant Discovery Protocol

    App1->>App2: SPDP: Participant announcement
    App2->>App1: SPDP: Participant announcement

    Note over App1,App2: SEDP: Simple Endpoint Discovery Protocol

    App1->>App2: SEDP: DataWriter metadata
    App2->>App1: SEDP: DataReader metadata

    Note over App1,App2: Endpoints matched!
    Note over App1,App2: Ready for data exchange

Reliable Data Exchange

When using RELIABLE reliability QoS:

sequenceDiagram
    participant Writer
    participant Reader

    Writer->>Reader: DATA (seq=1)
    Writer->>Reader: DATA (seq=2)
    Note over Reader: seq=2 lost
    Writer->>Reader: HEARTBEAT (seq=1-3)
    Reader->>Writer: ACKNACK (missing: 2)
    Writer->>Reader: DATA (seq=2) [repair]
    Reader->>Writer: ACKNACK (all received)

    Note over Writer,Reader: All data delivered

Best-Effort Data Exchange

When using BEST_EFFORT reliability QoS:

sequenceDiagram
    participant Writer
    participant Reader

    Writer->>Reader: DATA (seq=1)
    Writer->>Reader: DATA (seq=2)
    Note over Reader: seq=2 lost
    Writer->>Reader: DATA (seq=3)

    Note over Reader: Process seq=1, 3
    Note over Reader: Skip seq=2 (no repair)

Quality of Service (QoS)

QoS policies control the behavior of DDS entities. Key policies include:

Reliability

  • BEST_EFFORT: Fast, no retransmission (good for real-time sensor data)
  • RELIABLE: Guaranteed delivery with retransmission (good for commands)

Durability

  • VOLATILE: No historical data (only live data)
  • TRANSIENT_LOCAL: Late joiners get historical data
  • TRANSIENT: Historical data survives process restart
  • PERSISTENT: Historical data persists in database

History

  • KEEP_LAST(n): Keep only last n samples
  • KEEP_ALL: Keep all samples (subject to resource limits)

Example QoS Configuration

auto qos = astutedds::dcps::DataWriterQosBuilder()
    .reliability(astutedds::dcps::ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS)
    .durability(astutedds::dcps::DurabilityQosPolicyKind::TRANSIENT_LOCAL_DURABILITY_QOS)
    .history(astutedds::dcps::HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS, 10)
    .build();

auto writer = publisher->create_datawriter(topic, qos);

RTPS Wire Protocol

DDS uses the RTPS (Real-Time Publish-Subscribe) protocol for network communication:

graph LR
    A[Application] --> B[DDS API]
    B --> C[RTPS Protocol]
    C --> D[UDP/IP Transport]
    D --> E[Network]

RTPS provides:

  • Discovery: Automatic participant and endpoint discovery
  • Reliability: HEARTBEAT/ACKNACK protocol for guaranteed delivery
  • Efficiency: Compact binary encoding (CDR/XCDR)
  • Interoperability: Standard wire format for cross-vendor communication

Type System (X-Types)

AstuteDDS supports DDS X-Types 1.3 for dynamic type handling:

graph TB
    IDL[IDL Definition] --> Compiler[IDL Compiler]
    Compiler --> TypeObject[TypeObject]
    Compiler --> CppCode[C++ Code]

    TypeObject --> TypeRegistry[Type Registry]
    CppCode --> App[Application]

    TypeRegistry --> DynamicData[Dynamic Data]
    App --> DynamicData

    TypeRegistry -.type discovery.-> RemoteApp[Remote Application]

Features:

  • TypeObject: Runtime type representation
  • Type Discovery: Automatic type propagation
  • Assignability: Type compatibility checking
  • Dynamic Data: Runtime data manipulation without code generation

Data Representation

DDS uses CDR (Common Data Representation) for serialization:

  • XCDR1: Traditional CDR with alignment rules
  • XCDR2: Enhanced CDR with delimiters and optional members
graph LR
    A[Struct Data] --> B{Encoding}
    B -->|XCDR1| C[Aligned Binary]
    B -->|XCDR2| D[Delimited Binary]

    C --> E[Network Transmission]
    D --> E

    E --> F{Decoding}
    F --> G[Struct Data]

Use Cases

DDS is used in:

  • Military & Defense: Command and control, sensor fusion
  • Aerospace: Flight control, avionics
  • Industrial IoT: Factory automation, SCADA
  • Automotive: ADAS, autonomous vehicles
  • Medical: Real-time patient monitoring
  • Financial: High-frequency trading

Next Steps