17 #include "rclcpp/generic_client.hpp"
18 #include "rclcpp/typesupport_helpers.hpp"
20 #include "rosidl_runtime_c/service_type_support_struct.h"
21 #include "rosidl_typesupport_introspection_cpp/identifier.hpp"
22 #include "rosidl_typesupport_introspection_cpp/service_introspection.hpp"
26 GenericClient::GenericClient(
28 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
29 const std::string & service_name,
30 const std::string & service_type,
32 : ClientBase(node_base, node_graph)
34 const rosidl_service_type_support_t * service_ts;
37 service_type,
"rosidl_typesupport_cpp");
40 service_type,
"rosidl_typesupport_cpp", *ts_lib_);
43 service_ts->response_typesupport,
44 rosidl_typesupport_introspection_cpp::typesupport_identifier);
45 response_members_ =
static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *
>(
46 response_type_support_intro->data);
47 }
catch (std::runtime_error & err) {
50 "Invalid service type: %s",
56 this->get_client_handle().get(),
57 this->get_rcl_node_handle(),
63 auto rcl_node_handle = this->get_rcl_node_handle();
72 rclcpp::exceptions::throw_from_rcl_error(ret,
"could not create generic client");
77 GenericClient::create_response()
79 void * response =
new uint8_t[response_members_->size_of_];
80 response_members_->init_function(response, rosidl_runtime_cpp::MessageInitialization::ZERO);
81 return std::shared_ptr<void>(
85 response_members_->fini_function(p);
86 delete[]
reinterpret_cast<uint8_t *
>(p);
90 std::shared_ptr<rmw_request_id_t>
91 GenericClient::create_request_header()
95 return std::shared_ptr<rmw_request_id_t>(
new rmw_request_id_t);
99 GenericClient::handle_response(
100 std::shared_ptr<rmw_request_id_t> request_header,
101 std::shared_ptr<void> response)
103 auto optional_pending_request =
104 this->get_and_erase_pending_request(request_header->sequence_number);
105 if (!optional_pending_request) {
108 auto & value = *optional_pending_request;
109 if (std::holds_alternative<Promise>(value)) {
110 auto & promise = std::get<Promise>(value);
111 promise.set_value(std::move(response));
112 }
else if (std::holds_alternative<CallbackTypeValueVariant>(value)) {
113 auto & inner = std::get<CallbackTypeValueVariant>(value);
114 const auto & callback = std::get<CallbackType>(inner);
115 auto & promise = std::get<Promise>(inner);
116 auto & future = std::get<SharedFuture>(inner);
117 promise.set_value(std::move(response));
118 callback(std::move(future));
123 GenericClient::prune_pending_requests()
125 std::lock_guard guard(pending_requests_mutex_);
126 auto ret = pending_requests_.size();
127 pending_requests_.clear();
132 GenericClient::remove_pending_request(int64_t request_id)
134 std::lock_guard guard(pending_requests_mutex_);
135 return pending_requests_.erase(request_id) != 0u;
141 return this->remove_pending_request(future.request_id);
147 return this->remove_pending_request(future.request_id);
150 std::optional<GenericClient::CallbackInfoVariant>
151 GenericClient::get_and_erase_pending_request(int64_t request_number)
153 std::unique_lock<std::mutex> lock(pending_requests_mutex_);
154 auto it = pending_requests_.find(request_number);
155 if (it == pending_requests_.end()) {
156 RCUTILS_LOG_DEBUG_NAMED(
158 "Received invalid sequence number. Ignoring...");
161 auto value = std::move(it->second.second);
162 pending_requests_.erase(request_number);
166 GenericClient::FutureAndRequestId
167 GenericClient::async_send_request(
const Request request)
170 auto future = promise.get_future();
171 auto req_id = async_send_request_impl(
178 GenericClient::async_send_request_impl(
const Request request, CallbackInfoVariant value)
180 int64_t sequence_number;
181 std::lock_guard<std::mutex> lock(pending_requests_mutex_);
184 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to send request");
186 pending_requests_.try_emplace(
188 std::make_pair(std::chrono::system_clock::now(), std::move(value)));
189 return sequence_number;
RCLCPP_PUBLIC Logger get_child(const std::string &suffix)
Return a logger that is a descendant of this logger.
Pure virtual interface class for the NodeBase part of the Node API.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_client_init(rcl_client_t *client, const rcl_node_t *node, const rosidl_service_type_support_t *type_support, const char *service_name, const rcl_client_options_t *options)
Initialize a rcl client.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_send_request(const rcl_client_t *client, const void *ros_request, int64_t *sequence_number)
Send a ROS request using a client.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC std::string expand_topic_or_service_name(const std::string &name, const std::string &node_name, const std::string &namespace_, bool is_service=false)
Expand a topic or service name and throw if it is not valid.
RCLCPP_PUBLIC Logger get_node_logger(const rcl_node_t *node)
Return a named logger using an rcl_node_t.
RCLCPP_PUBLIC std::shared_ptr< rcpputils::SharedLibrary > get_typesupport_library(const std::string &type, const std::string &typesupport_identifier)
Load the type support library for the given type.
RCLCPP_PUBLIC const rosidl_message_type_support_t * get_message_typesupport_handle(const std::string &type, const std::string &typesupport_identifier, rcpputils::SharedLibrary &library)
Extracts the message type support handle from the library.
RCLCPP_PUBLIC const rosidl_service_type_support_t * get_service_typesupport_handle(const std::string &type, const std::string &typesupport_identifier, rcpputils::SharedLibrary &library)
Extracts the service type support handle from the library.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_name(const rcl_node_t *node)
Return the name of the node.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_namespace(const rcl_node_t *node)
Return the namespace of the node.
Options available for a rcl_client_t.
A convenient GenericClient::Future and request id pair.
A convenient GenericClient::SharedFuture and request id pair.
#define RCL_RET_SERVICE_NAME_INVALID
Service name (same as topic name) does not pass validation.
#define RCL_RET_OK
Success return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.