pub struct Executor { /* private fields */ }Implementations§
Source§impl Executor
impl Executor
Sourcepub fn open(config: &ExecutorConfig<'_>) -> Result<Self, NodeError>
pub fn open(config: &ExecutorConfig<'_>) -> Result<Self, NodeError>
Open a new executor session using the active RMW backend.
Phase 115.M.4 — auto-registers the cffi vtable for whichever
backend the build was configured for, mirroring the C++ side’s
#ifdef NROS_RMW_<NAME> fan-out in <nros/node.hpp>. The
runtime’s atomic vtable slot is idempotent: a re-call of any
backend’s register() is a no-op, so the fan-out below is safe
to invoke on every Executor::open (cheaper than a Once and
doesn’t pull in std::sync for no_std targets).
Connects to the middleware at the locator specified in config.
§Example
let config = ExecutorConfig::from_env().node_name("my_node");
let mut executor = Executor::open(&config)?;Sourcepub fn open_multi(specs: &[SessionSpec<'_>]) -> Result<Self, NodeError>
pub fn open_multi(specs: &[SessionSpec<'_>]) -> Result<Self, NodeError>
Phase 128.F.1 — explicit per-backend session declaration for
bridge mode. specs[0] becomes the primary session; specs[1..]
open as extras keyed by RMW name. After construction, every
create_node_on(name, rmw) call dispatches to whichever
session was opened under that RMW name (or, when the rmw name
matches the primary, the primary session itself).
Single-backend callers should keep using
open — this entry costs an extra
open_with_rmw per spec and adds no value when only one
backend is linked.
$NROS_RMW env is ignored: bridge mode wants explicit names.
Sourcepub fn open_with_rmw(
rmw_name: &str,
config: &ExecutorConfig<'_>,
) -> Result<Self, NodeError>
pub fn open_with_rmw( rmw_name: &str, config: &ExecutorConfig<'_>, ) -> Result<Self, NodeError>
Phase 104.C.1 — open the Executor against a specific RMW
backend by name. Selects from the named registry (Phase
104.B.2). rmw_name must match one of the names a backend
registered under ("zenoh", "cyclonedds", "xrce", …).
Equivalent to Executor::open when the registry has exactly
one backend (the default-backend fast path). Use this entry
point in multi-backend builds where Executor::open would
pick the first-registered slot.
Single-Executor multi-Node multi-RMW (the long-term Design X
from docs/roadmap/phase-104-multi-backend-bridges.md) is
follow-up work — Phase 104.C.2 + C.3.
Source§impl Executor
impl Executor
Sourcepub fn from_session(session: CffiSession) -> Self
pub fn from_session(session: CffiSession) -> Self
Create an executor from an already-opened session.
Sourcepub unsafe fn from_session_ptr(session_ptr: *mut CffiSession) -> Self
pub unsafe fn from_session_ptr(session_ptr: *mut CffiSession) -> Self
Create an executor from a borrowed session pointer.
§Safety
session_ptrmust point to a valid, initialized session that lives at least as long as this executor.- The caller must not move or drop the session while the executor exists.
Sourcepub unsafe fn open_with_session(session: *mut CffiSession) -> Self
pub unsafe fn open_with_session(session: *mut CffiSession) -> Self
Phase 228.B (RFC-0015) — construct a tier task’s executor that shares
a session opened once by the orchestration main().
In the per-tier execution model main() opens one RMW session, then
spawns one RTOS task per priority tier; each task calls this to get an
Executor over the same session (the Borrowed session store — this
executor neither owns nor closes it), registers its tier’s callback
groups, and spins. Thin alias over Executor::from_session_ptr.
§Safety
session must outlive every executor/task built from it (the
orchestration main() holds it and never returns / WFIs), and must not
be mutated except through these executors’ spin calls.
Sourcepub fn session_ptr(&mut self) -> *mut CffiSession
pub fn session_ptr(&mut self) -> *mut CffiSession
Raw pointer to this executor’s RMW session, for the per-tier model:
the boot task opens the one session via Executor::open (the RMW
session is a process-wide singleton — opening twice fails), then hands
this pointer to each spawned tier task’s
Executor::open_with_session. The boot task’s executor owns the
session and outlives every borrower, so the pointer stays valid for the
program’s life. Works for both Owned and Borrowed stores.
§Safety
The returned pointer aliases self.session. Callers must keep self
alive (not moved/dropped) for as long as any tier executor uses the
pointer, and must only touch the session through executor spin calls
(the RMW backend serializes concurrent access through its own locks).
Sourcepub fn session_handle(&mut self) -> SessionHandle
pub fn session_handle(&mut self) -> SessionHandle
Opaque, Send form of session_ptr — the per-tier
model hands this to each spawned tier task (it can cross the RTOS task /
thread boundary, which a bare *mut cannot). See SessionHandle.
§Safety
Same contract as session_ptr: self (the session
owner) must outlive every executor built from the handle.
Sourcepub unsafe fn open_with_session_handle(handle: SessionHandle) -> Self
pub unsafe fn open_with_session_handle(handle: SessionHandle) -> Self
Open an Executor over the session a SessionHandle refers to (the
Borrowed store — neither owns nor closes it). The tier-task counterpart
to session_handle.
§Safety
The handle’s session must still be alive (its owning executor not moved or dropped); access only through executor spin calls.
Sourcepub fn set_active_groups(&mut self, groups: &[&str])
pub fn set_active_groups(&mut self, groups: &[&str])
Phase 228.C — set this tier executor’s active callback-group filter. The
generated per-tier task calls this before registering nodes; afterwards
only callbacks whose .callback_group() is in groups register here.
An empty slice (or never calling it) leaves the wildcard — register all
callbacks (the single-tier degenerate case + today’s behaviour).
Sourcepub fn group_active(&self, group: &str) -> bool
pub fn group_active(&self, group: &str) -> bool
Phase 228.C — whether a callback in group should register in this
executor under the current filter. Wildcard (None) accepts everything.
Sourcepub fn set_primary_identity(&mut self, rmw_name: &str, locator: &str)
pub fn set_primary_identity(&mut self, rmw_name: &str, locator: &str)
Set the node name and namespace used for liveliness tokens.
Called by open() to propagate config values. When register_subscription
or register_service creates entities, these values are attached to the
Phase 156 — record the primary session’s backend identity
(rmw name + locator) so NodeBuilder::resolve_session_slot
can detect when a .rmw(name) matches the primary instead
of opening a SECOND backend session against the same
singleton (zenoh-pico’s g_session is process-wide;
opening twice fails). Executor::open* calls this
automatically; the C surface (nros_executor_init) calls
it manually because it constructs via from_session_ptr
which doesn’t know the open metadata. Empty strings = “no
primary identity tracked”; the cache check degrades to
always-miss.
Sourcepub fn set_node_identity(&mut self, node_name: &str, namespace: &str)
pub fn set_node_identity(&mut self, node_name: &str, namespace: &str)
TopicInfo/ServiceInfo so the zenoh backend can declare liveliness.
Sourcepub fn default_sched_context_id(&self) -> SchedContextId
pub fn default_sched_context_id(&self) -> SchedContextId
Identifier of the auto-created default Fifo-class scheduling
context. Every callback registered without an explicit
[bind_handle_to_sched_context] binds to this SC.
Sourcepub fn create_sched_context(
&mut self,
sc: SchedContext,
) -> Result<SchedContextId, NodeError>
pub fn create_sched_context( &mut self, sc: SchedContext, ) -> Result<SchedContextId, NodeError>
Register a new scheduling context. Returns a [SchedContextId]
callers pass to [bind_handle_to_sched_context] to attach
callbacks. Phase 110.B.
Sourcepub fn bind_handle_to_sched_context(
&mut self,
handle: HandleId,
sc_id: SchedContextId,
) -> Result<(), NodeError>
pub fn bind_handle_to_sched_context( &mut self, handle: HandleId, sc_id: SchedContextId, ) -> Result<(), NodeError>
Bind a registered callback to a scheduling context. The next
spin_once cycle dispatches the callback through that SC’s
queue (FIFO bitmap or EDF heap). Phase 110.B.
Sourcepub fn register_time_triggered_dispatcher(&mut self, major_frame_us: u32)
pub fn register_time_triggered_dispatcher(&mut self, major_frame_us: u32)
Phase 110.G — enable time-triggered dispatch by setting the
executor’s major-frame length. Once set, every spin_once
cycle gates dispatch through each entry’s bound SC’s
tt_window_offset_us / tt_window_duration_us fields:
dispatch only fires when the current monotonic time falls
inside the window [off, off + duration) mod major_frame.
major_frame_us = 0 disables the TT gate (default state).
Setting a non-zero major frame after callbacks are already
registered is allowed — TT gates take effect on the next
spin_once cycle.
Sourcepub fn apply_time_triggered_schedule<const N: usize>(
&mut self,
schedule: &TimeTriggeredSchedule<N>,
) -> Result<[SchedContextId; N], TimeTriggeredScheduleError>
pub fn apply_time_triggered_schedule<const N: usize>( &mut self, schedule: &TimeTriggeredSchedule<N>, ) -> Result<[SchedContextId; N], TimeTriggeredScheduleError>
Phase 110.G — apply a declarative cyclic schedule.
One-shot helper that wraps the underlying primitives:
validates the schedule (major_frame > 0, no overlapping
windows, every window fits inside the major frame), sets the
executor’s major-frame length, then materialises one
SchedContext per window with class = TimeTriggered +
the window’s offset / duration. Returns the per-window
[SchedContextId] array so callers can immediately
bind_handle_to_sched_context(handle, sc_id) for their
subscription / timer handles.
N is the schedule’s declared maximum window count;
schedule.window_count gates how many SCs are actually
created. Unused trailing slots return
SchedContextId::default() (sentinel — callers must respect
window_count).
Sourcepub fn register_sporadic_timer(
&mut self,
sc_id: SchedContextId,
timer: OpaqueTimerHandle,
) -> Result<Arc<AtomicSporadicState>, NodeError>
pub fn register_sporadic_timer( &mut self, sc_id: SchedContextId, timer: OpaqueTimerHandle, ) -> Result<Arc<AtomicSporadicState>, NodeError>
Phase 110.E.b — register an ISR-driven refill timer for an
already-created Sporadic SC. The caller invokes their
platform’s PlatformTimer::create_periodic with the returned
Arc<AtomicSporadicState> as user_data and the
atomic_sporadic_refill_thunk as the callback, then hands
the resulting platform handle to this method via
OpaqueTimerHandle::new(handle, destroy_fn).
The Executor stores both the Arc and the handle so Drop can
clean them up. Calling this on a non-Sporadic SC returns
Err(InvalidSchedContextBinding).
Sourcepub fn sched_context(&self, sc_id: SchedContextId) -> Option<&SchedContext>
pub fn sched_context(&self, sc_id: SchedContextId) -> Option<&SchedContext>
Inspect a registered scheduling context. Phase 110.B.
Sourcepub fn node_builder<'a, 'cfg>(
&'a mut self,
name: &'cfg str,
) -> NodeBuilder<'a, 'cfg>
pub fn node_builder<'a, 'cfg>( &'a mut self, name: &'cfg str, ) -> NodeBuilder<'a, 'cfg>
Phase 104.C.2 — start a rclcpp-style Node builder for this
Executor. The returned NodeBuilder
is chainable:
let id = exec.node_builder("ingress")
.rmw("zenoh")
.locator("tcp/127.0.0.1:7447")
.sched(my_sc_id)
.build()?;In Phase 104.C.2 the Node table is storage-only — all registered Nodes share the Executor’s primary session. Per- Node session binding (the bridge feature) lands in Phase 104.C.3 when the session cache is wired.
Sourcepub fn nodes(&self) -> &[NodeRecord]
pub fn nodes(&self) -> &[NodeRecord]
Return the Node table — Phase 104.C.2 read accessor.
Sourcepub fn node(&self, id: NodeId) -> Option<&NodeRecord>
pub fn node(&self, id: NodeId) -> Option<&NodeRecord>
Borrow a Node’s metadata by id, returning None if the id
is out of range.
Sourcepub fn node_mut(&mut self, id: NodeId) -> NodeCtx<'_>
pub fn node_mut(&mut self, id: NodeId) -> NodeCtx<'_>
Phase 189.M1 — an executor-borrowing node handle for the entity builders
(exec.node_mut(id).subscription(t)... / .create_subscription(...)).
A short-lived &mut Executor borrow — use one at a time; entity handles
are owned and outlive it (see NodeCtx).
Sourcepub fn node_session_mut(&mut self, node_id: NodeId) -> Option<&mut CffiSession>
pub fn node_session_mut(&mut self, node_id: NodeId) -> Option<&mut CffiSession>
Phase 104.C.9.b — resolve the per-Node session for direct
entity creation paths (C++ FFI publisher / subscription /
service that bypass the register_*_on arena dispatch).
Returns None when node_id is out of range or the Node’s
session_idx lands outside the executor’s session table.
Sourcepub fn create_publisher_on<M: MessageForRmw>(
&mut self,
node_id: NodeId,
topic_name: &str,
qos: QosSettings,
) -> Result<EmbeddedPublisher<M>, NodeError>
pub fn create_publisher_on<M: MessageForRmw>( &mut self, node_id: NodeId, topic_name: &str, qos: QosSettings, ) -> Result<EmbeddedPublisher<M>, NodeError>
Phase 189.M1 — create a typed publisher bound to a node’s session.
Backs node.publisher(t).typed::<M>().build() on the
executor-borrowing NodeCtx; the returned
handle is owned and outlives the NodeCtx.
Sourcepub fn create_publisher_raw_on(
&mut self,
node_id: NodeId,
topic_name: &str,
type_name: &str,
type_hash: &str,
qos: QosSettings,
) -> Result<EmbeddedRawPublisher, NodeError>
pub fn create_publisher_raw_on( &mut self, node_id: NodeId, topic_name: &str, type_name: &str, type_hash: &str, qos: QosSettings, ) -> Result<EmbeddedRawPublisher, NodeError>
Phase 189.M1 — create a generic (type-erased) publisher bound to a
node’s session. Backs node.publisher(t).generic(ty, hash).build();
the bridge re-publishes through this handle on the dest session.
Sourcepub fn with_node_try<R>(
&mut self,
id: NodeId,
f: impl FnOnce(&mut NodeHandle<'_>) -> Result<R, NodeError>,
) -> Result<R, NodeError>
pub fn with_node_try<R>( &mut self, id: NodeId, f: impl FnOnce(&mut NodeHandle<'_>) -> Result<R, NodeError>, ) -> Result<R, NodeError>
Phase 104.C.3.2 — scoped Node-handle access. The closure
receives a [Node] bound to the requested [NodeId]’s
session + identity. Use the standard Node::create_publisher,
create_subscription, etc. APIs inside.
rclcpp-aligned bridge pattern:
let node_in = exec.node_builder("ingress").rmw("zenoh").build()?;
let node_out = exec.node_builder("egress").rmw("xrce").build()?;
let pub_out = exec.with_node(node_out, |n| {
n.create_publisher::<Int32>("/fwd")
})??;
exec.with_node(node_in, |n| {
n.create_subscription_buffered::<Int32, _, 1024>(
"/src", qos(), move |m| { let _ = pub_out.publish(m); }
)
})??;The closure can return any type; double-? unwraps the
outer Result<R, NodeError> from with_node and the inner
result returned by the closure.
Phase 104.C.3.3.d — flat-Result variant of
with_node. When the closure already
returns Result<R, NodeError>, this avoids the double-?:
// Without `with_node_try`:
let pub_ = exec.with_node(id, |n| n.create_publisher(...))??;
// With `with_node_try`:
let pub_ = exec.with_node_try(id, |n| n.create_publisher(...))?;pub fn with_node<R>( &mut self, id: NodeId, f: impl FnOnce(&mut NodeHandle<'_>) -> R, ) -> Result<R, NodeError>
Sourcepub fn node_id_by_name(&self, name: &str, namespace: &str) -> Option<NodeId>
pub fn node_id_by_name(&self, name: &str, namespace: &str) -> Option<NodeId>
Find a registered executor node by final name and namespace.
Sourcepub fn create_node(&mut self, name: &str) -> Result<NodeHandle<'_>, NodeError>
pub fn create_node(&mut self, name: &str) -> Result<NodeHandle<'_>, NodeError>
Create a node on this executor.
Sourcepub fn create_node_on(
&mut self,
name: &str,
rmw: &str,
) -> Result<NodeHandle<'_>, NodeError>
pub fn create_node_on( &mut self, name: &str, rmw: &str, ) -> Result<NodeHandle<'_>, NodeError>
Phase 128.F.2 — bridge-mode node factory. Registers a Node
bound to the named RMW backend by opening (or reusing) an
extra session via node_builder().rmw(rmw).build(), then
returns a [Node] borrowing that session. Use when the
binary intentionally links more than one backend and a Node
must speak a specific one.
The single-backend common case should keep using
create_node — this entry costs an
extra session lookup and serves no purpose when only one
backend is registered.
Sourcepub fn register_dispatch_slot(
&mut self,
state: *mut c_void,
on_callback: unsafe extern "C" fn(*mut c_void, *const u8, usize, *mut c_void),
) -> Result<(), ()>
pub fn register_dispatch_slot( &mut self, state: *mut c_void, on_callback: unsafe extern "C" fn(*mut c_void, *const u8, usize, *mut c_void), ) -> Result<(), ()>
Phase 216 follow-up — register a per-Node dispatch trampoline.
The board-side Entry pkg (or the macro-emitted
register_dispatch(executor) wrapper, once wired) calls this
once per deployed Node pkg, handing in the
__nros_node_<pkg>_on_callback symbol + the Node’s per-pkg
state blob. Executor::dispatch_callback then linear-scans
the registered slots when the dispatch task hands off a
SignaledCallback.
Returns Err(()) when the registry is full (MAX_NODES
entries — raise via NROS_EXECUTOR_MAX_NODES at build time).
§Safety
state must outlive the executor (the typical shape is a
*mut State produced by
nros::__private_node_state_into_raw from the
macro-emitted i(); that pointer’s lifetime IS the
Executor’s by construction). on_callback must be safe to
invoke with (state, cb_id_ptr, cb_id_len, ctx) matching the
per-Node __nros_node_<pkg>_on_callback ABI emitted by the
nros::node!() macro (Phase 216.A.5).
Sourcepub fn dispatch_slot_count(&self) -> usize
pub fn dispatch_slot_count(&self) -> usize
Phase 216 follow-up — current registered dispatch-slot count. Diagnostic / test surface.
Sourcepub unsafe fn enroll_component(
&mut self,
state: *mut c_void,
tick: unsafe extern "C" fn(*mut c_void, *mut c_void),
drop: unsafe extern "C" fn(*mut c_void),
) -> Result<(), ()>
pub unsafe fn enroll_component( &mut self, state: *mut c_void, tick: unsafe extern "C" fn(*mut c_void, *mut c_void), drop: unsafe extern "C" fn(*mut c_void), ) -> Result<(), ()>
Phase 258 (Track 2, 2a) — enroll a component into the executor-owned
tick registry. Called by nros’s install/register_node_borrowed
after it builds the Arc<ComponentCell>: state is the leaked
Arc<ComponentCell> (the slot takes ownership), tick/drop are the
nros-side trampolines (see [ComponentSlot]). The slot’s tick
runs at the tail of every spin_once; its drop
runs once on Executor::drop.
Returns Err(()) when the registry is full (MAX_NODES — raise via
NROS_EXECUTOR_MAX_NODES at build time). On error the caller still
owns state (the slot was not stored) and must drop it.
§Safety
state must be a *mut produced by leaking the component cell the
tick/drop trampolines expect (an Arc<ComponentCell> via
Arc::into_raw in the canonical nros caller), and must remain valid
until the matching drop runs. tick must be safe to invoke with
(state, exec_ctx = *mut Executor) each spin; drop must be safe to
invoke exactly once with state.
Sourcepub fn component_slot_count(&self) -> usize
pub fn component_slot_count(&self) -> usize
Phase 258 (Track 2, 2a) — current enrolled component-slot count. Diagnostic / test surface.
Sourcepub fn dispatch_callback(&mut self, cb_id: &str, ctx: *mut c_void)
pub fn dispatch_callback(&mut self, cb_id: &str, ctx: *mut c_void)
Phase 216 final dispatch hook — stable entry point the
framework’s dispatch task (RTIC __nros_run /
Embassy __nros_run_task) calls for each SignaledCallback
envelope it dequeues from the board-side SPSC / Embassy
channel.
§Signature shape
nros-node sits below nros in the dep graph, so the typed
nros::CallbackId<'_> / nros::CallbackCtx<'_> types
referenced in the Phase 216 design notes cannot appear in the
signature here. The macro emit translates the dequeued
envelope to the layer-clean (cb_id: &str, ctx: *mut c_void)
pair before calling this method; the per-Node on_callback
trampoline ABI (Phase 216.A.5,
__nros_node_<pkg>_on_callback(state, cb_id_ptr, cb_id_len, ctx)) uses the same untyped shape on the other side of the
fence, so the round-trip stays type-consistent.
§Body — linear scan of the dispatch registry
Each registered [DispatchSlot] holds an
__nros_node_<pkg>_on_callback fn pointer + the owning Node’s
state blob. The macro-emitted trampoline body
matches on CallbackId tags the Node declared and is a
no-op for non-matching cb_ids — at most one Node per
cb_id actually acts, the rest are cheap string-compare
no-ops. This mirrors the strategy
ExecutorNodeRuntime::dispatch_callback uses in
packages/core/nros/src/node_runtime.rs:470.
§What’s NOT auto-wired today
The nros::node!() macro doesn’t yet emit a
register_dispatch(executor) wrapper that pushes the per-pkg
(state, on_callback) into this registry. Until that wiring
lands (Phase 216 follow-up — see commit msg), downstream
consumers (board’s init_hardware, or the codegen-emitted
run_plan) must call
Executor::register_dispatch_slot explicitly with the
__nros_node_<pkg>_on_callback symbol + a state blob from
the macro-emitted i().
Sourcepub fn session(&self) -> &CffiSession
pub fn session(&self) -> &CffiSession
Get a reference to the underlying session.
Sourcepub fn session_mut(&mut self) -> &mut CffiSession
pub fn session_mut(&mut self) -> &mut CffiSession
Get a mutable reference to the underlying session.
Sourcepub fn ping(&mut self, timeout_ms: i32) -> Result<(), NodeError>
pub fn ping(&mut self, timeout_ms: i32) -> Result<(), NodeError>
Phase 124.F.3 — session-level connectivity probe. Wire-level round-trip “is the peer / agent / router still reachable?” — cheaper than the service-availability probe (no discovery state required).
Returns Ok(()) on reply within timeout_ms,
Err(NodeError::Transport(Timeout)) on no reply,
Err(NodeError::Transport(Unsupported)) when the active
backend can’t probe.
Mirrors micro-ROS’s rmw_uros_ping_agent. Useful for
reconnect-on-link-loss patterns: bare-metal code can call
ping(100) periodically and tear down / re-open the session
on timeout.
Sourcepub unsafe fn action_client_core_mut(
&mut self,
entry_index: usize,
) -> Option<&mut ActionClientCore>
pub unsafe fn action_client_core_mut( &mut self, entry_index: usize, ) -> Option<&mut ActionClientCore>
Get a mutable reference to an action client core in the arena by entry index.
§Safety
The caller must ensure that entry_index refers to an ActionClientRawArenaEntry.
Sourcepub unsafe fn service_client_entry_mut(
&mut self,
entry_index: usize,
) -> Option<&mut ServiceClientRawArenaEntry<{ crate::config::DEFAULT_RX_BUF_SIZE }>>
pub unsafe fn service_client_entry_mut( &mut self, entry_index: usize, ) -> Option<&mut ServiceClientRawArenaEntry<{ crate::config::DEFAULT_RX_BUF_SIZE }>>
Get a mutable reference to a service-client arena entry (Phase 82).
Returns None if entry_index doesn’t refer to a service client
entry. The default reply buffer size is assumed because the C API
always uses the default — the entry was registered via
register_service_client_raw_sized::<DEFAULT_RX_BUF_SIZE>.
§Safety
entry_index must refer to a ServiceClientRawArenaEntry.
Sourcepub fn set_trigger(&mut self, trigger: Trigger)
pub fn set_trigger(&mut self, trigger: Trigger)
Set the executor-level trigger condition.
Controls which handles must be ready before spin_once dispatches
callbacks. Defaults to Trigger::AnyReady.
Sourcepub fn set_semantics(&mut self, semantics: ExecutorSemantics)
pub fn set_semantics(&mut self, semantics: ExecutorSemantics)
Set the executor data communication semantics.
Choose between Direct (process in place) and LET
(snapshot-then-process) semantics. See ExecutorSemantics.
Sourcepub fn set_invocation(&mut self, id: HandleId, mode: InvocationMode)
pub fn set_invocation(&mut self, id: HandleId, mode: InvocationMode)
Sourcepub fn register_subscription_buffered_raw_info_on<F, const RX_BUF: usize>(
&mut self,
node_id: NodeId,
topic_name: &str,
type_name: &str,
type_hash: &str,
qos: QosSettings,
callback: F,
) -> Result<HandleId, NodeError>
pub fn register_subscription_buffered_raw_info_on<F, const RX_BUF: usize>( &mut self, node_id: NodeId, topic_name: &str, type_name: &str, type_hash: &str, qos: QosSettings, callback: F, ) -> Result<HandleId, NodeError>
Register a raw (type-erased) buffered subscription whose callback
also receives a RawMessageInfo
carrying the sample’s wire attachment (Phase 189.M1).
Backs the node.subscription(t).generic(..).message_info().build(cb)
builder — the cross-RMW bridge reads the bridge_origin tag from
info.attachment() for echo suppression. One sample per
spin_once; the attachment is staged in a flat per-entry buffer
(cap RAW_INFO_ATT_CAP).
Sourcepub fn add_arena_subscription_callback<F, const RX_BUF: usize>(
&mut self,
handle: RmwSubscriber,
qos: QosSettings,
callback: F,
) -> Result<HandleId, NodeError>
pub fn add_arena_subscription_callback<F, const RX_BUF: usize>( &mut self, handle: RmwSubscriber, qos: QosSettings, callback: F, ) -> Result<HandleId, NodeError>
Register a raw byte-shaped callback against a pre-built
RmwSubscriber handle.
Backend-agnostic primitive — the caller is responsible for obtaining the handle by whatever route the active backend supports:
- Generic ROS-typed flow: call
Session::create_subscriberonself.session_mut()with aTopicInfo. Thenode_mut(id).subscription(t).generic(ty, hash)builder is the convenience wrapper for this path. - Backend-specific flow (e.g. uORB needs
&'static orb_metadata): reach into the concrete session viaSelf::session_mutand call its backend-specific create method, then hand the handle here.nros-px4::uorb::create_subscription_with_callbackis the example.
The arena-store + vtable wiring is identical to
register_subscription_buffered_raw; the only thing that varies is
where the handle came from. Callback fires on every message
delivery during spin_once; bytes are
passed as &[u8].
Sourcepub fn register_service<Svc, F>(
&mut self,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
pub fn register_service<Svc, F>(
&mut self,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
Register a service callback with the default buffer size.
The callback is stored in the arena and invoked during spin_once().
Sourcepub fn register_service_sized<Svc, F, const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
pub fn register_service_sized<Svc, F, const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
Register a service callback with custom request/reply buffer sizes.
Sourcepub fn register_service_sized_on<Svc, F, const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
node_id: NodeId,
service_name: &str,
qos: QosSettings,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
pub fn register_service_sized_on<Svc, F, const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
node_id: NodeId,
service_name: &str,
qos: QosSettings,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
Phase 104.C.3.3.a — Node-aware variant of
register_service_sized.
Sourcepub fn register_service_on<Svc, F>(
&mut self,
node_id: NodeId,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
pub fn register_service_on<Svc, F>(
&mut self,
node_id: NodeId,
service_name: &str,
callback: F,
) -> Result<HandleId, NodeError>where
Svc: RosService + 'static,
Svc::Request: MessageForRmw,
Svc::Reply: MessageForRmw,
F: FnMut(&Svc::Request) -> Svc::Reply + 'static,
Phase 104.C.3.3.a — Node-aware variant of
register_service.
Sourcepub fn register_timer<F>(
&mut self,
period: TimerDuration,
callback: F,
) -> Result<HandleId, NodeError>where
F: FnMut() + 'static,
pub fn register_timer<F>(
&mut self,
period: TimerDuration,
callback: F,
) -> Result<HandleId, NodeError>where
F: FnMut() + 'static,
Register a repeating timer callback.
The callback fires every period milliseconds during spin_once().
The timer delta is approximated by the timeout_ms argument to spin_once.
Sourcepub fn register_timer_oneshot<F>(
&mut self,
delay: TimerDuration,
callback: F,
) -> Result<HandleId, NodeError>where
F: FnMut() + 'static,
pub fn register_timer_oneshot<F>(
&mut self,
delay: TimerDuration,
callback: F,
) -> Result<HandleId, NodeError>where
F: FnMut() + 'static,
Register a one-shot timer callback.
The callback fires once after delay milliseconds, then becomes inert.
Sourcepub fn add_arena_subscription_c_callback<const RX_BUF: usize>(
&mut self,
node_id: Option<NodeId>,
topic_name: &str,
type_name: &str,
type_hash: &str,
qos: QosSettings,
callback: RawSubscriptionCallback,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn add_arena_subscription_c_callback<const RX_BUF: usize>( &mut self, node_id: Option<NodeId>, topic_name: &str, type_name: &str, type_hash: &str, qos: QosSettings, callback: RawSubscriptionCallback, context: *mut c_void, ) -> Result<HandleId, NodeError>
The kept C-FFI subscription core (Phase 189.M2.b): registers a
raw RawSubscriptionCallback fn-ptr + context against an
optional node’s session. The Rust ergonomic surface is the
node.subscription(t) builder (closures); this is the single
primitive the nros-c thin wrapper lowers to. node_id == None
is the legacy single-node path.
Sourcepub fn add_arena_subscription_c_info_callback<const RX_BUF: usize>(
&mut self,
node_id: Option<NodeId>,
topic_name: &str,
type_name: &str,
type_hash: &str,
qos: QosSettings,
callback: RawSubscriptionInfoCallback,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn add_arena_subscription_c_info_callback<const RX_BUF: usize>( &mut self, node_id: Option<NodeId>, topic_name: &str, type_name: &str, type_hash: &str, qos: QosSettings, callback: RawSubscriptionInfoCallback, context: *mut c_void, ) -> Result<HandleId, NodeError>
Phase 189.M3.4 — register a raw C-fn-ptr subscription whose callback
also receives the sample’s wire attachment
(RawSubscriptionInfoCallback: (data, len, attachment, att_len, context)) — the C analog of the Rust
node.subscription(t).generic(..).message_info() builder. Backs the C
FFI nros_executor_register_subscription_raw_with_info. Flat per-entry
payload + attachment buffers (cap RAW_INFO_ATT_CAP);
one sample per spin_once.
Sourcepub fn register_service_raw(
&mut self,
service_name: &str,
service_type: &str,
service_hash: &str,
callback: RawServiceCallback,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_raw( &mut self, service_name: &str, service_type: &str, service_hash: &str, callback: RawServiceCallback, context: *mut c_void, ) -> Result<HandleId, NodeError>
Register a raw (untyped) service callback.
Register a raw (untyped) service callback with the default buffer size.
The callback receives and produces CDR bytes without typed deserialization/serialization. Used by the C API wrapper.
Sourcepub fn register_service_raw_sized<const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
service_name: &str,
service_type: &str,
service_hash: &str,
qos: QosSettings,
callback: RawServiceCallback,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_raw_sized<const REQ_BUF: usize, const REPLY_BUF: usize>( &mut self, service_name: &str, service_type: &str, service_hash: &str, qos: QosSettings, callback: RawServiceCallback, context: *mut c_void, ) -> Result<HandleId, NodeError>
Register a raw (untyped) service callback with custom buffer sizes + QoS.
REQ_BUF and REPLY_BUF set the stack-allocated CDR buffers
for the request and reply respectively. Increase for services
with large payloads (e.g., parameter services). qos applies to both
the request + reply endpoints (Phase 193.2c).
Sourcepub fn register_service_raw_sized_on<const REQ_BUF: usize, const REPLY_BUF: usize>(
&mut self,
node_id: NodeId,
service_name: &str,
service_type: &str,
service_hash: &str,
qos: QosSettings,
callback: RawServiceCallback,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_raw_sized_on<const REQ_BUF: usize, const REPLY_BUF: usize>( &mut self, node_id: NodeId, service_name: &str, service_type: &str, service_hash: &str, qos: QosSettings, callback: RawServiceCallback, context: *mut c_void, ) -> Result<HandleId, NodeError>
Phase 104.C.3.3.a — Node-aware variant of
[register_service_raw_sized]. C-FFI path.
Sourcepub fn register_service_client_raw(
&mut self,
service_name: &str,
service_type: &str,
service_hash: &str,
callback: Option<RawResponseCallback>,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_client_raw( &mut self, service_name: &str, service_type: &str, service_hash: &str, callback: Option<RawResponseCallback>, context: *mut c_void, ) -> Result<HandleId, NodeError>
Register a raw (untyped) service client with the default reply buffer size.
The client is owned by the executor’s arena. Each spin_once
dispatch polls the in-flight reply slot via try_recv_reply_raw
and fires the registered callback when the response arrives.
Used by the C API thin wrapper — see Phase 82.
Sourcepub fn register_service_client_raw_sized<const REPLY_BUF: usize>(
&mut self,
service_name: &str,
service_type: &str,
service_hash: &str,
qos: QosSettings,
callback: Option<RawResponseCallback>,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_client_raw_sized<const REPLY_BUF: usize>( &mut self, service_name: &str, service_type: &str, service_hash: &str, qos: QosSettings, callback: Option<RawResponseCallback>, context: *mut c_void, ) -> Result<HandleId, NodeError>
Register a raw service client with a custom reply buffer size + QoS.
qos applies to the client’s request + reply endpoints (Phase 193.3b);
defaults to QosSettings::services_default via the convenience
wrapper.
Sourcepub fn register_service_client_raw_sized_on<const REPLY_BUF: usize>(
&mut self,
node_id: NodeId,
service_name: &str,
service_type: &str,
service_hash: &str,
qos: QosSettings,
callback: Option<RawResponseCallback>,
context: *mut c_void,
) -> Result<HandleId, NodeError>
pub fn register_service_client_raw_sized_on<const REPLY_BUF: usize>( &mut self, node_id: NodeId, service_name: &str, service_type: &str, service_hash: &str, qos: QosSettings, callback: Option<RawResponseCallback>, context: *mut c_void, ) -> Result<HandleId, NodeError>
Phase 104.C.3.3.a — Node-aware variant of
[register_service_client_raw_sized]. Routes the client
creation through the named Node’s session.
Sourcepub fn register_guard_condition<F>(
&mut self,
callback: F,
) -> Result<(HandleId, GuardConditionHandle), NodeError>where
F: FnMut() + 'static,
pub fn register_guard_condition<F>(
&mut self,
callback: F,
) -> Result<(HandleId, GuardConditionHandle), NodeError>where
F: FnMut() + 'static,
Register a guard condition with a callback.
Returns both the HandleId for trigger configuration and a
GuardConditionHandle for triggering from other threads.
Sourcepub fn cancel_timer(&mut self, id: HandleId) -> Result<(), NodeError>
pub fn cancel_timer(&mut self, id: HandleId) -> Result<(), NodeError>
Cancel a timer. A cancelled timer will not fire but still accumulates
elapsed time. The timer can be restarted with reset_timer().
Sourcepub fn reset_timer(&mut self, id: HandleId) -> Result<(), NodeError>
pub fn reset_timer(&mut self, id: HandleId) -> Result<(), NodeError>
Reset a timer. Clears the cancelled state and resets the elapsed time to zero, so the timer starts a fresh period.
Sourcepub fn timer_is_cancelled(&self, id: HandleId) -> bool
pub fn timer_is_cancelled(&self, id: HandleId) -> bool
Check if a timer is cancelled.
Sourcepub fn timer_period_ms(&self, id: HandleId) -> Option<u64>
pub fn timer_period_ms(&self, id: HandleId) -> Option<u64>
Get the period of a timer in milliseconds, or None if the handle
is not a valid timer.
Sourcepub fn spin_once(&mut self, timeout: Duration) -> SpinOnceResult
pub fn spin_once(&mut self, timeout: Duration) -> SpinOnceResult
Drive I/O and dispatch registered callbacks once.
Three-phase execution:
- Readiness scan — query each handle’s
has_data(). - Trigger evaluation — check if the executor-level trigger passes.
- Dispatch — invoke callbacks according to their
InvocationMode.
Returns a SpinOnceResult with counts of processed items and errors.
§Arguments
timeout— upper bound on the I/O wait. Saturated ati32::MAXms (~24 days) for the underlying transport call.
Phase 84.D7: unified on core::time::Duration. The previous
timeout_ms: i32 signature had a latent footgun where
spin_once(-1) silently froze timers while still polling I/O;
Duration has no negative sentinel.
Sourcepub fn spin(&mut self, timeout: Duration) -> !
pub fn spin(&mut self, timeout: Duration) -> !
Drive I/O and dispatch callbacks in an infinite loop.
Each iteration calls spin_once(timeout_ms),
which pumps the transport and dispatches all registered callbacks.
This is the primary run loop for embedded applications:
let mut executor = Executor::open(&config)?;
executor.register_subscription::<Int32, _>("/topic", |msg| { /* ... */ })?;
executor.spin(10); // never returnsSourcepub fn spin_default(&mut self) -> !
pub fn spin_default(&mut self) -> !
Phase 104.C.3.3.c — rclcpp-spin()-shape no-arg variant.
Defaults the per-iteration timeout to 50 ms, which keeps
idle binaries from busy-spinning while staying responsive
enough for default-QoS messaging.
Sourcepub async fn spin_async(&mut self) -> !
pub async fn spin_async(&mut self) -> !
Drive I/O and dispatch callbacks asynchronously.
Runs forever, yielding between poll cycles so that other async tasks
(e.g., Promise) can make progress.
Uses only core::future — no external async runtime dependency.
§Usage patterns
// Pattern 1: select with a promise (embassy-futures)
use embassy_futures::select::{select, Either};
let promise = client.call(&req)?;
let Either::Second(reply) = select(executor.spin_async(), promise).await
else { unreachable!() };
// Pattern 2: manual polling (no async runtime)
let mut promise = client.call(&req)?;
loop {
executor.spin_once(core::time::Duration::from_millis(10));
if let Ok(Some(r)) = promise.try_recv() { break r; }
}Sourcepub fn spin_one_period(
&mut self,
period_ms: u64,
elapsed_ms: u64,
) -> SpinPeriodPollingResult
pub fn spin_one_period( &mut self, period_ms: u64, elapsed_ms: u64, ) -> SpinPeriodPollingResult
Process one iteration and return remaining sleep time.
This is no_std compatible — the caller is responsible for the actual
delay using platform-specific sleep.
§Arguments
period_ms- Target period in millisecondselapsed_ms- Time elapsed since last call (used for timer ticking)
§Example
loop {
let r = executor.spin_one_period(10, elapsed_ms);
platform_sleep_ms(r.remaining_ms);
}Source§impl Executor
impl Executor
Sourcepub fn spin_blocking(&mut self, opts: SpinOptions) -> Result<(), NodeError>
pub fn spin_blocking(&mut self, opts: SpinOptions) -> Result<(), NodeError>
Blocking spin loop with configurable exit conditions.
Runs until one of:
halt()is called (from another thread or signal handler)- Timeout expires (if set in options)
- Max callbacks reached (if set in options)
only_nextis true (single iteration)
§Example
// Spin forever until halted
executor.spin_blocking(SpinOptions::default())?;
// Spin with 5-second timeout
executor.spin_blocking(SpinOptions::new().timeout_ms(5000))?;
// Single iteration
executor.spin_blocking(SpinOptions::spin_once())?;Sourcepub fn spin_one_period_timed(&mut self, period: Duration) -> SpinPeriodResult
pub fn spin_one_period_timed(&mut self, period: Duration) -> SpinPeriodResult
Execute one period with wall-clock overrun detection.
Calls spin_once(), measures wall-clock time, sleeps
for the remainder if under budget.
§Example
let period = std::time::Duration::from_millis(10);
let result = executor.spin_one_period_timed(period);
if result.overrun {
log::warn!("Period overrun: {:?}", result.elapsed);
}Sourcepub fn spin_period(&mut self, period: Duration) -> Result<(), NodeError>
pub fn spin_period(&mut self, period: Duration) -> Result<(), NodeError>
Spin at a fixed rate with drift compensation. Blocks until halted.
Uses wall-clock time to maintain the target rate. The next invocation
time is accumulated (not reset to now + period) to prevent cumulative
drift.
§Example
// 100Hz control loop — blocks until halt() is called
executor.spin_period(std::time::Duration::from_millis(10))?;Sourcepub fn halt(&self)
pub fn halt(&self)
Request the executor to stop spinning.
Sets a flag that causes spin_blocking() or
spin_period() to exit on the next iteration.
Safe to call from another thread or signal handler.
Also raises the Phase 104.C.6 wake flag so a spin_once already
blocked inside a backend’s drive_io falls through to the halt
check on its next loop iteration instead of waiting out its full
timeout_ms first.
Sourcepub unsafe fn open_threaded(
self,
policy: SchedPolicy,
apply_policy: fn(SchedPolicy) -> Result<(), SchedError>,
spin_period: Duration,
) -> ThreadHandle
pub unsafe fn open_threaded( self, policy: SchedPolicy, apply_policy: fn(SchedPolicy) -> Result<(), SchedError>, spin_period: Duration, ) -> ThreadHandle
Phase 110.D.b — move this Executor onto a fresh OS thread,
apply a per-thread scheduling policy via the caller-supplied
apply_policy function, and run the spin loop until
[ThreadHandle::halt] fires.
The function-pointer indirection on apply_policy lets the
caller pass any platform’s PlatformScheduler::set_current_thread_policy
without forcing Executor to be generic over the platform —
keeps the existing Executor type stable.
Multi-executor preemption (the actual hard-RT win) comes from
the OS scheduler — call open_threaded once per criticality
tier, each with its own policy / priority. The kernel handles
preemption across executors; within a single executor,
dispatch remains non-preemptive (110.A–C bucketed sets).
§Safety
Moves self across thread boundaries. Executor contains a
raw *mut session::ConcreteSession when constructed via
from_session_ptr; the caller must ensure that pointer’s
referent stays valid across the lifetime of the spawned thread
and that no other thread mutates the session concurrently.
from_session (Owned) is safer — ConcreteSession ownership
transfers cleanly into the thread.
Sourcepub fn halt_flag(&self) -> Arc<AtomicBool>
pub fn halt_flag(&self) -> Arc<AtomicBool>
Sourcepub fn wake(&self)
pub fn wake(&self)
Phase 104.C.6 — wake the executor from another thread / ISR / signal handler.
Sets the shared wake_flag. The next spin_once swap-clears the
flag, skips the blocking wait on the primary session, and polls
every session non-blockingly so whatever queued the wake is
observed in a single iteration. Idempotent — multiple wake()
calls collapse into one observed wake per spin_once.
Sourcepub fn wake_handle(&self) -> Arc<AtomicBool>
pub fn wake_handle(&self) -> Arc<AtomicBool>
Phase 104.C.6 — clone of the shared wake flag for cross-thread use (signal handlers, foreign threads, future per-backend vtable wake hooks).
§Example
let wake = executor.wake_handle();
std::thread::spawn(move || {
// ... compute something ...
// hand off to executor by setting the flag.
wake.store(true, Ordering::SeqCst);
});
loop { executor.spin_once(Duration::from_millis(100)); }Source§impl Executor
impl Executor
Sourcepub fn register_action_server<A, GoalF, CancelF>(
&mut self,
action_name: &str,
goal_callback: GoalF,
cancel_callback: CancelF,
) -> Result<ActionServerHandle<A>, NodeError>where
A: RosAction + 'static,
A::Goal: Clone + MessageForRmw,
A::Result: Clone + Default + MessageForRmw,
A::Feedback: MessageForRmw,
A::SendGoalRequest: MessageForRmw,
A::SendGoalResponse: MessageForRmw,
A::GetResultRequest: MessageForRmw,
A::GetResultResponse: MessageForRmw,
A::FeedbackMessage: MessageForRmw,
GoalF: FnMut(&GoalId, &A::Goal) -> GoalResponse + 'static,
CancelF: FnMut(&GoalId, GoalStatus) -> CancelResponse + 'static,
pub fn register_action_server<A, GoalF, CancelF>(
&mut self,
action_name: &str,
goal_callback: GoalF,
cancel_callback: CancelF,
) -> Result<ActionServerHandle<A>, NodeError>where
A: RosAction + 'static,
A::Goal: Clone + MessageForRmw,
A::Result: Clone + Default + MessageForRmw,
A::Feedback: MessageForRmw,
A::SendGoalRequest: MessageForRmw,
A::SendGoalResponse: MessageForRmw,
A::GetResultRequest: MessageForRmw,
A::GetResultResponse: MessageForRmw,
A::FeedbackMessage: MessageForRmw,
GoalF: FnMut(&GoalId, &A::Goal) -> GoalResponse + 'static,
CancelF: FnMut(&GoalId, GoalStatus) -> CancelResponse + 'static,
Register an action server with goal/cancel callbacks.
The executor automatically dispatches:
- Goal acceptance via
goal_callback - Cancel requests via
cancel_callback - Result serving for completed goals
Use the returned ActionServerHandle to publish feedback and complete goals.
Uses default buffer sizes and max 4 concurrent goals.
Sourcepub fn register_action_server_sized<A, GoalF, CancelF, const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize>(
&mut self,
action_name: &str,
goal_callback: GoalF,
cancel_callback: CancelF,
) -> Result<ActionServerHandle<A>, NodeError>where
A: RosAction + 'static,
A::Goal: Clone + MessageForRmw,
A::Result: Clone + Default + MessageForRmw,
A::Feedback: MessageForRmw,
A::SendGoalRequest: MessageForRmw,
A::SendGoalResponse: MessageForRmw,
A::GetResultRequest: MessageForRmw,
A::GetResultResponse: MessageForRmw,
A::FeedbackMessage: MessageForRmw,
GoalF: FnMut(&GoalId, &A::Goal) -> GoalResponse + 'static,
CancelF: FnMut(&GoalId, GoalStatus) -> CancelResponse + 'static,
pub fn register_action_server_sized<A, GoalF, CancelF, const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize>(
&mut self,
action_name: &str,
goal_callback: GoalF,
cancel_callback: CancelF,
) -> Result<ActionServerHandle<A>, NodeError>where
A: RosAction + 'static,
A::Goal: Clone + MessageForRmw,
A::Result: Clone + Default + MessageForRmw,
A::Feedback: MessageForRmw,
A::SendGoalRequest: MessageForRmw,
A::SendGoalResponse: MessageForRmw,
A::GetResultRequest: MessageForRmw,
A::GetResultResponse: MessageForRmw,
A::FeedbackMessage: MessageForRmw,
GoalF: FnMut(&GoalId, &A::Goal) -> GoalResponse + 'static,
CancelF: FnMut(&GoalId, GoalStatus) -> CancelResponse + 'static,
Register an action server with custom buffer sizes.
Source§impl Executor
impl Executor
Sourcepub fn register_action_server_raw(
&mut self,
spec: RawActionServerSpec<'_>,
) -> Result<ActionServerRawHandle, NodeError>
pub fn register_action_server_raw( &mut self, spec: RawActionServerSpec<'_>, ) -> Result<ActionServerRawHandle, NodeError>
Register a raw action server with raw-bytes callbacks.
Unlike register_action_server(), this does
not require RosAction — the goal/cancel callbacks receive raw CDR
bytes. This is used by the C API thin wrapper.
type_name and type_hash identify the action type for key expression
construction and liveliness tokens.
Sourcepub fn register_action_server_raw_sized<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize>(
&mut self,
spec: RawActionServerSpec<'_>,
) -> Result<ActionServerRawHandle, NodeError>
pub fn register_action_server_raw_sized<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize, const MAX_GOALS: usize>( &mut self, spec: RawActionServerSpec<'_>, ) -> Result<ActionServerRawHandle, NodeError>
Register a raw action server with custom buffer sizes.
spec.node_id selects the target: None registers on the
executor’s own node, Some(id) routes the server’s 5 underlying
handles through the named Node’s session (Phase 104.C.3.3.a).
spec.qos applies to the action’s three underlying service
servers (send_goal / cancel_goal / get_result; Phase 193.4b); the
feedback + status publishers keep their own profiles.
Source§impl Executor
impl Executor
Sourcepub fn register_action_client_raw(
&mut self,
spec: RawActionClientSpec<'_>,
) -> Result<ActionClientRawHandle, NodeError>
pub fn register_action_client_raw( &mut self, spec: RawActionClientSpec<'_>, ) -> Result<ActionClientRawHandle, NodeError>
Register a raw action client with the executor.
Creates service clients for send_goal, cancel_goal, get_result, and a
feedback subscriber. The executor polls these during spin_once and
invokes the provided callbacks when responses/feedback arrive.
§Arguments
action_name— action name (e.g., “/fibonacci”)type_name— action type (e.g., “example_interfaces::action::dds_::Fibonacci_”)type_hash— type hash (e.g., “TypeHashNotSupported”)goal_response_callback— called when goal is accepted/rejectedfeedback_callback— called when feedback is receivedresult_callback— called when result is receivedcontext— opaque pointer passed to all callbacks
Sourcepub fn register_action_client_raw_sized<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize>(
&mut self,
spec: RawActionClientSpec<'_>,
) -> Result<ActionClientRawHandle, NodeError>
pub fn register_action_client_raw_sized<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize>( &mut self, spec: RawActionClientSpec<'_>, ) -> Result<ActionClientRawHandle, NodeError>
Register a raw action client with explicit buffer sizes.
spec.node_id selects the target: None registers on the
executor’s own node, Some(id) routes the client’s 4 underlying
handles through the named Node’s session (Phase 104.C.3.3.a).
Source§impl Executor
impl Executor
Sourcepub fn register_action_client_core<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize>(
&mut self,
core: ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>,
goal_response_callback: Option<RawGoalResponseCallback>,
feedback_callback: Option<RawFeedbackCallback>,
result_callback: Option<RawResultCallback>,
context: *mut c_void,
) -> Result<ActionClientRawHandle, NodeError>
pub fn register_action_client_core<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize>( &mut self, core: ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>, goal_response_callback: Option<RawGoalResponseCallback>, feedback_callback: Option<RawFeedbackCallback>, result_callback: Option<RawResultCallback>, context: *mut c_void, ) -> Result<ActionClientRawHandle, NodeError>
Register an existing ActionClientCore with the executor for async polling.
Unlike register_action_client_raw (which creates new transport handles),
this takes ownership of an existing core. Use this when the core was
already created by the C/C++ action client init.