r2r/src/qos.rs

531 lines
16 KiB
Rust

//! QoS (Quality of Service)
//! full credit goes to https://github.com/rclrust/rclrust/blob/main/rclrust/src/qos.rs
use std::time::Duration;
use r2r_rcl::{
rmw_qos_durability_policy_t, rmw_qos_history_policy_t, rmw_qos_liveliness_policy_t,
rmw_qos_reliability_policy_t, rmw_time_t,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HistoryPolicy {
KeepAll,
KeepLast,
SystemDefault,
Unknown,
}
impl From<HistoryPolicy> for rmw_qos_history_policy_t {
fn from(history_policy: HistoryPolicy) -> Self {
match history_policy {
HistoryPolicy::KeepAll => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_ALL,
HistoryPolicy::KeepLast => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_LAST,
HistoryPolicy::SystemDefault => {
rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT
}
HistoryPolicy::Unknown => rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_UNKNOWN,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ReliabilityPolicy {
BestEffort,
Reliable,
SystemDefault,
Unknown,
}
impl From<ReliabilityPolicy> for rmw_qos_reliability_policy_t {
fn from(reliability_policy: ReliabilityPolicy) -> Self {
match reliability_policy {
ReliabilityPolicy::BestEffort => {
rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT
}
ReliabilityPolicy::Reliable => {
rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_RELIABLE
}
ReliabilityPolicy::SystemDefault => {
rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT
}
ReliabilityPolicy::Unknown => {
rmw_qos_reliability_policy_t::RMW_QOS_POLICY_RELIABILITY_UNKNOWN
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DurabilityPolicy {
TransientLocal,
Volatile,
SystemDefault,
Unknown,
}
impl From<DurabilityPolicy> for rmw_qos_durability_policy_t {
fn from(durability_policy: DurabilityPolicy) -> Self {
match durability_policy {
DurabilityPolicy::TransientLocal => {
rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL
}
DurabilityPolicy::Volatile => {
rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_VOLATILE
}
DurabilityPolicy::SystemDefault => {
rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT
}
DurabilityPolicy::Unknown => {
rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_UNKNOWN
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LivelinessPolicy {
Automatic,
ManualByNode,
ManualByTopic,
SystemDefault,
Unknown,
}
impl From<LivelinessPolicy> for rmw_qos_liveliness_policy_t {
fn from(liveliness_policy: LivelinessPolicy) -> Self {
match liveliness_policy {
LivelinessPolicy::Automatic => {
rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_AUTOMATIC
}
LivelinessPolicy::ManualByNode => {
rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE
}
LivelinessPolicy::ManualByTopic => {
rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC
}
LivelinessPolicy::SystemDefault => {
rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT
}
LivelinessPolicy::Unknown => {
rmw_qos_liveliness_policy_t::RMW_QOS_POLICY_LIVELINESS_UNKNOWN
}
}
}
}
/// QoS profile
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QosProfile {
/// History QoS policy setting.
pub history: HistoryPolicy,
/// Size of the message queue.
pub depth: usize,
/// Reliabiilty QoS policy setting.
pub reliability: ReliabilityPolicy,
/// Durability QoS policy setting.
pub durability: DurabilityPolicy,
/// The period at which messages are expected to be sent/received.
pub deadline: Duration,
/// The age at which messages are considered expired and no longer valid.
pub lifespan: Duration,
/// Liveliness QoS policy setting.
pub liveliness: LivelinessPolicy,
/// The time within which the RMW node or publisher must show that it is alive.
pub liveliness_lease_duration: Duration,
/// If true, any ROS specific namespacing conventions will be circumvented.
///
/// In the case of DDS and topics, for example, this means the typical ROS specific prefix of rt
/// would not be applied as described here:
///
/// <http://design.ros2.org/articles/topic_and_service_names.html#ros-specific-namespace-prefix>
///
/// This might be useful when trying to directly connect a native DDS topic with a ROS 2 topic.
pub avoid_ros_namespace_conventions: bool,
}
impl QosProfile {
/// Sensor Data QoS class
/// - History: Keep last,
/// - Depth: 5,
/// - Reliability: Best effort,
/// - Durability: Volatile,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - avoid ros namespace conventions: false
pub const fn sensor_data() -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth: 5,
reliability: ReliabilityPolicy::BestEffort,
durability: DurabilityPolicy::Volatile,
..Self::common()
}
}
/// Parameters QoS class
/// - History: Keep last,
/// - Depth: 1000,
/// - Reliability: Reliable,
/// - Durability: Volatile,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn parameters() -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth: 1000,
reliability: ReliabilityPolicy::Reliable,
durability: DurabilityPolicy::Volatile,
..Self::common()
}
}
/// Default QoS class
/// - History: Keep last,
/// - Depth: 10,
/// - Reliability: Reliable,
/// - Durability: Volatile,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn default() -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth: 10,
reliability: ReliabilityPolicy::Reliable,
durability: DurabilityPolicy::Volatile,
..Self::common()
}
}
/// Services QoS class
/// - History: Keep last,
/// - Depth: 10,
/// - Reliability: Reliable,
/// - Durability: Volatile,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn services_default() -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth: 10,
reliability: ReliabilityPolicy::Reliable,
durability: DurabilityPolicy::Volatile,
..Self::common()
}
}
/// Parameter events QoS class
/// - History: Keep last,
/// - Depth: 1000,
/// - Reliability: Reliable,
/// - Durability: Volatile,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn parameter_events() -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth: 1000,
reliability: ReliabilityPolicy::Reliable,
durability: DurabilityPolicy::Volatile,
..Self::common()
}
}
/// System defaults QoS class
/// - History: System default,
/// - Depth: System default,
/// - Reliability: System default,
/// - Durability: System default,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: System default,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn system_default() -> Self {
Self::common()
}
/// Unknow QoS class
/// - History: Unknown,
/// - Depth: System default,
/// - Reliability: Unknown,
/// - Durability: Unknown,
/// - Deadline: Default,
/// - Lifespan: Default,
/// - Liveliness: Unknown,
/// - Liveliness lease duration: Default,
/// - Avoid ros namespace conventions: false
pub const fn unknown() -> Self {
Self {
history: HistoryPolicy::Unknown,
reliability: ReliabilityPolicy::Unknown,
durability: DurabilityPolicy::Unknown,
liveliness: LivelinessPolicy::Unknown,
..Self::common()
}
}
const fn common() -> Self {
Self {
history: HistoryPolicy::SystemDefault,
depth: r2r_rcl::RMW_QOS_POLICY_DEPTH_SYSTEM_DEFAULT as usize,
reliability: ReliabilityPolicy::SystemDefault,
durability: DurabilityPolicy::SystemDefault,
deadline: Duration::ZERO,
lifespan: Duration::ZERO,
liveliness: LivelinessPolicy::SystemDefault,
liveliness_lease_duration: Duration::ZERO,
avoid_ros_namespace_conventions: false,
}
}
/// Set the history policy.
///
/// # Examples
///
/// ```
/// # use r2r::qos::{HistoryPolicy, QosProfile};
/// #
/// let qos = QosProfile::default().history(HistoryPolicy::KeepAll);
/// ```
pub const fn history(self, history: HistoryPolicy) -> Self {
Self { history, ..self }
}
/// Set the history to keep last.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().keep_last(10);
/// ```
pub const fn keep_last(self, depth: usize) -> Self {
Self {
history: HistoryPolicy::KeepLast,
depth,
..self
}
}
/// Set the history to keep all.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().keep_all();
/// ```
pub const fn keep_all(self) -> Self {
Self {
history: HistoryPolicy::KeepAll,
depth: 0,
..self
}
}
/// Set the reliability setting.
///
/// # Examples
///
/// ```
/// # use r2r::qos::{QosProfile, ReliabilityPolicy};
/// #
/// let qos = QosProfile::default().reliability(ReliabilityPolicy::Reliable);
/// ```
pub const fn reliability(self, reliability: ReliabilityPolicy) -> Self {
Self {
reliability,
..self
}
}
/// Set the reliability setting to reliable.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().reliable();
/// ```
pub const fn reliable(self) -> Self {
self.reliability(ReliabilityPolicy::Reliable)
}
/// Set the reliability setting to best effort.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().best_effort();
/// ```
pub const fn best_effort(self) -> Self {
self.reliability(ReliabilityPolicy::BestEffort)
}
/// Set the durability setting.
///
/// # Examples
///
/// ```
/// # use r2r::qos::{DurabilityPolicy, QosProfile};
/// #
/// let qos = QosProfile::default().durability(DurabilityPolicy::Volatile);
/// ```
pub const fn durability(self, durability: DurabilityPolicy) -> Self {
Self { durability, ..self }
}
/// Set the durability setting to volatile.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().volatile();
/// ```
pub const fn volatile(self) -> Self {
self.durability(DurabilityPolicy::Volatile)
}
/// Set the durability setting to transient local.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().transient_local();
/// ```
pub const fn transient_local(self) -> Self {
self.durability(DurabilityPolicy::TransientLocal)
}
/// Set the deadline setting.
///
/// # Examples
///
/// ```
/// # use std::time::Duration;
/// #
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().deadline(Duration::from_secs(5));
/// ```
pub const fn deadline(self, deadline: Duration) -> Self {
Self { deadline, ..self }
}
/// Set the lifespan setting.
///
/// # Examples
///
/// ```
/// # use std::time::Duration;
/// #
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().lifespan(Duration::from_secs(5));
/// ```
pub const fn lifespan(self, lifespan: Duration) -> Self {
Self { lifespan, ..self }
}
/// Set the liveliness setting.
///
/// # Examples
///
/// ```
/// # use r2r::qos::{LivelinessPolicy, QosProfile};
/// #
/// let qos = QosProfile::default().liveliness(LivelinessPolicy::Automatic);
/// ```
pub const fn liveliness(self, liveliness: LivelinessPolicy) -> Self {
Self { liveliness, ..self }
}
/// Set the liveliness_lease_duration setting.
///
/// # Examples
///
/// ```
/// # use std::time::Duration;
/// #
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().liveliness_lease_duration(Duration::from_secs(5));
/// ```
pub const fn liveliness_lease_duration(self, liveliness_lease_duration: Duration) -> Self {
Self {
liveliness_lease_duration,
..self
}
}
/// Set the avoid_ros_namespace_conventions setting.
///
/// # Examples
///
/// ```
/// # use r2r::qos::QosProfile;
/// #
/// let qos = QosProfile::default().avoid_ros_namespace_conventions(true);
/// ```
pub const fn avoid_ros_namespace_conventions(
self,
avoid_ros_namespace_conventions: bool,
) -> Self {
Self {
avoid_ros_namespace_conventions,
..self
}
}
}
impl From<QosProfile> for r2r_rcl::rmw_qos_profile_t {
fn from(qos: QosProfile) -> Self {
Self {
history: qos.history.into(),
depth: qos.depth,
reliability: qos.reliability.into(),
durability: qos.durability.into(),
deadline: qos.deadline.to_rmw_time_t(),
lifespan: qos.lifespan.to_rmw_time_t(),
liveliness: qos.liveliness.into(),
liveliness_lease_duration: qos.liveliness_lease_duration.to_rmw_time_t(),
avoid_ros_namespace_conventions: qos.avoid_ros_namespace_conventions,
}
}
}
pub(crate) trait RclDurationT {
fn to_rmw_time_t(&self) -> rmw_time_t;
}
impl RclDurationT for Duration {
fn to_rmw_time_t(&self) -> rmw_time_t {
rmw_time_t {
sec: self.as_secs(),
nsec: self.subsec_nanos().into(),
}
}
}