ROS 2 rclcpp + rcl - lyrical  lyrical
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 <optional>
22 #include <memory>
23 #include <sstream>
24 #include <thread>
25 #include <type_traits>
26 #include <utility>
27 
28 #include "rclcpp/clock.hpp"
29 #include "rclcpp/context.hpp"
30 #include "rclcpp/function_traits.hpp"
31 #include "rclcpp/macros.hpp"
32 #include "rclcpp/rate.hpp"
33 #include "rclcpp/utilities.hpp"
34 #include "rclcpp/visibility_control.hpp"
35 #include "tracetools/tracetools.h"
36 #include "tracetools/utils.hpp"
37 
38 #include "rcl/error_handling.h"
39 #include "rcl/timer.h"
40 
41 #include "rmw/error_handling.h"
42 #include "rmw/rmw.h"
43 
44 namespace rclcpp
45 {
46 
47 struct TimerInfo
48 {
49  Time expected_call_time;
50  Time actual_call_time;
51 };
52 
53 class TimerBase
54 {
55 public:
56  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(TimerBase)
57 
58 
68  RCLCPP_PUBLIC
69  explicit TimerBase(
70  Clock::SharedPtr clock,
71  std::chrono::nanoseconds period,
72  rclcpp::Context::SharedPtr context,
73  bool autostart = true);
74 
76  RCLCPP_PUBLIC
77  virtual
78  ~TimerBase();
79 
81 
84  RCLCPP_PUBLIC
85  void
86  cancel();
87 
89 
94  RCLCPP_PUBLIC
95  bool
96  is_canceled();
97 
99 
102  RCLCPP_PUBLIC
103  void
104  reset();
105 
107 
114  RCLCPP_PUBLIC
115  virtual std::shared_ptr<void>
116  call() = 0;
117 
119 
122  RCLCPP_PUBLIC
123  virtual void
124  execute_callback(const std::shared_ptr<void> & data) = 0;
125 
126  RCLCPP_PUBLIC
127  std::shared_ptr<const rcl_timer_t>
128  get_timer_handle();
129 
131 
136  RCLCPP_PUBLIC
137  std::chrono::nanoseconds
139 
141 
142  virtual bool is_steady() = 0;
143 
145 
151  RCLCPP_PUBLIC
152  bool is_ready();
153 
155 
164  RCLCPP_PUBLIC
165  bool
166  exchange_in_use_by_wait_set_state(bool in_use_state);
167 
169 
184  RCLCPP_PUBLIC
185  void
186  set_on_reset_callback(const std::function<void(size_t)> & callback);
187 
189  RCLCPP_PUBLIC
190  void
192 
194  RCLCPP_PUBLIC
195  const Clock::SharedPtr & get_clock() const;
196 
197 protected:
198  std::recursive_mutex callback_mutex_;
199  // Declare callback before timer_handle_, so on destruction
200  // the callback is destroyed last. Otherwise, the rcl timer
201  // callback would point briefly to a destroyed function.
202  // Clearing the callback on timer destructor also makes sure
203  // the rcl callback is cleared before on_reset_callback_.
204  std::function<void(size_t)> on_reset_callback_{nullptr};
205 
206  Clock::SharedPtr clock_;
207  std::shared_ptr<rcl_timer_t> timer_handle_;
208 
209  std::atomic<bool> in_use_by_wait_set_{false};
210 
211  RCLCPP_PUBLIC
212  void
213  set_on_reset_callback(rcl_event_callback_t callback, const void * user_data);
214 };
215 
216 using VoidCallbackType = std::function<void ()>;
217 using TimerCallbackType = std::function<void (TimerBase &)>;
218 using TimerInfoCallbackType = std::function<void (const TimerInfo &)>;
219 
221 template<
222  typename FunctorT,
223  typename std::enable_if<
227  >::type * = nullptr
228 >
229 class GenericTimer : public TimerBase
230 {
231 public:
232  RCLCPP_SMART_PTR_DEFINITIONS(GenericTimer)
233 
234 
242  explicit GenericTimer(
243  Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback,
244  rclcpp::Context::SharedPtr context, bool autostart = true
245  )
246  : TimerBase(clock, period, context, autostart), callback_(std::forward<FunctorT>(callback))
247  {
248  TRACETOOLS_TRACEPOINT(
249  rclcpp_timer_callback_added,
250  static_cast<const void *>(get_timer_handle().get()),
251  reinterpret_cast<const void *>(&callback_));
252 #ifndef TRACETOOLS_DISABLED
253  if (TRACETOOLS_TRACEPOINT_ENABLED(rclcpp_callback_register)) {
254  char * symbol = tracetools::get_symbol(callback_);
255  TRACETOOLS_DO_TRACEPOINT(
256  rclcpp_callback_register,
257  reinterpret_cast<const void *>(&callback_),
258  symbol);
259  std::free(symbol);
260  }
261 #endif
262  }
263 
265  virtual ~GenericTimer()
266  {
267  // Stop the timer from running.
268  cancel();
269  }
270 
275  std::shared_ptr<void>
276  call() override
277  {
278  auto timer_call_info_ = std::make_shared<rcl_timer_call_info_t>();
279  rcl_ret_t ret = rcl_timer_call_with_info(timer_handle_.get(), timer_call_info_.get());
280  if (ret == RCL_RET_TIMER_CANCELED) {
281  return nullptr;
282  }
283  if (ret != RCL_RET_OK) {
284  throw std::runtime_error("Failed to notify timer that callback occurred");
285  }
286  return timer_call_info_;
287  }
288 
292  void
293  execute_callback(const std::shared_ptr<void> & data) override
294  {
295  TRACETOOLS_TRACEPOINT(callback_start, reinterpret_cast<const void *>(&callback_), false);
296  execute_callback_delegate<>(*static_cast<rcl_timer_call_info_t *>(data.get()));
297  TRACETOOLS_TRACEPOINT(callback_end, reinterpret_cast<const void *>(&callback_));
298  }
299 
300  // void specialization
301  template<
302  typename CallbackT = FunctorT,
303  typename std::enable_if<
305  >::type * = nullptr
306  >
307  void
308  execute_callback_delegate(const rcl_timer_call_info_t &)
309  {
310  callback_();
311  }
312 
313  template<
314  typename CallbackT = FunctorT,
315  typename std::enable_if<
317  >::type * = nullptr
318  >
319  void
320  execute_callback_delegate(const rcl_timer_call_info_t &)
321  {
322  callback_(*this);
323  }
324 
325 
326  template<
327  typename CallbackT = FunctorT,
328  typename std::enable_if<
330  >::type * = nullptr
331  >
332  void
333  execute_callback_delegate(const rcl_timer_call_info_t & timer_call_info)
334  {
335  const TimerInfo info{Time{timer_call_info.expected_call_time, clock_->get_clock_type()},
336  Time{timer_call_info.actual_call_time, clock_->get_clock_type()}};
337  callback_(info);
338  }
339 
341 
342  bool
343  is_steady() override
344  {
345  return clock_->get_clock_type() == RCL_STEADY_TIME;
346  }
347 
348 protected:
349  RCLCPP_DISABLE_COPY(GenericTimer)
350 
351  FunctorT callback_;
352 };
353 
354 template<
355  typename FunctorT,
356  typename std::enable_if<
360  >::type * = nullptr
361 >
362 class WallTimer : public GenericTimer<FunctorT>
363 {
364 public:
365  RCLCPP_SMART_PTR_DEFINITIONS(WallTimer)
366 
367 
375  std::chrono::nanoseconds period,
376  FunctorT && callback,
377  rclcpp::Context::SharedPtr context,
378  bool autostart = true)
379  : GenericTimer<FunctorT>(
380  std::make_shared<Clock>(RCL_STEADY_TIME), period, std::move(callback), context, autostart)
381  {}
382 
383 protected:
384  RCLCPP_DISABLE_COPY(WallTimer)
385 };
386 
387 } // namespace rclcpp
388 
389 #endif // RCLCPP__TIMER_HPP_
Context which encapsulates shared state between nodes and other similar entities.
Definition: context.hpp:80
Generic timer. Periodically executes a user-specified callback.
Definition: timer.hpp:230
bool is_steady() override
Is the clock steady (i.e. is the time between ticks constant?)
Definition: timer.hpp:343
void execute_callback(const std::shared_ptr< void > &data) override
Definition: timer.hpp:293
virtual ~GenericTimer()
Default destructor.
Definition: timer.hpp:265
std::shared_ptr< void > call() override
Definition: timer.hpp:276
virtual RCLCPP_PUBLIC ~TimerBase()
TimerBase destructor.
Definition: timer.cpp:77
RCLCPP_PUBLIC const Clock::SharedPtr & get_clock() const
Returns the clock this timer uses.
Definition: timer.cpp:221
RCLCPP_PUBLIC void set_on_reset_callback(const std::function< void(size_t)> &callback)
Set a callback to be called when the timer is reset.
Definition: timer.cpp:153
RCLCPP_PUBLIC bool is_canceled()
Return the timer cancellation state.
Definition: timer.cpp:92
RCLCPP_PUBLIC void reset()
Reset the timer.
Definition: timer.cpp:103
RCLCPP_PUBLIC void clear_on_reset_callback()
Unset the callback registered for reset timer.
Definition: timer.cpp:202
virtual RCLCPP_PUBLIC void execute_callback(const std::shared_ptr< void > &data)=0
Call the callback function when the timer signal is emitted.
virtual RCLCPP_PUBLIC std::shared_ptr< void > call()=0
Indicate that we're about to execute the callback.
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:147
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:116
RCLCPP_PUBLIC TimerBase(Clock::SharedPtr clock, std::chrono::nanoseconds period, rclcpp::Context::SharedPtr context, bool autostart=true)
TimerBase constructor.
Definition: timer.cpp:32
RCLCPP_PUBLIC std::chrono::nanoseconds time_until_trigger()
Check how long the timer has until its next scheduled callback.
Definition: timer.cpp:127
RCLCPP_PUBLIC void cancel()
Cancel the timer.
Definition: timer.cpp:83
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
Structure which encapsulates timer information when called.
Definition: timer.h:56
@ RCL_STEADY_TIME
Use a steady clock time.
Definition: time.h:70
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_call_with_info(rcl_timer_t *timer, rcl_timer_call_info_t *call_info)
Same as rcl_timer_call() except that it also retrieves the actual and expected call time.
Definition: timer.c:245
#define RCL_RET_OK
Success return code.
Definition: types.h:27
#define RCL_RET_TIMER_CANCELED
Given timer was canceled return code.
Definition: types.h:95
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24