Entities#
All the ROS entities (subscriptions, publishers, timers etc.) are wrapped so that they are either Streams or provide an asynchronous interface with icey::Promise (service client, TF).
-
template<class ServiceT>
struct ServiceClient# A service client offering an async/await API and per-request timeouts. Service calls happen asynchronously and return a promise that can be awaited using co_await. This allows synchronization with other operations, enabling you to effectively perform synchronous service calls. We do not offer a function to wait until the service is available for two reasons: (1) there is no asynchronous function available at the rclcpp layer (re-implementation using asynchronous graph change notification would be required), and (2) ROS does not seem to optimize RPC calls by keeping connections open; therefore, it does not seem beneficial to differentiate whether the server is available or not.
Public Types
Public Functions
-
ServiceClient(std::weak_ptr<NodeBase> node, const std::string &service_name, const rclcpp::QoS &qos = rclcpp::ServicesQoS())#
Constructs the service client. A node has to be provided because it is needed to create timeout timers for every service call.
-
impl::Promise<Response, std::string> call(Request request, const Duration &timeout) const#
Make an asynchronous call to the service. Returns a impl::Promise that can be awaited using
co_await. Requests can never hang forever but will eventually time out. Also you don’t need to clean up pending requests — they will be cleaned up automatically. So this function will never cause any memory leaks.
Example usage:
auto client = node->icey().create_client<ExampleService>("set_bool_service1"); auto request = std::make_shared<ExampleService::Request>(); icey::Result<ExampleService::Response::SharedPtr, std::string> result = co_await client.call(request, 1s);
- Parameters:
request – the request
timeout – The timeout for the service call, both for service discovery and the actual call.
- Returns:
A promise that can be awaited to obtain the response or an error. Possible errors are “TIMEOUT”, “SERVICE_UNAVAILABLE” or “INTERRUPTED”.
-
ServiceClient(std::weak_ptr<NodeBase> node, const std::string &service_name, const rclcpp::QoS &qos = rclcpp::ServicesQoS())#
-
struct TransformBuffer#
A TransformBuffer offers a modern, asynchronous interface for looking up transforms at a given point in time. This class is lightweight pointer to underlying implementation and can therefore be copied and passed around by value (PIMPL idiom)
Public Types
-
using RequestHandle = TransformBufferImpl::RequestHandle#
-
using OnTransform = std::function<void(const geometry_msgs::msg::TransformStamped&)>#
-
using OnError = std::function<void(const tf2::TransformException&)>#
Public Functions
-
TransformBuffer() = default#
-
RequestHandle lookup(const std::string &target_frame, const std::string &source_frame, Time time, const Duration &timeout, OnTransform on_transform, OnError on_error)#
Makes an asynchronous lookup for a for a transform at the given time between the given frames. Callback-based API.
Warning
Currently the timeout is measured with wall-time, i.e. does not consider sim-time due to the limitation of ROS 2 Humble only offering wall-timers
- Parameters:
target_frame –
source_frame –
time –
timeout –
on_transform – The callback that is called with the requested transform after it becomes available
on_error – The callback that is called if a timeout occurs.
- Returns:
The “handle”, identifying this request. You can use this handle to call
cancel_requestif you want to cancel the request.
-
bool cancel_request(RequestHandle request_handle)#
Cancel a transform request: This means that the registered callbacks will no longer be called. If the given request does not exist, this function does nothing, in this case it returns false. If a request was cleaned up, this function returns true.
-
impl::Promise<geometry_msgs::msg::TransformStamped, std::string> lookup(const std::string &target_frame, const std::string &source_frame, const Time &time, const Duration &timeout)#
Does an asynchronous lookup for a single transform that can be awaited using
co_await- Parameters:
target_frame –
source_frame –
time – At which time to get the transform
timeout – How long to wait for the transform
- Returns:
A future that resolves with the transform or with an error if a timeout occurs
-
impl::Promise<geometry_msgs::msg::TransformStamped, std::string> lookup(const std::string &target_frame, const std::string &source_frame, const rclcpp::Time &time, const Duration &timeout)#
Same as
lookup, but accepts a ROS time point.- Parameters:
target_frame –
source_frame –
time – At which time to get the transform
timeout – How long to wait for the transform
- Returns:
A future that resolves with the transform or with an error if a timeout occurs
-
using RequestHandle = TransformBufferImpl::RequestHandle#
-
template<class ActionT>
struct ActionClient# A action client offering an async/await API and per-request timeouts. Everything happens asynchronously and returns a promise that can be awaited using co_await.
Public Types
-
using FeedbackCallback = typename GoalHandle::FeedbackCallback#
-
using Result = typename GoalHandle::WrappedResult#
-
using RequestID = int64_t#
-
using AsyncGoalHandleT = AsyncGoalHandle<ActionT>#
Public Functions
-
using FeedbackCallback = typename GoalHandle::FeedbackCallback#
-
template<class ActionT>
struct AsyncGoalHandle# An AsyncGoalHandle is created once a requested goal was accepted by the action server. It provides an async/await based API for requesting the result and cancellation. WARNING: On Humble, there seems to be a memory leak bug in the underlying send_goal API.
Public Types
-
using Result = typename GoalHandle::WrappedResult#
Public Functions
-
const rclcpp_action::GoalUUID &get_goal_id() const#
Get the goal UUID.
-
rclcpp::Time get_goal_stamp() const#
Get the time when the goal was accepted.
-
int8_t get_status()#
Get the goal status code. See https://docs.ros.org/en/ros2_packages/rolling/api/action_msgs/msg/GoalStatus.html for possible values
-
ResultPromise result(const Duration &timeout) const#
Obtain the result asynchronously.
-
impl::Promise<CancelResponse, std::string> cancel(const Duration &timeout) const#
Cancel this goal. Warning: Not co_awaiting this promise leads to use-after free !
TODO check in gdb whether it is a problem that this promise might resolve synchronously, i.e. do we get a stack overflow ?
-
std::shared_ptr<GoalHandle> get_goal_handle() const#
Returns the held rclcpp_action::GoalHandle.
-
using Result = typename GoalHandle::WrappedResult#
-
template<class _Value>
struct ParameterStream : public icey::Stream<_Value># An stream representing parameters. It always registers the callback to obtain the parameter updates.
Public Functions
-
ParameterStream() = default#
-
ParameterStream(const Value &default_value, const Validator<Value> &validator = {}, std::string description = "", bool read_only = false, bool ignore_override = false)#
A constructor that should only be used for parameter structs. It does not set the name of the parameter and therefore leaves this ParameterStream in a not fully initialized state. Context::declare_parameter_struct later infers the name of this parameter from the name of the field in the parameter struct and sets it before registering the parameter with ROS.
- Parameters:
default_value –
validator – the validator implementing constraints
description – the description written in the ParameterDescriptor
read_only – if yes, the parameter cannot be modified
ignore_override –
-
ParameterStream(Context &context, const std::string ¶meter_name, const Value &default_value, const Validator<Value> &validator = {}, std::string description = "", bool read_only = false, bool ignore_override = false)#
The standard constructor used when declaring parameters with Context::declare_parameter.
- Parameters:
context – the ICEY context
parameter_name –
default_value –
validator – the validator implementing constraints
description –
read_only – if set to true, parameter updates will be rejected
ignore_override –
-
void register_with_ros(Context &context)#
Register this parameter with the ROS node, meaning it actually calls node->declare_parameter(). After calling this method, this ParameterStream will have a value.
Public Members
-
std::string parameter_name#
-
ParameterStream() = default#
-
template<class _Message>
struct SubscriptionStream : public icey::Stream<_Message::SharedPtr, Nothing, SubscriptionStreamImpl<_Message>># A stream that represents a regular ROS subscription. It stores as its value always a shared pointer to the message.
Public Types
-
struct TimerStream : public icey::Stream<size_t, Nothing, TimerImpl>#
A Stream representing a ROS-Timer. It saves the number of ticks as it’s value. TODO use this TimerInfo thingy, it actually exists in ROS 2 as well.
-
template<class _Value>
struct PublisherStream : public icey::Stream<_Value, Nothing, PublisherImpl<_Value>># A Stream representing a ROS-publisher.
- Template Parameters:
_Value – Can be either a
Messageorstd::shared_ptr<Message>whereMessagemust be something publishable, i.e. either a valid ROS message or a masqueraded type.
Public Types
-
struct TransformSubscriptionStream : public icey::Stream<geometry_msgs::msg::TransformStamped, std::string, TransformSubscriptionStreamImpl>#
A Stream that represents a subscription between two coordinate systems. (See TFListener) It yields a value each time the transform between these two coordinate systems changes.
Public Types
-
using Base = Stream<geometry_msgs::msg::TransformStamped, std::string, TransformSubscriptionStreamImpl>#
-
using Message = geometry_msgs::msg::TransformStamped#
-
using Self = TransformSubscriptionStream#
Public Functions
-
TransformSubscriptionStream() = default#
-
TransformSubscriptionStream(Context &context, ValueOrParameter<std::string> target_frame, ValueOrParameter<std::string> source_frame)#
-
using Base = Stream<geometry_msgs::msg::TransformStamped, std::string, TransformSubscriptionStreamImpl>#
-
struct TransformPublisherStream : public icey::Stream<geometry_msgs::msg::TransformStamped, Nothing, TransformPublisherStreamImpl>#
Public Types
-
using Value = geometry_msgs::msg::TransformStamped#
-
using Value = geometry_msgs::msg::TransformStamped#
Parameter validation#
Some extra classes related to parameters:
-
template<class Value>
struct Interval# What follows, is an improved parameters API. For API docs, see https://docs.ros.org/en/jazzy/p/rcl_interfaces First, some constraints we can impose on parameters: A closed interval, meaning a value must be greater or equal to a minimum value and less or equal to a maximum value.
-
template<class Value>
struct Set# A set specified by a given list of values that are in the set.
-
template<class Value>
struct Validator# A parameter validator, validating parameter updates. It is able to constrain parameter values. It is essentially a function that returns true if a value is allowed and false otherwise.
- Template Parameters:
Value – the parameter type (i.e. double)
Public Types
-
using Validate = std::function<std::string(const rclcpp::Parameter&)>#
The type of the validator predicate, meaning the function that returns an error if the parameter update is rejected and an empty string otherwise. Why we don’t return a std::optional<std::string> ? Because this way we can ensure through the type system that if a parameter update is rejected, it is always rejected for a reason.
-
template<class Value>
struct ValueOrParameter# A class that abstracts a plain value and a ParameterStream so that both are supported in promise mode. This is needed for example for timeouts and coordinate system names.
Public Functions
-
ValueOrParameter() = default#
-
ValueOrParameter(const Value &value)#
Construct a ValueOrParameter implicitly from a value.
-
template<class T>
ValueOrParameter(const T &v)# Construct a ValueOrParameter implicitly from a something similar to a value, For example,
"hello"is a const char[5] literal that is convertible to a std::string, the value.
-
ValueOrParameter(const ParameterStream<Value> ¶m)#
Construct a ValueOrParameter implicitly from parameter (i.e. ParameterStream)
-
ValueOrParameter() = default#