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)
35 service_type,
"rosidl_typesupport_cpp");
38 service_type,
"rosidl_typesupport_cpp", *ts_lib_);
41 service_ts_->response_typesupport,
42 rosidl_typesupport_introspection_cpp::typesupport_identifier);
43 response_members_ =
static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *
>(
44 response_type_support_intro->data);
47 this->get_client_handle().get(),
48 this->get_rcl_node_handle(),
54 auto rcl_node_handle = this->get_rcl_node_handle();
63 rclcpp::exceptions::throw_from_rcl_error(ret,
"could not create generic client");
68 GenericClient::create_response()
70 void * response =
new uint8_t[response_members_->size_of_];
71 response_members_->init_function(response, rosidl_runtime_cpp::MessageInitialization::ZERO);
72 return std::shared_ptr<void>(
76 response_members_->fini_function(p);
77 delete[]
reinterpret_cast<uint8_t *
>(p);
81 std::shared_ptr<rmw_request_id_t>
82 GenericClient::create_request_header()
86 return std::shared_ptr<rmw_request_id_t>(
new rmw_request_id_t);
90 GenericClient::handle_response(
91 std::shared_ptr<rmw_request_id_t> request_header,
92 std::shared_ptr<void> response)
94 auto optional_pending_request =
95 this->get_and_erase_pending_request(request_header->sequence_number);
96 if (!optional_pending_request) {
99 auto & value = *optional_pending_request;
100 if (std::holds_alternative<Promise>(value)) {
101 auto & promise = std::get<Promise>(value);
102 promise.set_value(std::move(response));
107 GenericClient::prune_pending_requests()
109 std::lock_guard guard(pending_requests_mutex_);
110 auto ret = pending_requests_.size();
111 pending_requests_.clear();
116 GenericClient::remove_pending_request(int64_t request_id)
118 std::lock_guard guard(pending_requests_mutex_);
119 return pending_requests_.erase(request_id) != 0u;
122 std::optional<GenericClient::CallbackInfoVariant>
123 GenericClient::get_and_erase_pending_request(int64_t request_number)
125 std::unique_lock<std::mutex> lock(pending_requests_mutex_);
126 auto it = pending_requests_.find(request_number);
127 if (it == pending_requests_.end()) {
128 RCUTILS_LOG_DEBUG_NAMED(
130 "Received invalid sequence number. Ignoring...");
133 auto value = std::move(it->second.second);
134 pending_requests_.erase(request_number);
138 GenericClient::FutureAndRequestId
139 GenericClient::async_send_request(
const Request request)
142 auto future = promise.get_future();
143 auto req_id = async_send_request_impl(
150 GenericClient::async_send_request_impl(
const Request request, CallbackInfoVariant value)
152 int64_t sequence_number;
153 std::lock_guard<std::mutex> lock(pending_requests_mutex_);
156 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to send request");
158 pending_requests_.try_emplace(
160 std::make_pair(std::chrono::system_clock::now(), std::move(value)));
161 return sequence_number;
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 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.
#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.