4 #include <rclcpp/client.hpp> 5 #include <rclcpp/serialized_message.hpp> 6 #include <rclcpp/typesupport_helpers.hpp> 7 #include <rosidl_typesupport_introspection_cpp/field_types.hpp> 8 #include <rosidl_typesupport_introspection_cpp/service_introspection.hpp> 15 static std::tuple<std::string, std::string, std::string> extract_type_identifier(
16 const std::string& full_type) {
17 char type_separator =
'/';
18 auto sep_position_back = full_type.find_last_of(type_separator);
19 auto sep_position_front = full_type.find_first_of(type_separator);
20 if (sep_position_back == std::string::npos || sep_position_back == 0 ||
21 sep_position_back == full_type.length() - 1) {
22 throw std::runtime_error(
23 "Message type is not of the form package/type and cannot be processed");
26 std::string package_name = full_type.substr(0, sep_position_front);
27 std::string middle_module =
"";
28 if (sep_position_back - sep_position_front > 0) {
30 full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1);
32 std::string type_name = full_type.substr(sep_position_back + 1);
34 return std::make_tuple(package_name, middle_module, type_name);
42 using rosidl_typesupport_introspection_cpp::MessageMembers;
43 using rosidl_typesupport_introspection_cpp::ServiceMembers;
46 void* buffer = malloc(members->size_of_);
47 if (buffer ==
nullptr) {
48 throw std::runtime_error(
"Failed to allocate memory");
50 memset(buffer, 0, members->size_of_);
51 members->init_function(buffer, rosidl_runtime_cpp::MessageInitialization::ALL);
52 return std::shared_ptr<void>(buffer, free);
56 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
58 return std::string(TYPESUPPORT_INTROSPECTION_LIB_NAME) +
"__get_service_type_support_handle__" +
59 pkgName +
"__" + (middleModule.empty() ?
"srv" : middleModule) +
"__" + typeName;
81 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
82 const auto lengthPrefixedString = [](
const std::string&
s) {
83 return std::to_string(
s.size()) +
s;
86 return "_ZN" + lengthPrefixedString(TYPESUPPORT_LIB_NAME) +
87 lengthPrefixedString(
"get_service_type_support_handle") +
"IN" +
88 lengthPrefixedString(pkgName) +
89 lengthPrefixedString(middleModule.empty() ?
"srv" : middleModule) +
90 lengthPrefixedString(typeName) +
"EEEPK" +
91 lengthPrefixedString(
"rosidl_service_type_support_t") +
"v";
95 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr nodeGraph,
96 std::string serviceName, std::string serviceType,
97 rcl_client_options_t& client_options)
98 : rclcpp::ClientBase(nodeBase, nodeGraph) {
99 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
100 const auto requestTypeName = serviceType +
"_Request";
101 const auto responseTypeName = serviceType +
"_Response";
103 _typeSupportLib = rclcpp::get_typesupport_library(serviceType, TYPESUPPORT_LIB_NAME);
105 rclcpp::get_typesupport_library(serviceType, TYPESUPPORT_INTROSPECTION_LIB_NAME);
107 throw std::runtime_error(
"Failed to load shared library for service type " + serviceType);
112 throw std::runtime_error(
"Failed to find symbol '" + typesupportSymbolName +
"' in " +
116 const rosidl_service_type_support_t* (*get_ts)() =
nullptr;
118 (
reinterpret_cast<decltype(get_ts)
>(
_typeSupportLib->get_symbol(typesupportSymbolName)))();
127 rclcpp::get_typesupport_handle(requestTypeName, TYPESUPPORT_LIB_NAME, *
_typeSupportLib);
129 rclcpp::get_typesupport_handle(responseTypeName, TYPESUPPORT_LIB_NAME, *
_typeSupportLib);
131 rcl_ret_t ret = rcl_client_init(this->get_client_handle().
get(), this->get_rcl_node_handle(),
132 _serviceTypeSupportHdl, serviceName.c_str(), &client_options);
133 if (ret != RCL_RET_OK) {
134 if (ret == RCL_RET_SERVICE_NAME_INVALID) {
135 auto rcl_node_handle = this->get_rcl_node_handle();
138 rclcpp::expand_topic_or_service_name(serviceName, rcl_node_get_name(rcl_node_handle),
139 rcl_node_get_namespace(rcl_node_handle),
true);
141 rclcpp::exceptions::throw_from_rcl_error(ret,
"could not create client");
151 return std::shared_ptr<rmw_request_id_t>(
new rmw_request_id_t);
155 std::shared_ptr<void> response) {
157 int64_t sequence_number = request_header->sequence_number;
159 auto ser_response = std::make_shared<rclcpp::SerializedMessage>();
161 &ser_response->get_rcl_serialized_message());
162 if (r != RMW_RET_OK) {
163 RCUTILS_LOG_ERROR_NAMED(
"foxglove_bridge",
"Failed to serialize service response. Ignoring...");
169 RCUTILS_LOG_ERROR_NAMED(
"foxglove_bridge",
"Received invalid sequence number. Ignoring...");
173 auto call_promise = std::get<0>(tuple);
174 auto callback = std::get<1>(tuple);
175 auto future = std::get<2>(tuple);
180 call_promise->set_value(ser_response);
191 int64_t sequence_number;
196 const rmw_serialized_message_t* sm = &request->get_rcl_serialized_message();
198 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to desirialize request");
200 rcl_ret_t ret = rcl_send_request(get_client_handle().
get(), buf.get(), &sequence_number);
201 if (RCL_RET_OK != ret) {
202 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to send request");
208 std::make_tuple(call_promise, std::forward<CallbackType>(cb),
f);
std::string getServiceTypeSupportHandleSymbolName(const std::string &serviceType)
std::string getTypeIntrospectionSymbolName(const std::string &serviceType)
const rosidl_service_type_support_t * _serviceTypeSupportHdl
std::shared_future< SharedResponse > SharedFuture
std::mutex pending_requests_mutex_
const rosidl_message_type_support_t * _responseTypeSupportHdl
std::function< void(SharedFuture)> CallbackType
void handle_response(std::shared_ptr< rmw_request_id_t > request_header, std::shared_ptr< void > response) override
std::shared_ptr< void > create_response() override
constexpr char TYPESUPPORT_LIB_NAME[]
const rosidl_service_type_support_t * _typeIntrospectionHdl
std::shared_ptr< rclcpp::SerializedMessage > SharedRequest
SharedFuture async_send_request(SharedRequest request)
std::shared_ptr< void > allocate_message(const MessageMembers *members)
GenericClient(rclcpp::node_interfaces::NodeBaseInterface *node_base, rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph, std::string service_name, std::string service_type, rcl_client_options_t &client_options)
std::shared_ptr< rcpputils::SharedLibrary > _typeSupportLib
std::map< int64_t, std::tuple< SharedPromise, CallbackType, SharedFuture > > pending_requests_
std::shared_ptr< rmw_request_id_t > create_request_header() override
const rosidl_message_type_support_t * _requestTypeSupportHdl
std::shared_ptr< rcpputils::SharedLibrary > _typeIntrospectionLib
std::shared_ptr< Promise > SharedPromise
constexpr char TYPESUPPORT_INTROSPECTION_LIB_NAME[]