ROS 2 rclcpp + rcl - rolling  rolling-6c35dd21
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 <sstream>
17 #include <string>
18 #include <thread>
19 
20 #include "rclcpp/node_interfaces/node_type_descriptions.hpp"
21 #include "rclcpp/parameter_client.hpp"
22 
23 #include "type_description_interfaces/srv/get_type_description.h"
24 
25 namespace
26 {
27 // Helper wrapper for rclcpp::Service to access ::Request and ::Response types for allocation.
28 struct GetTypeDescription__C
29 {
30  using Request = type_description_interfaces__srv__GetTypeDescription_Request;
31  using Response = type_description_interfaces__srv__GetTypeDescription_Response;
32  using Event = type_description_interfaces__srv__GetTypeDescription_Event;
33 };
34 } // namespace
35 
36 // Helper function for C typesupport.
37 namespace rosidl_typesupport_cpp
38 {
39 template<>
40 rosidl_service_type_support_t const *
41 get_service_type_support_handle<GetTypeDescription__C>()
42 {
43  return ROSIDL_GET_SRV_TYPE_SUPPORT(type_description_interfaces, srv, GetTypeDescription);
44 }
45 } // namespace rosidl_typesupport_cpp
46 
47 namespace rclcpp
48 {
49 namespace node_interfaces
50 {
51 
53 {
54 public:
55  using ServiceT = GetTypeDescription__C;
56 
57  rclcpp::Logger logger_;
58  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
59  rclcpp::Service<ServiceT>::SharedPtr type_description_srv_;
60 
62  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
63  const rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr & node_logging,
64  const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr & node_parameters,
65  const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr & node_services)
66  : logger_(node_logging->get_logger()),
67  node_base_(std::move(node_base))
68  {
69  rclcpp::ParameterValue enable_param;
70  const std::string enable_param_name = "start_type_description_service";
71 
72  if (!node_parameters->has_parameter(enable_param_name)) {
73  enable_param = node_parameters->declare_parameter(
74  enable_param_name,
76  rcl_interfaces::msg::ParameterDescriptor()
77  .set__name(enable_param_name)
78  .set__type(rclcpp::PARAMETER_BOOL)
79  .set__description("Start the ~/get_type_description service for this node.")
80  .set__read_only(true));
81  } else {
82  enable_param = node_parameters->get_parameter(enable_param_name).get_parameter_value();
83  }
84  if (enable_param.get_type() != rclcpp::PARAMETER_BOOL) {
85  RCLCPP_ERROR(
86  logger_,
87  "Invalid type '%s' for parameter 'start_type_description_service', should be 'bool'",
88  rclcpp::to_string(enable_param.get_type()).c_str());
89  std::ostringstream ss;
90  ss << "Wrong parameter type, parameter {" << enable_param_name << "} is of type {bool}, "
91  << "setting it to {" << to_string(enable_param.get_type()) << "} is not allowed.";
92  throw rclcpp::exceptions::InvalidParameterTypeException(enable_param_name, ss.str());
93  }
94 
95  if (enable_param.get<bool>()) {
96  auto * rcl_node = node_base_->get_rcl_node_handle();
97  std::shared_ptr<rcl_service_t> rcl_srv(
98  new rcl_service_t,
99  [rcl_node, logger = this->logger_](rcl_service_t * service)
100  {
101  if (rcl_service_fini(service, rcl_node) != RCL_RET_OK) {
102  RCLCPP_ERROR(
103  logger,
104  "Error in destruction of rcl service handle [~/get_type_description]: %s",
105  rcl_get_error_string().str);
106  rcl_reset_error();
107  }
108  delete service;
109  });
111  rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_srv.get(), rcl_node);
112 
113  if (rcl_ret != RCL_RET_OK) {
114  RCLCPP_ERROR(
115  logger_, "Failed to initialize ~/get_type_description service: %s",
116  rcl_get_error_string().str);
117  rcl_reset_error();
118  throw std::runtime_error(
119  "Failed to initialize ~/get_type_description service.");
120  }
121 
123  cb.set(
124  [this](
125  const std::shared_ptr<rmw_request_id_t> & header,
126  const std::shared_ptr<ServiceT::Request> & request,
127  const std::shared_ptr<ServiceT::Response> & response
128  ) {
130  node_base_->get_rcl_node_handle(),
131  header.get(),
132  request.get(),
133  response.get());
134  });
135 
136  type_description_srv_ = std::make_shared<Service<ServiceT>>(
137  node_base_->get_shared_rcl_node_handle(),
138  rcl_srv,
139  cb);
140  node_services->add_service(
141  std::dynamic_pointer_cast<ServiceBase>(type_description_srv_),
142  nullptr);
143  }
144  }
145 };
146 
147 NodeTypeDescriptions::NodeTypeDescriptions(
148  const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_base,
149  const rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr & node_logging,
150  const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr & node_parameters,
151  const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr & node_services)
152 : impl_(new NodeTypeDescriptionsImpl(
153  node_base,
154  node_logging,
155  node_parameters,
156  node_services))
157 {}
158 
159 NodeTypeDescriptions::~NodeTypeDescriptions()
160 {}
161 
162 } // namespace node_interfaces
163 } // 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:587
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:521
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:225
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:45
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