Skip to main content

EmbeddedServiceClient

Struct EmbeddedServiceClient 

Source
pub struct EmbeddedServiceClient<Svc, const REQ_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#0}, const REPLY_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#1}>
where Svc: RosService,
{ /* private fields */ }
Expand description

Typed service client handle with internal buffers.

Implementations§

Source§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>
where Svc: RosService,

Source

pub fn call( &mut self, request: &<Svc as RosService>::Request, ) -> Result<Promise<'_, <Svc as RosService>::Reply>, NodeError>

Call the service (non-blocking). Returns a Promise that can be polled.

Use with Executor::spin_once() to drive I/O while waiting:

let mut promise = client.call(&request)?;
loop {
    executor.spin_once(core::time::Duration::from_millis(10));
    if let Some(reply) = promise.try_recv()? {
        break;
    }
}
§Errors

Returns NodeError::RequestInFlight if a previous call’s reply has not been received. This prevents the old hazard where dropping a Promise without awaiting its reply left the stale reply queued to land on the next call. Resolve by polling the existing promise to completion or calling reset_in_flight.

Source

pub fn reset_in_flight(&mut self)

Explicitly clear the in-flight flag (Phase 84.D3).

Call this if a previous Promise was dropped without completing and you want to abandon the pending reply. The next call will proceed but may still observe the stale reply if one is in the transport’s queue — callers that need strict correctness should drain / ignore one extra try_recv first.

Source

pub fn wait_for_service( &mut self, executor: &mut Executor, timeout: Duration, ) -> Result<bool, NodeError>

Block until at least one matching service server is discoverable on the network, or timeout elapses.

Returns Ok(true) if a matching server reported back inside the budget; Ok(false) on timeout (no server visible). Mirrors rclcpp::ClientBase::wait_for_service and rclpy.client.Client.wait_for_service.

On the Zenoh backend this issues a z_liveliness_get against the matching server’s wildcarded liveliness keyexpr; the executor is spun cooperatively while the query is in flight so other subscribers / timers continue to make progress. Backends without liveliness discovery answer Ok(true) immediately (default trait impl in nros-rmw), so the call is a no-op cost when discovery isn’t supported.

Recommended usage — gate the first call() on this:

let mut client = node.create_client::<AddTwoInts>("/add_two_ints")?;
if !client.wait_for_service(&mut executor, Duration::from_secs(5))? {
    return Err(NodeError::Timeout);
}
let mut promise = client.call(&request)?;

Once the server is observed, the result is latched: subsequent service_is_ready checks return true without another round trip. This matches rclcpp’s snapshot semantic — discovery isn’t re-proven on every call.

Source

pub fn service_is_ready(&self) -> bool

Snapshot whether a matching service server is currently visible.

Non-blocking. Matches rclcpp::ClientBase::service_is_ready and rclpy.client.Client.service_is_ready. Backends without liveliness discovery return true (assume always reachable).

Source

pub fn server_available(&self) -> Result<bool, NodeError>

Phase 124.C.3 — graph-aware server-availability probe.

Returns Ok(true) / Ok(false) when the backend can answer (zenoh queryable interest, DDS built-in topic reader), or Err(NodeError::Transport(Unsupported)) when it can’t (XRCE agent without participant enumeration). Distinct from service_is_ready — that one collapses “no” and “don’t know” into the same false.

Used to gate the first call_raw so a startup-ordering race (client opens before server’s discovery announcement lands) doesn’t surface as a request-side timeout.

Auto Trait Implementations§

§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> Freeze for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>

§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> RefUnwindSafe for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>
where Svc: RefUnwindSafe,

§

impl<Svc, const REQ_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#0}, const REPLY_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#1}> !Send for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>

§

impl<Svc, const REQ_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#0}, const REPLY_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#1}> !Sync for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>

§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> Unpin for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>
where Svc: Unpin,

§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> UnsafeUnpin for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>

§

impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> UnwindSafe for EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>
where Svc: UnwindSafe,

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> 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, 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.