ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
timer.hpp
1 // Copyright 2014 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 #ifndef RCLCPP__TIMER_HPP_
16 #define RCLCPP__TIMER_HPP_
17 
18 #include <atomic>
19 #include <chrono>
20 #include <functional>
21 #include <memory>
22 #include <sstream>
23 #include <thread>
24 #include <type_traits>
25 #include <utility>
26 
27 #include "rclcpp/clock.hpp"
28 #include "rclcpp/context.hpp"
29 #include "rclcpp/function_traits.hpp"
30 #include "rclcpp/macros.hpp"
31 #include "rclcpp/rate.hpp"
32 #include "rclcpp/utilities.hpp"
33 #include "rclcpp/visibility_control.hpp"
34 #include "tracetools/tracetools.h"
35 #include "tracetools/utils.hpp"
36 
37 #include "rcl/error_handling.h"
38 #include "rcl/timer.h"
39 
40 #include "rmw/error_handling.h"
41 #include "rmw/rmw.h"
42 
43 namespace rclcpp
44 {
45 
46 class TimerBase
47 {
48 public:
49  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(TimerBase)
50 
51 
57  RCLCPP_PUBLIC
58  explicit TimerBase(
59  Clock::SharedPtr clock,
60  std::chrono::nanoseconds period,
61  rclcpp::Context::SharedPtr context);
62 
64  RCLCPP_PUBLIC
65  virtual
66  ~TimerBase();
67 
69 
72  RCLCPP_PUBLIC
73  void
74  cancel();
75 
77 
82  RCLCPP_PUBLIC
83  bool
84  is_canceled();
85 
87 
90  RCLCPP_PUBLIC
91  void
92  reset();
93 
95 
101  RCLCPP_PUBLIC
102  virtual bool
103  call() = 0;
104 
106  RCLCPP_PUBLIC
107  virtual void
109 
110  RCLCPP_PUBLIC
111  std::shared_ptr<const rcl_timer_t>
112  get_timer_handle();
113 
115 
120  RCLCPP_PUBLIC
121  std::chrono::nanoseconds
123 
125 
126  virtual bool is_steady() = 0;
127 
129 
135  RCLCPP_PUBLIC
136  bool is_ready();
137 
139 
148  RCLCPP_PUBLIC
149  bool
150  exchange_in_use_by_wait_set_state(bool in_use_state);
151 
152 protected:
153  Clock::SharedPtr clock_;
154  std::shared_ptr<rcl_timer_t> timer_handle_;
155 
156  std::atomic<bool> in_use_by_wait_set_{false};
157 };
158 
159 
160 using VoidCallbackType = std::function<void ()>;
161 using TimerCallbackType = std::function<void (TimerBase &)>;
162 
164 template<
165  typename FunctorT,
166  typename std::enable_if<
169  >::type * = nullptr
170 >
171 class GenericTimer : public TimerBase
172 {
173 public:
174  RCLCPP_SMART_PTR_DEFINITIONS(GenericTimer)
175 
176 
183  explicit GenericTimer(
184  Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback,
185  rclcpp::Context::SharedPtr context
186  )
187  : TimerBase(clock, period, context), callback_(std::forward<FunctorT>(callback))
188  {
189  TRACEPOINT(
190  rclcpp_timer_callback_added,
191  static_cast<const void *>(get_timer_handle().get()),
192  static_cast<const void *>(&callback_));
193  TRACEPOINT(
194  rclcpp_callback_register,
195  static_cast<const void *>(&callback_),
196  tracetools::get_symbol(callback_));
197  }
198 
200  virtual ~GenericTimer()
201  {
202  // Stop the timer from running.
203  cancel();
204  }
205 
210  bool
211  call() override
212  {
213  rcl_ret_t ret = rcl_timer_call(timer_handle_.get());
214  if (ret == RCL_RET_TIMER_CANCELED) {
215  return false;
216  }
217  if (ret != RCL_RET_OK) {
218  throw std::runtime_error("Failed to notify timer that callback occurred");
219  }
220  return true;
221  }
222 
226  void
227  execute_callback() override
228  {
229  TRACEPOINT(callback_start, static_cast<const void *>(&callback_), false);
230  execute_callback_delegate<>();
231  TRACEPOINT(callback_end, static_cast<const void *>(&callback_));
232  }
233 
234  // void specialization
235  template<
236  typename CallbackT = FunctorT,
237  typename std::enable_if<
239  >::type * = nullptr
240  >
241  void
242  execute_callback_delegate()
243  {
244  callback_();
245  }
246 
247  template<
248  typename CallbackT = FunctorT,
249  typename std::enable_if<
251  >::type * = nullptr
252  >
253  void
254  execute_callback_delegate()
255  {
256  callback_(*this);
257  }
258 
260 
261  bool
262  is_steady() override
263  {
264  return clock_->get_clock_type() == RCL_STEADY_TIME;
265  }
266 
267 protected:
268  RCLCPP_DISABLE_COPY(GenericTimer)
269 
270  FunctorT callback_;
271 };
272 
273 template<
274  typename FunctorT,
275  typename std::enable_if<
278  >::type * = nullptr
279 >
280 class WallTimer : public GenericTimer<FunctorT>
281 {
282 public:
283  RCLCPP_SMART_PTR_DEFINITIONS(WallTimer)
284 
285 
292  std::chrono::nanoseconds period,
293  FunctorT && callback,
294  rclcpp::Context::SharedPtr context)
295  : GenericTimer<FunctorT>(
296  std::make_shared<Clock>(RCL_STEADY_TIME), period, std::move(callback), context)
297  {}
298 
299 protected:
300  RCLCPP_DISABLE_COPY(WallTimer)
301 };
302 
303 } // namespace rclcpp
304 
305 #endif // RCLCPP__TIMER_HPP_
Context which encapsulates shared state between nodes and other similar entities.
Definition: context.hpp:73
Generic timer. Periodically executes a user-specified callback.
Definition: timer.hpp:172
bool is_steady() override
Is the clock steady (i.e. is the time between ticks constant?)
Definition: timer.hpp:262
virtual ~GenericTimer()
Default destructor.
Definition: timer.hpp:200
void execute_callback() override
Definition: timer.hpp:227
bool call() override
Definition: timer.hpp:211
virtual RCLCPP_PUBLIC ~TimerBase()
TimerBase destructor.
Definition: timer.cpp:73
RCLCPP_PUBLIC bool is_canceled()
Return the timer cancellation state.
Definition: timer.cpp:86
RCLCPP_PUBLIC void reset()
Reset the timer.
Definition: timer.cpp:97
virtual RCLCPP_PUBLIC bool call()=0
Indicate that we're about to execute the callback.
RCLCPP_PUBLIC TimerBase(Clock::SharedPtr clock, std::chrono::nanoseconds period, rclcpp::Context::SharedPtr context)
TimerBase constructor.
Definition: timer.cpp:29
RCLCPP_PUBLIC bool exchange_in_use_by_wait_set_state(bool in_use_state)
Exchange the "in use by wait set" state for this timer.
Definition: timer.cpp:137
virtual bool is_steady()=0
Is the clock steady (i.e. is the time between ticks constant?)
RCLCPP_PUBLIC bool is_ready()
Check if the timer is ready to trigger the callback.
Definition: timer.cpp:106
virtual RCLCPP_PUBLIC void execute_callback()=0
Call the callback function when the timer signal is emitted.
RCLCPP_PUBLIC std::chrono::nanoseconds time_until_trigger()
Check how long the timer has until its next scheduled callback.
Definition: timer.cpp:117
RCLCPP_PUBLIC void cancel()
Cancel the timer.
Definition: timer.cpp:77
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
@ RCL_STEADY_TIME
Use a steady clock time.
Definition: time.h:70
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_call(rcl_timer_t *timer)
Call the timer's callback and set the last call time.
Definition: timer.c:243
#define RCL_RET_OK
Success return code.
Definition: types.h:26
#define RCL_RET_TIMER_CANCELED
Given timer was canceled return code.
Definition: types.h:92
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:23