CycloneDDS Setup
Configure CycloneDDS to communicate with HDDS participants.
Installation
Ubuntu/Debian
sudo apt install cyclonedds-dev cyclonedds-tools
From Source
git clone https://github.com/eclipse-cyclonedds/cyclonedds.git
cd cyclonedds
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j$(nproc)
sudo make install
ROS2 (Already Installed)
# CycloneDDS is bundled with ROS2
source /opt/ros/$ROS_DISTRO/setup.bash
Basic Configuration
Minimal Interop Configuration
Create cyclonedds.xml:
<?xml version="1.0" encoding="UTF-8"?>
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<AllowMulticast>true</AllowMulticast>
</General>
</Domain>
</CycloneDDS>
Apply configuration:
export CYCLONEDDS_URI=file:///path/to/cyclonedds.xml
Network Interface Selection
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<NetworkInterfaceAddress>eth0</NetworkInterfaceAddress>
<!-- Or by IP -->
<!-- <NetworkInterfaceAddress>192.168.1.100</NetworkInterfaceAddress> -->
</General>
</Domain>
</CycloneDDS>
Discovery Configuration
Multicast Discovery (Default)
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<AllowMulticast>spdp</AllowMulticast>
</General>
</Domain>
</CycloneDDS>
Unicast Discovery (No Multicast)
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<AllowMulticast>false</AllowMulticast>
</General>
<Discovery>
<Peers>
<Peer address="192.168.1.100"/> <!-- HDDS participant -->
<Peer address="192.168.1.101"/>
</Peers>
</Discovery>
</Domain>
</CycloneDDS>
Domain ID
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="42">
<!-- Configuration for domain 42 -->
</Domain>
</CycloneDDS>
Or via environment:
export ROS_DOMAIN_ID=42
Transport Configuration
Socket Buffers
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<Internal>
<SocketReceiveBufferSize min="4MB"/>
<SocketSendBufferSize min="4MB"/>
</Internal>
</Domain>
</CycloneDDS>
Shared Memory (Iceoryx)
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<SharedMemory>
<Enable>true</Enable>
<SubId>0</SubId>
<LogLevel>warning</LogLevel>
</SharedMemory>
</Domain>
</CycloneDDS>
Note: CycloneDDS shared memory uses Iceoryx and is not directly compatible with HDDS built-in shared memory. For same-host interop, use UDP loopback.
Debugging
Enable Tracing
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<Tracing>
<Verbosity>finest</Verbosity>
<OutputFile>cyclone.log</OutputFile>
<Category>discovery</Category>
</Tracing>
</Domain>
</CycloneDDS>
Check Discovery
# List discovered participants
ddsperf -D0 ping
# Monitor topic traffic
ddsperf sub MySensorTopic
Type Definition
CycloneDDS and HDDS must use identical type definitions.
IDL File
// sensor_data.idl
module sensors {
struct SensorData {
unsigned long sensor_id; // @key
float value;
unsigned long long timestamp;
};
};
Generate CycloneDDS Types
idlc -l c sensor_data.idl
# Generates: sensor_data.c, sensor_data.h
Generate HDDS Types
hdds-gen -l rust sensor_data.idl
# Generates: sensor_data.rs
Verification
Test Connectivity
CycloneDDS Publisher:
#include <dds/dds.h>
#include "sensor_data.h"
int main() {
dds_entity_t participant = dds_create_participant(0, NULL, NULL);
dds_entity_t topic = dds_create_topic(
participant, &sensors_SensorData_desc, "SensorTopic", NULL, NULL);
dds_entity_t writer = dds_create_writer(participant, topic, NULL, NULL);
sensors_SensorData sample = { .sensor_id = 1, .value = 25.5, .timestamp = 0 };
dds_write(writer, &sample);
dds_delete(participant);
return 0;
}
HDDS Subscriber:
use hdds::*;
fn main() -> Result<(), HddsError> {
let participant = DomainParticipant::new(0)?;
let topic = participant.create_topic::<SensorData>("SensorTopic")?;
let subscriber = participant.create_subscriber()?;
let reader = subscriber.create_datareader(&topic)?;
loop {
if let Ok(samples) = reader.take() {
for (sample, _) in samples {
println!("Received from CycloneDDS: {:?}", sample);
}
}
}
}
Common Issues
| Issue | Solution |
|---|---|
| No discovery | Check domain ID matches, check network interface |
| Type mismatch | Use same IDL, regenerate types |
| No data | Check QoS compatibility |
Full Example Configuration
<?xml version="1.0" encoding="UTF-8"?>
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="0">
<General>
<NetworkInterfaceAddress>auto</NetworkInterfaceAddress>
<AllowMulticast>spdp</AllowMulticast>
<MaxMessageSize>65500B</MaxMessageSize>
</General>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>100</MaxAutoParticipantIndex>
</Discovery>
<Internal>
<SocketReceiveBufferSize min="4MB"/>
<SocketSendBufferSize min="4MB"/>
</Internal>
<Tracing>
<Verbosity>warning</Verbosity>
</Tracing>
</Domain>
</CycloneDDS>
Next Steps
- QoS Mapping - QoS configuration
- Example - Complete interop example
- Wire Compatibility - Protocol details