ROS 2 rclcpp + rcl - rolling  rolling-a919a6e5
ROS 2 C++ Client Library with ROS Client Library
utilities.cpp
1 // Copyright 2015 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 "rclcpp/utilities.hpp"
16 
17 #include <chrono>
18 #include <functional>
19 #include <string>
20 #include <vector>
21 
22 #include "./signal_handler.hpp"
23 #include "rclcpp/contexts/default_context.hpp"
24 #include "rclcpp/detail/utilities.hpp"
25 #include "rclcpp/exceptions.hpp"
26 
27 #include "rcl/error_handling.h"
28 #include "rcl/rcl.h"
29 
30 namespace rclcpp
31 {
32 
33 void
35  int argc,
36  char const * const * argv,
37  const InitOptions & init_options,
38  SignalHandlerOptions signal_handler_options)
39 {
40  using rclcpp::contexts::get_global_default_context;
41  get_global_default_context()->init(argc, argv, init_options);
42  // Install the signal handlers.
43  install_signal_handlers(signal_handler_options);
44 }
45 
46 bool
48 {
49  return SignalHandler::get_global_signal_handler().install(signal_handler_options);
50 }
51 
52 bool
54 {
56 }
57 
60 {
62 }
63 
64 
65 bool
67 {
69 }
70 
71 static
72 std::vector<std::string>
73 _remove_ros_arguments(
74  char const * const * argv,
75  const rcl_arguments_t * args,
76  rcl_allocator_t alloc)
77 {
78  rcl_ret_t ret;
79  int nonros_argc = 0;
80  const char ** nonros_argv = NULL;
81 
83  argv,
84  args,
85  alloc,
86  &nonros_argc,
87  &nonros_argv);
88 
89  if (RCL_RET_OK != ret || nonros_argc < 0) {
90  // Not using throw_from_rcl_error, because we may need to append deallocation failures.
91  exceptions::RCLError exc(ret, rcl_get_error_state(), "");
92  rcl_reset_error();
93  if (NULL != nonros_argv) {
94  alloc.deallocate(nonros_argv, alloc.state);
95  }
96  throw exc;
97  }
98 
99  std::vector<std::string> return_arguments(static_cast<size_t>(nonros_argc));
100 
101  for (size_t ii = 0; ii < static_cast<size_t>(nonros_argc); ++ii) {
102  return_arguments[ii] = std::string(nonros_argv[ii]);
103  }
104 
105  if (NULL != nonros_argv) {
106  alloc.deallocate(nonros_argv, alloc.state);
107  }
108 
109  return return_arguments;
110 }
111 
112 std::vector<std::string>
114  int argc,
115  char const * const * argv,
116  const InitOptions & init_options)
117 {
118  init(argc, argv, init_options);
119 
120  using rclcpp::contexts::get_global_default_context;
121  auto rcl_context = get_global_default_context()->get_rcl_context();
122  return _remove_ros_arguments(argv, &(rcl_context->global_arguments), rcl_get_default_allocator());
123 }
124 
125 std::vector<std::string>
126 remove_ros_arguments(int argc, char const * const * argv)
127 {
130 
131  rcl_ret_t ret;
132 
133  ret = rcl_parse_arguments(argc, argv, alloc, &parsed_args);
134  if (RCL_RET_OK != ret) {
135  exceptions::throw_from_rcl_error(ret, "failed to parse arguments");
136  }
137 
138  std::vector<std::string> return_arguments;
139  try {
140  return_arguments = _remove_ros_arguments(argv, &parsed_args, alloc);
141  } catch (exceptions::RCLError & exc) {
142  if (RCL_RET_OK != rcl_arguments_fini(&parsed_args)) {
143  exc.formatted_message += std::string(
144  ", failed also to cleanup parsed arguments, leaking memory: ") +
145  rcl_get_error_string().str;
146  rcl_reset_error();
147  }
148  throw exc;
149  }
150 
151  ret = rcl_arguments_fini(&parsed_args);
152  if (RCL_RET_OK != ret) {
153  exceptions::throw_from_rcl_error(
154  ret, "failed to cleanup parsed arguments, leaking memory");
155  }
156 
157  return return_arguments;
158 }
159 
160 bool
161 ok(Context::SharedPtr context)
162 {
163  using rclcpp::contexts::get_global_default_context;
164  if (nullptr == context) {
165  context = get_global_default_context();
166  }
167  return context->is_valid();
168 }
169 
170 bool
171 shutdown(Context::SharedPtr context, const std::string & reason)
172 {
173  using rclcpp::contexts::get_global_default_context;
174  auto default_context = get_global_default_context();
175  if (nullptr == context) {
176  context = default_context;
177  }
178  bool ret = context->shutdown(reason);
179  if (context == default_context) {
181  }
182  return ret;
183 }
184 
185 void
186 on_shutdown(std::function<void()> callback, Context::SharedPtr context)
187 {
188  using rclcpp::contexts::get_global_default_context;
189  if (nullptr == context) {
190  context = get_global_default_context();
191  }
192  context->on_shutdown(callback);
193 }
194 
195 bool
196 sleep_for(const std::chrono::nanoseconds & nanoseconds, Context::SharedPtr context)
197 {
198  using rclcpp::contexts::get_global_default_context;
199  if (nullptr == context) {
200  context = get_global_default_context();
201  }
202  return context->sleep_for(nanoseconds);
203 }
204 
205 const char *
206 get_c_string(const char * string_in)
207 {
208  return string_in;
209 }
210 
211 const char *
212 get_c_string(const std::string & string_in)
213 {
214  return string_in.c_str();
215 }
216 
217 std::vector<const char *>
218 get_c_vector_string(const std::vector<std::string> & strings_in)
219 {
220  std::vector<const char *> cstrings;
221  cstrings.reserve(strings_in.size());
222 
223  for (size_t i = 0; i < strings_in.size(); ++i) {
224  cstrings.push_back(strings_in[i].c_str());
225  }
226 
227  return cstrings;
228 }
229 
230 } // namespace rclcpp
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
Definition: allocator.h:37
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_parse_arguments(int argc, const char *const *argv, rcl_allocator_t allocator, rcl_arguments_t *args_output)
Parse command line arguments into a structure usable by code.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_arguments_fini(rcl_arguments_t *args)
Reclaim resources held inside rcl_arguments_t structure.
RCL_PUBLIC RCL_WARN_UNUSED rcl_arguments_t rcl_get_zero_initialized_arguments(void)
Return a rcl_arguments_t struct with members initialized to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_remove_ros_arguments(const char *const *argv, const rcl_arguments_t *args, rcl_allocator_t allocator, int *nonros_argc, const char ***nonros_argv)
Return a list of arguments with ROS-specific arguments removed.
Encapsulation of options for initializing rclcpp.
bool is_installed()
Return true if installed, false otherwise.
static SignalHandler & get_global_signal_handler()
Return the global singleton of this class.
bool install(SignalHandlerOptions signal_handler_options=SignalHandlerOptions::All)
Install the signal handler for SIGINT/SIGTERM and start the dedicated signal handling thread.
rclcpp::SignalHandlerOptions get_current_signal_handler_options()
Get the current signal handler options.
Created when the return code does not match one of the other specialized exceptions.
Definition: exceptions.hpp:162
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC void init(int argc, char const *const *argv, const InitOptions &init_options=InitOptions(), SignalHandlerOptions signal_handler_options=SignalHandlerOptions::All)
Initialize communications via the rmw implementation and set up a global signal handler.
Definition: utilities.cpp:34
SignalHandlerOptions
Option to indicate which signal handlers rclcpp should install.
Definition: utilities.hpp:48
RCLCPP_PUBLIC bool signal_handlers_installed()
Return true if the signal handlers are installed, otherwise false.
Definition: utilities.cpp:53
RCLCPP_PUBLIC void on_shutdown(std::function< void()> callback, rclcpp::Context::SharedPtr context=nullptr)
Register a function to be called when shutdown is called on the context.
RCLCPP_PUBLIC bool sleep_for(const std::chrono::nanoseconds &nanoseconds, rclcpp::Context::SharedPtr context=nullptr)
Use the global condition variable to block for the specified amount of time.
RCLCPP_PUBLIC std::vector< std::string > remove_ros_arguments(int argc, char const *const *argv)
Remove ROS-specific arguments from argument vector.
Definition: utilities.cpp:126
RCLCPP_PUBLIC std::vector< std::string > init_and_remove_ros_arguments(int argc, char const *const *argv, const InitOptions &init_options=InitOptions())
Initialize communications via the rmw implementation and set up a global signal handler.
Definition: utilities.cpp:113
RCLCPP_PUBLIC std::vector< const char * > get_c_vector_string(const std::vector< std::string > &strings_in)
Return the std::vector of C string from the given std::vector<std::string>.
Definition: utilities.cpp:218
RCLCPP_PUBLIC bool install_signal_handlers(SignalHandlerOptions signal_handler_options=SignalHandlerOptions::All)
Install the global signal handler for rclcpp.
Definition: utilities.cpp:47
RCLCPP_PUBLIC bool shutdown(rclcpp::Context::SharedPtr context=nullptr, const std::string &reason="user called rclcpp::shutdown()")
Shutdown rclcpp context, invalidating it for derived entities.
RCLCPP_PUBLIC const char * get_c_string(const char *string_in)
Return the given string.
Definition: utilities.cpp:206
RCLCPP_PUBLIC bool ok(rclcpp::Context::SharedPtr context=nullptr)
Check rclcpp's status.
RCLCPP_PUBLIC SignalHandlerOptions get_current_signal_handler_options()
Get the current signal handler options.
Definition: utilities.cpp:59
RCLCPP_PUBLIC bool uninstall_signal_handlers()
Uninstall the global signal handler for rclcpp.
Definition: utilities.cpp:66
Hold output of parsing command line arguments.
Definition: arguments.h:36
#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