Skip to main content

FastDDS Interoperability

HDDS is certified compatible with eProsima FastDDS 2.x.

Requirements

  • FastDDS 2.10+ (recommended 2.14+)
  • Same domain ID on both ends
  • Compatible QoS policies

Quick Test

HDDS Publisher

use hdds::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let participant = DomainParticipant::new(0)?;
let topic = participant.create_topic::<HelloWorld>("HelloWorldTopic")?;
let publisher = participant.create_publisher()?;
let writer = publisher.create_writer(&topic)?;

loop {
writer.write(&HelloWorld {
message: "Hello from HDDS!".to_string(),
})?;
std::thread::sleep(std::time::Duration::from_secs(1));
}
}

FastDDS Subscriber (C++)

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>

int main() {
auto factory = DomainParticipantFactory::get_instance();
auto participant = factory->create_participant(0, PARTICIPANT_QOS_DEFAULT);

// Register type
TypeSupport type(new HelloWorldPubSubType());
type.register_type(participant);

auto topic = participant->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
auto subscriber = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
auto reader = subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);

// Read loop
HelloWorld sample;
SampleInfo info;
while (true) {
if (reader->take_next_sample(&sample, &info) == ReturnCode_t::RETCODE_OK) {
std::cout << "Received: " << sample.message() << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

IDL Type Definition

Both sides must use matching types:

// HelloWorld.idl
struct HelloWorld {
string message;
};

Generate for FastDDS:

fastddsgen HelloWorld.idl

Generate for HDDS:

hdds-gen gen --target rust HelloWorld.idl

QoS Compatibility

Verified Profiles

ProfileReliabilityDurabilityHistoryStatus
Sensor StreamingBestEffortVolatileKeepLast(1)
State SyncReliableTransientLocalKeepLast(10)
Event LogReliableTransientLocalKeepAll

FastDDS QoS (XML)

<?xml version="1.0" encoding="UTF-8"?>
<dds>
<profiles>
<data_writer_qos profile_name="hdds_interop">
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<durability>
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
</durability>
<history>
<kind>KEEP_LAST_HISTORY_QOS</kind>
<depth>10</depth>
</history>
</data_writer_qos>
</profiles>
</dds>

HDDS QoS (Rust)

let qos = DataWriterQos::default()
.reliability(Reliability::Reliable {
max_blocking_time: Duration::from_secs(1),
})
.durability(Durability::TransientLocal)
.history(History::KeepLast { depth: 10 });

Encapsulation Format

FastDDS uses PL_CDR_LE (0x0003) for discovery and DL_CDR2_LE for user data:

PhaseFastDDS FormatHDDS Support
SPDPPL_CDR_LE
SEDPPL_CDR_LE
User DataDL_CDR2_LE / CDR_LE

Network Configuration

Multicast (Default)

No configuration needed. Both use standard RTPS multicast:

Multicast: 239.255.0.1:7400 (domain 0)

Unicast Only

If multicast is disabled:

HDDS:

export HDDS_SPDP_UNICAST_PEERS="192.168.1.100:7400"

FastDDS (XML):

<participant profile_name="unicast_participant">
<rtps>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>192.168.1.100</address>
<port>7400</port>
</udpv4>
</locator>
</initialPeersList>
</builtin>
</rtps>
</participant>

Troubleshooting

Discovery Fails

  1. Check domain ID: Must match on both sides
  2. Check firewall: UDP ports 7400-7500 open
  3. Check multicast: ping 239.255.0.1

Type Mismatch

Ensure IDL matches exactly:

  • Same field names
  • Same field types
  • Same field order

QoS Incompatible

Most common issues:

  • HDDS BestEffort writer → FastDDS Reliable reader (fails)
  • HDDS Volatile → FastDDS TransientLocal reader (fails)

Performance Notes

MetricValue
Discovery time< 2 seconds
Message latency< 1 ms (same host)
Throughput100K+ msg/s

Next Steps