|
nros C++ API
Lightweight ROS 2 client for embedded real-time systems (C++ headers)
|
#include <client.hpp>
Public Types | |
| using | RequestType = typename S::Request |
| using | ResponseType = typename S::Response |
| using | TypedResponseFn = void(*)(const ResponseType &response) |
| using | TypedResponseFnWithCtx = void(*)(const ResponseType &response, void *ctx) |
Public Member Functions | |
| Result | async_send_request (const RequestType &req) |
| Result | call (const RequestType &req, ResponseType &resp, uint32_t timeout_ms=5000) |
| Result | call_polling (const RequestType &req, ResponseType &resp, uint32_t timeout_ms=100) |
| template<size_t RespCap> | |
| Result | call_polling_sized (const RequestType &req, ResponseType &resp, uint32_t timeout_ms=100) |
| template<size_t RespCap> | |
| Result | call_sized (const RequestType &req, ResponseType &resp, uint32_t timeout_ms=5000) |
| call with the REPLY buffer sized by the caller (issue 0964). | |
| Client () | |
| Client (Client &&other) | |
| size_t | handle_id () const |
| bool | is_valid () const |
| Check if the client is initialized and valid. | |
| Client & | operator= (Client &&other) |
| Future< ResponseType > | send_request (const RequestType &req) |
| template<size_t RespCap> | |
| Future< ResponseType, RespCap > | send_request_sized (const RequestType &req) |
| int | server_available () const |
| Expected< bool > | service_is_ready () const |
| Result | wait_for_service (uint32_t timeout_ms=5000) |
| ~Client () | |
Friends | |
| class | Node |
Typed service client for a ROS 2 service.
Mirrors rclcpp::Client<S>. The service type S must provide nested Request and Response types with TYPE_NAME, TYPE_HASH, SERIALIZED_SIZE_MAX, ffi_serialize(), and ffi_deserialize().
Usage (async – preferred):
| using nros::Client< S >::RequestType = typename S::Request |
| using nros::Client< S >::ResponseType = typename S::Response |
| using nros::Client< S >::TypedResponseFn = void (*)(const ResponseType& response) |
Phase 189.M3.3.f — typed response-handler signatures for the callback-style client (rclcpp async dispatch). The handler runs during spin_once when a reply arrives for a request sent via async_send_request.
| using nros::Client< S >::TypedResponseFnWithCtx = void (*)(const ResponseType& response, void* ctx) |
|
inline |
Destructor – releases service client resources.
Future-style clients own an RmwServiceClient in storage_; callback-style clients (M3.3.f) are owned by the executor arena, so the dtor must NOT touch storage_ for them.
|
inline |
|
inline |
Default constructor – creates an uninitialized service client. Use Node::create_client() to initialize.
|
inline |
Phase 189.M3.3.f — callback-style async send. Only valid on a callback-style client (created via the create_client(out, name, callback,
...) overload); the reply is delivered to the registered response handler during spin_once (no Future). Returns immediately after sending.
|
inline |
Send a request and block until a reply is received.
Spins the executor internally (like the runtime's Promise::wait). Never calls zpico_get — all I/O is driven by spin_once.
| req | Request to send. |
| resp | Output response struct (filled on success). |
| timeout_ms | Maximum wait time (default 5000ms). |
|
inline |
Issue 0278 (Half B) — send a request and block up to timeout_ms for the reply WITHOUT spinning the executor, so this is safe to call from inside a subscription/timer callback (where call()/Future::wait would return Reentrant, issue 0290). It sends then sleep-polls the reply queue.
CONSTRAINT: usable from a callback only on a MULTI-THREADED backend (zenoh MT, cyclonedds), where the backend's own read task delivers the reply into the client's queue while this loop yields. On a single-threaded / polled backend the reply can only arrive via spin_once — which the callback is blocking — so it will TIME OUT; use call() from the main loop there. Keep timeout_ms SHORT (tens of ms): this blocks the executor's dispatch thread for its duration.
| req | Request to send. |
| resp | Output response struct (filled on success). |
| timeout_ms | Maximum wait (default 100ms). |
|
inline |
call_polling with the REPLY buffer sized by the caller (issue 0964). The request buffer stays on the estimate: it is transmit scratch, where an over-estimate only wastes stack.
|
inline |
call with the REPLY buffer sized by the caller (issue 0964).
|
inline |
Executor handle for the callback-style client (Phase 189.M3.3.f); SIZE_MAX for future-style / uninitialized.
|
inline |
Check if the client is initialized and valid.
|
inline |
|
inline |
Send a request and return a Future for the response (non-blocking).
Call wait() on the returned future to block until the response arrives, or poll with is_ready() / try_take().
| req | Request to send. |
|
inline |
send_request with the REPLY buffer sized by the caller.
The receive buffer of a Future<T> is a member, so the capacity is a class template argument rather than a function one: this returns a Future<ResponseType, RespCap> (issue 0964). The request buffer is a transmit scratch buffer and is deliberately left on the estimate – over-sizing there only wastes stack.
| RespCap | Stack bytes the returned future holds for the reply. |
|
inline |
phase-379 W6 — preserved exactly: 1 ready, 0 not yet, -1 cannot answer. It cannot distinguish a failed call from an unsupported backend, which is why it is replaced rather than kept.
|
inline |
Phase 124.C.3 — graph-aware "is the matching server up?" probe.
Returns the count from the RMW backend's matched-server view:
1 — at least one matching server is currently visible.ok(false) — no matching server discovered yet.error(Unsupported) — backend cannot answer (e.g. XRCE without participant enumeration); caller must fall back to a timed wait_for_service or assume reachability.error(<code>) — the probe itself failed.Never spins the executor — synchronous, safe to call from inside callbacks. Mirrors rclcpp::ClientBase::service_is_ready but with a tri-state result instead of collapsing "don't know" and "no" into the same false.
|
inline |
phase-338 W8 — block until a matching service server is discoverable.
Mirrors rclcpp::ClientBase::wait_for_service. Prefer this over hand-rolling a retry loop around the first call() / send_request(): it waits for the actual condition instead of guessing an attempt count, and it re-probes, so a server that starts AFTER the wait begins is still seen (a single liveliness query samples the router's current token list and terminates).
Spins the executor cooperatively while probing, so do NOT call it from inside a callback — use the non-blocking server_available() there.
Returns ok when the server is visible, Timeout when the budget elapses.
|
friend |