ROS 2 rclcpp + rcl - kilted  kilted
ROS 2 C++ Client Library with ROS Client Library
node_type_descriptions.cpp
1 // Copyright 2023 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <memory>
16 #include <string>
17 #include <thread>
18 
19 #include "rclcpp/node_interfaces/node_type_descriptions.hpp"
20 #include "rclcpp/parameter_client.hpp"
21 
22 #include "type_description_interfaces/srv/get_type_description.h"
23 
24 namespace
25 {
26 // Helper wrapper for rclcpp::Service to access ::Request and ::Response types for allocation.
27 struct GetTypeDescription__C
28 {
29  using Request = type_description_interfaces__srv__GetTypeDescription_Request;
30  using Response = type_description_interfaces__srv__GetTypeDescription_Response;
31  using Event = type_description_interfaces__srv__GetTypeDescription_Event;
32 };
33 } // namespace
34 
35 // Helper function for C typesupport.
36 namespace rosidl_typesupport_cpp
37 {
38 template<>
39 rosidl_service_type_support_t const *
40 get_service_type_support_handle<GetTypeDescription__C>()
41 {
42  return ROSIDL_GET_SRV_TYPE_SUPPORT(type_description_interfaces, srv, GetTypeDescription);
43 }
44 } // namespace rosidl_typesupport_cpp
45 
46 namespace rclcpp
47 {
48 namespace node_interfaces
49 {
50 
52 {
53 public:
54  using ServiceT = GetTypeDescription__C;
55 
56  rclcpp::Logger logger_;
57  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
58  rclcpp::Service<ServiceT>::SharedPtr type_description_srv_;
59 
61  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
62  rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
63  rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
64  rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services)
65  : logger_(node_logging->get_logger()),
66  node_base_(node_base)
67  {
68  rclcpp::ParameterValue enable_param;
69  const std::string enable_param_name = "start_type_description_service";
70 
71  if (!node_parameters->has_parameter(enable_param_name)) {
72  enable_param = node_parameters->declare_parameter(
73  enable_param_name,
75  rcl_interfaces::msg::ParameterDescriptor()
76  .set__name(enable_param_name)
77  .set__type(rclcpp::PARAMETER_BOOL)
78  .set__description("Start the ~/get_type_description service for this node.")
79  .set__read_only(true));
80  } else {
81  enable_param = node_parameters->get_parameter(enable_param_name).get_parameter_value();
82  }
83  if (enable_param.get_type() != rclcpp::PARAMETER_BOOL) {
84  RCLCPP_ERROR(
85  logger_,
86  "Invalid type '%s' for parameter 'start_type_description_service', should be 'bool'",
87  rclcpp::to_string(enable_param.get_type()).c_str());
88  std::ostringstream ss;
89  ss << "Wrong parameter type, parameter {" << enable_param_name << "} is of type {bool}, "
90  << "setting it to {" << to_string(enable_param.get_type()) << "} is not allowed.";
91  throw rclcpp::exceptions::InvalidParameterTypeException(enable_param_name, ss.str());
92  }
93 
94  if (enable_param.get<bool>()) {
95  auto * rcl_node = node_base->get_rcl_node_handle();
96  std::shared_ptr<rcl_service_t> rcl_srv(
97  new rcl_service_t,
98  [rcl_node, logger = this->logger_](rcl_service_t * service)
99  {
100  if (rcl_service_fini(service, rcl_node) != RCL_RET_OK) {
101  RCLCPP_ERROR(
102  logger,
103  "Error in destruction of rcl service handle [~/get_type_description]: %s",
104  rcl_get_error_string().str);
105  rcl_reset_error();
106  }
107  delete service;
108  });
110  rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_srv.get(), rcl_node);
111 
112  if (rcl_ret != RCL_RET_OK) {
113  RCLCPP_ERROR(
114  logger_, "Failed to initialize ~/get_type_description service: %s",
115  rcl_get_error_string().str);
116  rcl_reset_error();
117  throw std::runtime_error(
118  "Failed to initialize ~/get_type_description service.");
119  }
120 
122  cb.set(
123  [this](
124  std::shared_ptr<rmw_request_id_t> header,
125  std::shared_ptr<ServiceT::Request> request,
126  std::shared_ptr<ServiceT::Response> response
127  ) {
129  node_base_->get_rcl_node_handle(),
130  header.get(),
131  request.get(),
132  response.get());
133  });
134 
135  type_description_srv_ = std::make_shared<Service<ServiceT>>(
136  node_base_->get_shared_rcl_node_handle(),
137  rcl_srv,
138  cb);
139  node_services->add_service(
140  std::dynamic_pointer_cast<ServiceBase>(type_description_srv_),
141  nullptr);
142  }
143  }
144 };
145 
146 NodeTypeDescriptions::NodeTypeDescriptions(
147  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
148  rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
149  rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
150  rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services)
151 : impl_(new NodeTypeDescriptionsImpl(
152  node_base,
153  node_logging,
154  node_parameters,
155  node_services))
156 {}
157 
158 NodeTypeDescriptions::~NodeTypeDescriptions()
159 {}
160 
161 } // namespace node_interfaces
162 } // namespace rclcpp
Store the type and value of a parameter.
RCLCPP_PUBLIC ParameterType get_type() const
Return an enum indicating the type of the set value.
Thrown if requested parameter type is invalid.
Definition: exceptions.hpp:271
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC std::string to_string(const FutureReturnCode &future_return_code)
String conversion function for FutureReturnCode.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_type_description_service_init(rcl_service_t *service, const rcl_node_t *node)
Initialize the node's ~/get_type_description service.
Definition: node.c:579
RCL_PUBLIC void rcl_node_type_description_service_handle_request(rcl_node_t *node, const rmw_request_id_t *request_header, const type_description_interfaces__srv__GetTypeDescription_Request *request, type_description_interfaces__srv__GetTypeDescription_Response *response)
Process a single pending request to the GetTypeDescription service.
Definition: node.c:513
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_fini(rcl_service_t *service, rcl_node_t *node)
Finalize a rcl_service_t.
Definition: service.c:234
RCL_PUBLIC RCL_WARN_UNUSED rcl_service_t rcl_get_zero_initialized_service(void)
Return a rcl_service_t struct with members set to NULL.
Definition: service.c:55
Structure which encapsulates a ROS Service.
Definition: service.h:43
#define RCL_RET_OK
Success return code.
Definition: types.h:27
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24