Skip to main content

QoSProfile

Struct QoSProfile 

Source
pub struct QoSProfile {
    pub history: QoSHistoryPolicy,
    pub reliability: QoSReliabilityPolicy,
    pub durability: QoSDurabilityPolicy,
    pub liveliness_kind: QoSLivelinessPolicy,
    pub depth: u32,
    pub deadline_ms: u32,
    pub lifespan_ms: u32,
    pub liveliness_lease_ms: u32,
    pub avoid_ros_namespace_conventions: bool,
    pub tx_express: bool,
}
Expand description

Full DDS-shaped QoS profile. Matches the field set of upstream rmw_qos_profile_t.

Backends advertise per-policy support via Session::supported_qos_policies; entities created with a profile the active backend can’t honour return TransportError::IncompatibleQos synchronously at create time — no silent downgrade.

Zero-valued time-window fields (“off”) mean infinite — the policy is effectively disabled for the entity.

Fields§

§history: QoSHistoryPolicy

History policy

§reliability: QoSReliabilityPolicy

Reliability policy

§durability: QoSDurabilityPolicy

Durability policy

§liveliness_kind: QoSLivelinessPolicy

Liveliness policy

§depth: u32

History depth (only used if history is KeepLast)

§deadline_ms: u32

Subscription max-inter-arrival / publisher offered-rate, ms. 0 = infinite (no deadline check).

§lifespan_ms: u32

Sample expiry, ms. Subscribers filter samples older than this. 0 = infinite (no expiry).

§liveliness_lease_ms: u32

Liveliness lease, ms. 0 = infinite.

§avoid_ros_namespace_conventions: bool

If true, topic-name encoding skips the /rt/ ROS prefix.

§tx_express: bool

Phase 282 (#145) — publisher-side “express” hint: this publisher’s samples bypass transport tx batching (zenoh: the wire EXPRESS flag; a batching zenoh-pico session sends them immediately instead of queueing them for the next flush). A transport hint, not a DDS policy — no RxO matching, no backend-compat validation; ignored by subscriptions and by backends without a batching concept.

Implementations§

Source§

impl QoSProfile

Source

pub fn apply_overrides( self, topic: &str, role: QoSOverrideRole, overrides: &[QoSOverride], ) -> Self

Phase 211.H — fold the plan’s qos_overrides matching topic + role into this profile, returning the overridden profile. Setup-time only (called from create_publisher/create_subscription): a single linear scan over the baked &'static table, no alloc, RT-safe. Later entries win on a duplicate (topic, role, policy) (last-write), matching the planner’s sorted, de-conflicted emit. Non-matching entries are ignored, so passing the whole node table to every entity is cheap + correct.

Source

pub fn apply_override_value(&mut self, value: QoSOverrideValue)

Issue 0303 — apply ONE decoded override value. The single place a policy maps to the field it sets; apply_overrides and the FFI folds both go through it, so a new policy cannot reach some paths only.

Source

pub fn apply_override_codes( self, topic: &str, role: QoSOverrideRole, codes: &[QoSOverrideCode], ) -> Self

Issue 0303 — fold baked QoSOverrideCodes for one (topic, role). Unrecognised codes are skipped; the producers reject them at BAKE time (nros_orchestration_ir::qos_override), so a code reaching here that this build does not know is an older image running newer data, not a user error to diagnose at runtime.

Source§

impl QoSProfile

Source

pub const BEST_EFFORT: Self

Best-effort QoS (for real-time).

Provenance: nros: best-effort keep-last(1); a shorthand, not an upstream constant.

Source

pub const RELIABLE: Self

Reliable QoS.

Provenance: nros: reliable keep-last(10); a shorthand, not an upstream constant.

Source

pub const QOS_PROFILE_SYSTEM_DEFAULT: Self

rmw_qos_profile_system_default — an absence, not a profile.

issue 0829. Every field is the sentinel: upstream’s constant names no concrete policy at all, and the two reference RMWs fill the absence with different numbers — rmw_cyclonedds_cpp’s create_readwrite_qos folds RMW_QOS_POLICY_DEPTH_SYSTEM_DEFAULT to KEEP_LAST(1), while rmw_zenoh_cpp’s QoS::QoS() fills it from RMW_ZENOH_DEFAULT_HISTORY_DEPTH, which is 42, over a comment stating the contract outright: “If the depth field in the qos profile is set to 0, the RMW implementation has the liberty to assign a default depth.”

So no baked number can be right. This carried a concrete Reliable / Volatile / KeepLast(1) until 2026-09-03, and nros::qos::SYSTEM_DEFAULT carried a concrete depth 10, which is how one name shipped two queue depths. Both are gone; the backend resolves this at its create entry via QoSProfile::resolve_system_default.

liveliness_kind is QoSLivelinessPolicy::None, which IS the sentinel on that policy — it lowers to NROS_RMW_LIVELINESS_SYSTEM_DEFAULT (0), the two having collapsed onto one value in phase-376 W5/B2. This is therefore the ONE preset that matches upstream on all nine fields.

Provenance: rmw_qos_profile_system_default.

Source

pub const QOS_PROFILE_UNKNOWN: Self

rmw_qos_profile_unknown — “the backend could not determine this”, and distinct from QOS_PROFILE_SYSTEM_DEFAULT.

SYSTEM_DEFAULT means “nobody asked, so the middleware chooses”; this means “we looked and cannot say”, which is what a *_get_actual_qos read-back owes its caller for a policy it cannot report. It is the starting value the read-back helper pre-loads, so a field the backend does not overwrite reads as an ABSENCE rather than as a confident grant of whatever was asked.

Never a request. No create_* accepts it — a backend’s qos_admit refuses UNKNOWN on every policy, because an application asking for “I cannot say” is a bug, not a preference.

The C ABI twin is NROS_RMW_QOS_PROFILE_UNKNOWN (rmw_entity.h), which existed from phase-428 W10 with no Rust counterpart: three of the four policy enums had no Unknown variant to build it from. They do now.

Provenance: rmw_qos_profile_unknown.

Source

pub const QOS_PROFILE_DEFAULT: Self

Default QoS profile — reliable, volatile, keep-last(10).

Provenance: rmw_qos_profile_default.

Source

pub const QOS_PROFILE_SENSOR_DATA: Self

Sensor data QoS profile — best-effort, volatile, keep-last(5).

Provenance: rmw_qos_profile_sensor_data.

Source

pub const QOS_PROFILE_SERVICES_DEFAULT: Self

Services default QoS profile — reliable, volatile, keep-last(10).

Provenance: rmw_qos_profile_services_default.

Source

pub const QOS_PROFILE_PARAMETERS: Self

Parameters QoS profile — KEEP_LAST(1000), RELIABLE, VOLATILE.

issue 0793 — this said TransientLocal until 2026-08-25, disagreeing both with upstream (/opt/ros/<distro>/include/rmw/rmw/qos_profiles.h) and with our own second copy of the same profile, nros::qos::PARAMETERS, which was already correct. Two copies of one profile that disagree is the defect; the wrong one being the one named after the upstream constant is what made it hard to see.

Provenance: rmw_qos_profile_parameters.

Source

pub const QOS_PROFILE_PARAMETER_EVENTS: Self

Parameter events QoS profile — KEEP_LAST(1000), RELIABLE, VOLATILE.

phase-428 W10 — this was KeepAll, depth 0 until 2026-09-05, under a comment claiming it matched rmw_qos_profile_parameter_events. Upstream is KEEP_LAST, 1000 (identical to rmw_qos_profile_parameters), and rclcpp::ParameterEventsQoS — which our own C++ surface mirrors — was already correct, so the two languages shipped different profiles under one name.

The difference INVERTS behaviour rather than weakening it: both DDS backends map KEEP_ALL faithfully, and a RELIABLE writer with KEEP_ALL blocks once history fills, where KEEP_LAST(1000) overwrites. A parameter server whose events nobody is reading would stall the node instead of dropping the oldest event.

Provenance: rmw_qos_profile_parameter_events.

Source

pub const QOS_PROFILE_ACTION_STATUS_DEFAULT: Self

Action status default QoS profile — reliable, transient-local, keep-last(1). From rcl_action, not rmw.

Provenance: rcl_action_qos_profile_status_default.

Source

pub const QOS_PROFILE_CLOCK: Self

Clock QoS profile — sensor-data shaped with depth 1.

Provenance: nros: mirrors rclrs::QOS_PROFILE_CLOCK; no rmw constant exists, so the gate cannot bind it — phase-428 W4.

Source

pub const QOS_PROFILE_PX4: Self

PX4 companion QoS profile (Phase 233 / RFC-0039 Track B). Matches the QoS PX4’s uxrce_dds_client uses on /fmu/out/* and /fmu/in/* — BEST_EFFORT + VOLATILE + KEEP_LAST(1). A nano-ros node talking to the same MicroXRCEAgent must use this (a reliable or TRANSIENT_LOCAL reader will not match PX4’s volatile best-effort writers). Verified against real PX4 SITL (nros-px4-sitl-test): TRANSIENT_LOCAL durability silently fails to match /fmu/out/*. Adjust depth via .keep_last(n) for higher-rate streams.

Provenance: nros: PX4 uxrce_dds_client companion QoS; no upstream constant.

Source§

impl QoSProfile

Source

pub const fn new() -> Self

Create new QoS settings with defaults (matches QOS_PROFILE_DEFAULT: Reliable, Volatile, KeepLast(10)).

Source

pub const fn topics_default() -> Self

Get the default QoS profile for ordinary topics

Source

pub const fn px4() -> Self

The PX4 companion QoS profile (QOS_PROFILE_PX4) — use for /fmu/out/* subscriptions and /fmu/in/* publications against a MicroXRCEAgent.

Source

pub const fn sensor_data_default() -> Self

Get the default QoS profile for sensor data topics

Source

pub const fn services_default() -> Self

Get the default QoS profile for services

Source

pub const fn parameter_services_default() -> Self

The parameter services’ profile — rclrs’s QoSProfile::parameter_services_default().

rmw_qos_profile_parameters: KEEP_LAST(1000), RELIABLE, VOLATILE. The depth is the point — 1000 against the generic services profile’s 10 — and it is what a tool setting many parameters at once depends on.

RENAMED in phase-417 G6, and the old spelling is GONE. It was parameters_default, an ours-only word for a name rclrs has; the ledger carried the pair as rust:QoSProfile::parameters_default (rename — ours is the one that should change) and rust:QoSProfile::parameter_services_default (gap). Adding the upstream name beside ours would have been a FOURTH spelling of one preset (QOS_PROFILE_PARAMETERS and QosPresets::PARAMETERS are the other two) and would have left the rename row open for good. No deprecated forwarder: a stale call should fail on the IDENTIFIER rather than on a deprecation, which is stage 6 step B’s rule and what the sibling parameter_events_default — already at rclrs’s spelling — makes the pair consistent with.

Source

pub const fn parameter_events_default() -> Self

Get the default QoS profile for parameter events

Source

pub const fn system_default() -> Self

Get the system default QoS profile

Source

pub const fn action_status_default() -> Self

Get the default QoS profile for action status topics

Source

pub const fn clock_default() -> Self

Get the default QoS profile for clock topics

Source

pub const fn keep_last(self, depth: u32) -> Self

Set history to keep last N messages

Source

pub const fn keep_all(self) -> Self

Set history to keep all messages

Source

pub const fn reliable(self) -> Self

Set reliability to reliable

Source

pub const fn best_effort(self) -> Self

Set reliability to best-effort

Source

pub const fn volatile(self) -> Self

Set durability to volatile

Source

pub const fn transient_local(self) -> Self

Set durability to transient local

Source

pub const fn reliability(self, policy: QoSReliabilityPolicy) -> Self

Set reliability policy explicitly

Source

pub const fn durability(self, policy: QoSDurabilityPolicy) -> Self

Set durability policy explicitly

Source

pub const fn history(self, policy: QoSHistoryPolicy) -> Self

Set history policy explicitly

Source

pub const fn depth(self, depth: u32) -> Self

Set history depth explicitly

Source

pub const fn tx_express(self, express: bool) -> Self

Phase 282 (#145) — mark this publisher’s samples “express”: they bypass transport tx batching (sent immediately even when the batching knob is on). A transport hint for control-tier / latency-sensitive topics; ignored on subscriptions and by backends without batching.

Source

pub const fn history_depth(&self) -> u8

Get history depth (for backwards compatibility)

Source§

impl QoSProfile

Source

pub const fn has_unknown(&self) -> bool

Does any policy in this profile carry its Unknown sentinel?

True only for a profile that came out of a *_get_actual_qos read-back on a backend that could not report every policy — never for one an application built. validate_against refuses such a profile at create time, so “I cannot say” cannot be laundered into a request.

Source

pub fn required_policies(&self) -> QoSPolicyMask

Compute the set of QoS policies actually requested by this profile.

Zero-valued time fields and LivelinessKind::None count as “not requesting” the corresponding policy — the cheap default.

issue 0829 — the four CORE bits (reliability, durability, history, depth) used to be added UNCONDITIONALLY, on the reasoning that every nano-ros backend honours them. That is true and still not the right test: this function answers what did the caller ASK FOR, and a SYSTEM_DEFAULT policy asks for nothing. Starting from CORE made QOS_PROFILE_SYSTEM_DEFAULT demand all four, so a backend that could not honour one would reject the profile with IncompatibleQos — for requesting nothing. The pattern was already here for the extended policies three lines down (a zero deadline_ms declines its bit); it just never reached the four CORE ones.

This RELAXES the mask, so it can only turn a rejection into an acceptance, never the reverse.

It used to say it flipped no verdict “because every supported_qos_policies impl in the tree returns at least CORE”. That stopped being true in phase-428 W9: the trait default is QoSPolicyMask::NONE now, so an implementation that claims nothing is refused on the first CORE bit a caller states — which is the whole point, and which makes THIS function’s sentinel handling the thing standing between QOS_PROFILE_SYSTEM_DEFAULT and a hard refusal.

Source

pub fn validate_against( &self, supported: QoSPolicyMask, ) -> Result<(), TransportError>

Returns Err(TransportError::IncompatibleQos(policy)) if any policy this profile requires is missing from the backend’s supported mask. Used at entity-create time to enforce the no silent degradation contract.

The error NAMES the policy (phase-417 G7). This computed the offending bit and discarded it until then, returning a bare IncompatibleQos — so every one of the six create_* paths in nros-node refused with the one fact the caller needed missing, while rmw_vtable.h told the reader the opposite. Which bit is reported when several are missing is QoSPolicyMask::lowest_policy’s choice, and it is stable so a test can assert it.

Source

pub const fn resolve_system_default(self, defaults: &QoSSystemDefaults) -> Self

Replace every SYSTEM_DEFAULT field with the backend’s own answer.

issue 0829 — a backend calls this at its create entry, before anything is derived from the profile (see QoSSystemDefaults for why the ordering matters on the zenoh path). Fields the caller DID state are left exactly as they are: this resolves an absence, it never overrides a request.

Idempotent, and safe to call on a fully concrete profile — a profile with no sentinel in it is returned unchanged.

Source

pub const fn has_unresolved_system_default(&self) -> bool

true if any field is still the SYSTEM_DEFAULT sentinel.

Depth is deliberately NOT part of this test: a KEEP_ALL profile legitimately carries depth 0 forever (any profile a caller builds with QoSProfile::keep_all and never gave a depth to — no NAMED preset is KEEP_ALL since phase-428 W10), and a backend that resolves the sentinel depth to 0 — XRCE does, on purpose — leaves a resolved profile reading 0 here. This asks about the three POLICY fields, where the sentinel is a distinct variant and so cannot be confused with a stated value.

Trait Implementations§

Source§

impl Clone for QoSProfile

Source§

fn clone(&self) -> QoSProfile

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for QoSProfile

Source§

impl Debug for QoSProfile

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for QoSProfile

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for QoSProfile

Source§

impl PartialEq for QoSProfile

Source§

fn eq(&self, other: &QoSProfile) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for QoSProfile

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.