ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
timer.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/timer.hpp"
16 
17 #include <chrono>
18 #include <string>
19 #include <memory>
20 #include <thread>
21 
22 #include "rclcpp/contexts/default_context.hpp"
23 #include "rclcpp/exceptions.hpp"
24 
25 #include "rcutils/logging_macros.h"
26 
27 using rclcpp::TimerBase;
28 
29 TimerBase::TimerBase(
30  rclcpp::Clock::SharedPtr clock,
31  std::chrono::nanoseconds period,
32  rclcpp::Context::SharedPtr context)
33 : clock_(clock), timer_handle_(nullptr)
34 {
35  if (nullptr == context) {
36  context = rclcpp::contexts::get_global_default_context();
37  }
38 
39  auto rcl_context = context->get_rcl_context();
40 
41  timer_handle_ = std::shared_ptr<rcl_timer_t>(
42  new rcl_timer_t, [ = ](rcl_timer_t * timer) mutable
43  {
44  {
45  std::lock_guard<std::mutex> clock_guard(clock->get_clock_mutex());
46  if (rcl_timer_fini(timer) != RCL_RET_OK) {
47  RCUTILS_LOG_ERROR_NAMED(
48  "rclcpp",
49  "Failed to clean up rcl timer handle: %s", rcl_get_error_string().str);
50  rcl_reset_error();
51  }
52  }
53  delete timer;
54  // Captured shared pointers by copy, reset to make sure timer is finalized before clock
55  clock.reset();
56  rcl_context.reset();
57  });
58 
59  *timer_handle_.get() = rcl_get_zero_initialized_timer();
60 
61  rcl_clock_t * clock_handle = clock_->get_clock_handle();
62  {
63  std::lock_guard<std::mutex> clock_guard(clock_->get_clock_mutex());
65  timer_handle_.get(), clock_handle, rcl_context.get(), period.count(), nullptr,
67  if (ret != RCL_RET_OK) {
68  rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't initialize rcl timer handle");
69  }
70  }
71 }
72 
74 {}
75 
76 void
78 {
79  rcl_ret_t ret = rcl_timer_cancel(timer_handle_.get());
80  if (ret != RCL_RET_OK) {
81  rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't cancel timer");
82  }
83 }
84 
85 bool
87 {
88  bool is_canceled = false;
89  rcl_ret_t ret = rcl_timer_is_canceled(timer_handle_.get(), &is_canceled);
90  if (ret != RCL_RET_OK) {
91  rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't get timer cancelled state");
92  }
93  return is_canceled;
94 }
95 
96 void
98 {
99  rcl_ret_t ret = rcl_timer_reset(timer_handle_.get());
100  if (ret != RCL_RET_OK) {
101  rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't reset timer");
102  }
103 }
104 
105 bool
107 {
108  bool ready = false;
109  rcl_ret_t ret = rcl_timer_is_ready(timer_handle_.get(), &ready);
110  if (ret != RCL_RET_OK) {
111  rclcpp::exceptions::throw_from_rcl_error(ret, "Failed to check timer");
112  }
113  return ready;
114 }
115 
116 std::chrono::nanoseconds
118 {
119  int64_t time_until_next_call = 0;
121  timer_handle_.get(), &time_until_next_call);
122  if (ret == RCL_RET_TIMER_CANCELED) {
123  return std::chrono::nanoseconds::max();
124  } else if (ret != RCL_RET_OK) {
125  rclcpp::exceptions::throw_from_rcl_error(ret, "Timer could not get time until next call");
126  }
127  return std::chrono::nanoseconds(time_until_next_call);
128 }
129 
130 std::shared_ptr<const rcl_timer_t>
131 TimerBase::get_timer_handle()
132 {
133  return timer_handle_;
134 }
135 
136 bool
138 {
139  return in_use_by_wait_set_.exchange(in_use_state);
140 }
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
Definition: allocator.h:37
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
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
RCLCPP_PUBLIC bool is_ready()
Check if the timer is ready to trigger the callback.
Definition: timer.cpp:106
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
Encapsulation of a time source.
Definition: time.h:138
Structure which encapsulates a ROS Timer.
Definition: timer.h:39
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_get_time_until_next_call(const rcl_timer_t *timer, int64_t *time_until_next_call)
Calculate and retrieve the time until the next call in nanoseconds.
Definition: timer.c:313
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_init(rcl_timer_t *timer, rcl_clock_t *clock, rcl_context_t *context, int64_t period, const rcl_timer_callback_t callback, rcl_allocator_t allocator)
Initialize a timer.
Definition: timer.c:127
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_reset(rcl_timer_t *timer)
Reset a timer.
Definition: timer.c:416
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_cancel(rcl_timer_t *timer)
Cancel a timer.
Definition: timer.c:393
RCL_PUBLIC RCL_WARN_UNUSED rcl_timer_t rcl_get_zero_initialized_timer(void)
Return a zero initialized timer.
Definition: timer.c:56
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_fini(rcl_timer_t *timer)
Finalize a timer.
Definition: timer.c:204
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_is_canceled(const rcl_timer_t *timer, bool *is_canceled)
Retrieve the canceled state of a timer.
Definition: timer.c:406
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_is_ready(const rcl_timer_t *timer, bool *is_ready)
Calculates whether or not the timer should be called.
Definition: timer.c:295
#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