4 #include <rclcpp/client.hpp>
5 #include <rclcpp/serialized_message.hpp>
6 #include <rclcpp/typesupport_helpers.hpp>
7 #include <rclcpp/version.h>
8 #include <rosidl_typesupport_introspection_cpp/field_types.hpp>
9 #include <rosidl_typesupport_introspection_cpp/service_introspection.hpp>
16 static std::tuple<std::string, std::string, std::string> extract_type_identifier(
17 const std::string& full_type) {
18 char type_separator =
'/';
19 auto sep_position_back = full_type.find_last_of(type_separator);
20 auto sep_position_front = full_type.find_first_of(type_separator);
21 if (sep_position_back == std::string::npos || sep_position_back == 0 ||
22 sep_position_back == full_type.length() - 1) {
23 throw std::runtime_error(
24 "Message type is not of the form package/type and cannot be processed");
27 std::string package_name = full_type.substr(0, sep_position_front);
28 std::string middle_module =
"";
29 if (sep_position_back - sep_position_front > 0) {
31 full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1);
33 std::string type_name = full_type.substr(sep_position_back + 1);
35 return std::make_tuple(package_name, middle_module, type_name);
43 using rosidl_typesupport_introspection_cpp::MessageMembers;
44 using rosidl_typesupport_introspection_cpp::ServiceMembers;
47 void* buffer = malloc(members->size_of_);
48 if (buffer ==
nullptr) {
49 throw std::runtime_error(
"Failed to allocate memory");
51 memset(buffer, 0, members->size_of_);
52 members->init_function(buffer, rosidl_runtime_cpp::MessageInitialization::ALL);
53 return std::shared_ptr<void>(buffer, free);
57 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
60 pkgName +
"__" + (middleModule.empty() ?
"srv" : middleModule) +
"__" + typeName;
82 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
83 const auto lengthPrefixedString = [](
const std::string&
s) {
84 return std::to_string(
s.size()) +
s;
88 lengthPrefixedString(
"get_service_type_support_handle") +
"IN" +
89 lengthPrefixedString(pkgName) +
90 lengthPrefixedString(middleModule.empty() ?
"srv" : middleModule) +
91 lengthPrefixedString(typeName) +
"EEEPK" +
92 lengthPrefixedString(
"rosidl_service_type_support_t") +
"v";
96 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr nodeGraph,
97 std::string serviceName, std::string serviceType,
98 rcl_client_options_t& client_options)
99 : rclcpp::ClientBase(nodeBase, nodeGraph) {
100 const auto [pkgName, middleModule, typeName] = extract_type_identifier(serviceType);
101 const auto requestTypeName = serviceType +
"_Request";
102 const auto responseTypeName = serviceType +
"_Response";
108 throw std::runtime_error(
"Failed to load shared library for service type " + serviceType);
113 throw std::runtime_error(
"Failed to find symbol '" + typesupportSymbolName +
"' in " +
117 const rosidl_service_type_support_t* (*get_ts)() =
nullptr;
119 (
reinterpret_cast<decltype(get_ts)
>(
_typeSupportLib->get_symbol(typesupportSymbolName)))();
129 #if RCLCPP_VERSION_GTE(25, 0, 0)
141 rcl_ret_t ret = rcl_client_init(this->get_client_handle().
get(), this->get_rcl_node_handle(),
143 if (ret != RCL_RET_OK) {
144 if (ret == RCL_RET_SERVICE_NAME_INVALID) {
145 auto rcl_node_handle = this->get_rcl_node_handle();
148 rclcpp::expand_topic_or_service_name(serviceName, rcl_node_get_name(rcl_node_handle),
149 rcl_node_get_namespace(rcl_node_handle),
true);
151 rclcpp::exceptions::throw_from_rcl_error(ret,
"could not create client");
161 return std::shared_ptr<rmw_request_id_t>(
new rmw_request_id_t);
165 std::shared_ptr<void> response) {
167 int64_t sequence_number = request_header->sequence_number;
169 auto ser_response = std::make_shared<rclcpp::SerializedMessage>();
171 &ser_response->get_rcl_serialized_message());
172 if (r != RMW_RET_OK) {
173 RCUTILS_LOG_ERROR_NAMED(
"foxglove_bridge",
"Failed to serialize service response. Ignoring...");
179 RCUTILS_LOG_ERROR_NAMED(
"foxglove_bridge",
"Received invalid sequence number. Ignoring...");
183 auto call_promise = std::get<0>(tuple);
184 auto callback = std::get<1>(tuple);
185 auto future = std::get<2>(tuple);
190 call_promise->set_value(ser_response);
201 int64_t sequence_number;
206 const rmw_serialized_message_t* sm = &request->get_rcl_serialized_message();
208 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to desirialize request");
210 rcl_ret_t ret = rcl_send_request(get_client_handle().
get(), buf.get(), &sequence_number);
211 if (RCL_RET_OK != ret) {
212 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to send request");
218 std::make_tuple(call_promise, std::forward<CallbackType>(cb),
f);