Entities#
All the ROS entities (subscriptions, publishers, timers etc.) are wrapped so that they are either Stream
s or provide an asynchronous interface with icey::Promise
(service client, TF).
-
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 paremeter 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
Message
orstd::shared_ptr<Message>
whereMessage
must be something publishable, i.e. either a valid ROS message or a masqueraded type.
Public Types
-
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(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.
-
RequestID call(Request request, const Duration &timeout, std::function<void(Response)> on_response, std::function<void(const std::string&)> on_error)#
Make an asynchronous call to the service with a timeout. Two callbacks may be provided: One for the response and one in case of error (timeout or service unavailable). 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.
- Parameters:
request – the request.
timeout – The timeout for the service call, both for service discovery and the actual call.
- Returns:
The request id using which this request can be cancelled.
-
impl::Promise<Response, std::string> call(Request request, const Duration &timeout)#
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(NodeBase &node, const std::string &service_name, const rclcpp::QoS &qos = rclcpp::ServicesQoS())#
-
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 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_request
if 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#
-
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#