Skip to main content

Reliability QoS Policy

The Reliability policy controls whether data delivery is guaranteed or best-effort.

Values

ValueDescriptionUse Case
best_effort()Fire and forget, no retransmissionSensor data, video streaming
reliable()Guaranteed delivery with ACK/NACKCommands, state synchronization

Best Effort

Samples are sent once without acknowledgment. If a sample is lost due to network issues, it is not retransmitted.

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("sensor_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let writer = participant
.topic::<SensorData>("sensors/temperature")?
.writer()
.qos(QoS::best_effort())
.build()?;

Characteristics:

  • Lowest latency (no ACK overhead)
  • No blocking on write
  • Samples may be lost
  • No memory accumulation for retransmission

Reliable

Samples are acknowledged by readers. Lost samples trigger NACK-based retransmission.

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("command_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let writer = participant
.topic::<Command>("robot/commands")?
.writer()
.qos(QoS::reliable().keep_last(100))
.build()?;

Characteristics:

  • Guaranteed delivery (if reader is reachable)
  • Higher latency due to ACK/NACK protocol
  • Writer may block if reader is slow
  • Memory used for retransmission buffer

Protocol Details

RTPS Reliable Protocol

Heartbeat Mechanism

Writers periodically send HEARTBEAT messages announcing available sequence numbers. Readers respond with ACKNACK indicating which samples they need.

ParameterDefaultDescription
Heartbeat period100 msTime between heartbeats
NACK response delay10 msDelay before sending NACK
Max retransmissionsUnlimitedRetries until timeout

Compatibility Rules

Writers and readers must have compatible reliability settings:

WriterReaderMatch?
RELIABLERELIABLE✅ Yes
RELIABLEBEST_EFFORT✅ Yes
BEST_EFFORTBEST_EFFORT✅ Yes
BEST_EFFORTRELIABLENo Match
Incompatibility

A BEST_EFFORT writer cannot satisfy a RELIABLE reader. The reader expects acknowledgments that the writer won't send.

Performance Considerations

Best Effort

use hdds::{Participant, QoS, TransportMode};

// High-frequency sensor data (1000+ Hz)
let writer = participant
.topic::<SensorData>("sensors/imu")?
.writer()
.qos(QoS::best_effort().keep_last(1))
.build()?;
  • Latency: ~100 μs
  • Throughput: Up to 4M msg/s
  • Memory: Minimal (no retransmission buffer)

Reliable

use hdds::{Participant, QoS, TransportMode};

// Critical commands requiring guaranteed delivery
let writer = participant
.topic::<Command>("robot/commands")?
.writer()
.qos(QoS::reliable().keep_last(100))
.build()?;
  • Latency: ~500 μs - 10 ms (depends on network)
  • Throughput: Up to 100K msg/s
  • Memory: History depth × sample size

Blocking Behavior

With reliable(), the write() call may block:

use hdds::Error;

// Non-blocking write with timeout
match writer.write(&sample) {
Ok(()) => println!("Sample sent"),
Err(Error::Timeout) => println!("Buffer full, sample dropped"),
Err(e) => return Err(e),
}

To avoid blocking:

  1. Use larger history depth to buffer samples
  2. Ensure readers keep up with writer rate

Examples

Telemetry (Best Effort)

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("telemetry")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// High-rate sensor data where occasional loss is acceptable
let writer = participant
.topic::<SensorData>("sensors/temperature")?
.writer()
.qos(QoS::best_effort().keep_last(1))
.build()?;

let reader = participant
.topic::<SensorData>("sensors/temperature")?
.reader()
.qos(QoS::best_effort())
.build()?;

Commands (Reliable)

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("robot_controller")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Robot commands that must not be lost
let writer = participant
.topic::<Command>("robot/commands")?
.writer()
.qos(QoS::reliable().keep_all())
.build()?;

let reader = participant
.topic::<Command>("robot/commands")?
.reader()
.qos(QoS::reliable())
.build()?;

Mixed System

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("mixed_system")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

// Writer offers reliable (stronger guarantee)
let writer = participant
.topic::<StateUpdate>("system/state")?
.writer()
.qos(QoS::reliable().keep_last(10))
.build()?;

// Reader A accepts best-effort (compatible)
let reader_a = participant
.topic::<StateUpdate>("system/state")?
.reader()
.qos(QoS::best_effort())
.build()?;

// Reader B requires reliable (compatible)
let reader_b = participant
.topic::<StateUpdate>("system/state")?
.reader()
.qos(QoS::reliable())
.build()?;

Next Steps