ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
rate.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__RATE_HPP_
16 #define RCLCPP__RATE_HPP_
17 
18 #include <chrono>
19 #include <memory>
20 #include <thread>
21 
22 #include "rclcpp/clock.hpp"
23 #include "rclcpp/duration.hpp"
24 #include "rclcpp/macros.hpp"
25 #include "rclcpp/utilities.hpp"
26 #include "rclcpp/visibility_control.hpp"
27 
28 namespace rclcpp
29 {
30 
31 class RateBase
32 {
33 public:
34  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(RateBase)
35 
36  RCLCPP_PUBLIC
37  virtual ~RateBase() {}
38 
39  RCLCPP_PUBLIC
40  virtual bool sleep() = 0;
41 
42  [[deprecated("use get_type() instead")]]
43  RCLCPP_PUBLIC
44  virtual bool is_steady() const = 0;
45 
46  RCLCPP_PUBLIC
47  virtual rcl_clock_type_t get_type() const = 0;
48 
49  RCLCPP_PUBLIC
50  virtual void reset() = 0;
51 };
52 
53 using std::chrono::duration;
54 using std::chrono::duration_cast;
55 using std::chrono::nanoseconds;
56 
57 template<class Clock = std::chrono::high_resolution_clock>
58 class [[deprecated("use rclcpp::Rate class instead of GenericRate")]] GenericRate : public RateBase
59 {
60 public:
61  RCLCPP_SMART_PTR_DEFINITIONS(GenericRate)
62 
63  explicit GenericRate(double rate)
64  : period_(duration_cast<nanoseconds>(duration<double>(1.0 / rate))), last_interval_(Clock::now())
65  {}
66  explicit GenericRate(std::chrono::nanoseconds period)
67  : period_(period), last_interval_(Clock::now())
68  {}
69 
70  virtual bool
71  sleep()
72  {
73  // Time coming into sleep
74  auto now = Clock::now();
75  // Time of next interval
76  auto next_interval = last_interval_ + period_;
77  // Detect backwards time flow
78  if (now < last_interval_) {
79  // Best thing to do is to set the next_interval to now + period
80  next_interval = now + period_;
81  }
82  // Calculate the time to sleep
83  auto time_to_sleep = next_interval - now;
84  // Update the interval
85  last_interval_ += period_;
86  // If the time_to_sleep is negative or zero, don't sleep
87  if (time_to_sleep <= std::chrono::seconds(0)) {
88  // If an entire cycle was missed then reset next interval.
89  // This might happen if the loop took more than a cycle.
90  // Or if time jumps forward.
91  if (now > next_interval + period_) {
92  last_interval_ = now + period_;
93  }
94  // Either way do not sleep and return false
95  return false;
96  }
97  // Sleep (will get interrupted by ctrl-c, may not sleep full time)
98  rclcpp::sleep_for(time_to_sleep);
99  return true;
100  }
101 
102  [[deprecated("use get_type() instead")]]
103  virtual bool
104  is_steady() const
105  {
106  return Clock::is_steady;
107  }
108 
109  virtual rcl_clock_type_t get_type() const
110  {
111  return Clock::is_steady ? RCL_STEADY_TIME : RCL_SYSTEM_TIME;
112  }
113 
114  virtual void
115  reset()
116  {
117  last_interval_ = Clock::now();
118  }
119 
120  std::chrono::nanoseconds period() const
121  {
122  return period_;
123  }
124 
125 private:
126  RCLCPP_DISABLE_COPY(GenericRate)
127 
128  std::chrono::nanoseconds period_;
129  using ClockDurationNano = std::chrono::duration<typename Clock::rep, std::nano>;
130  std::chrono::time_point<Clock, ClockDurationNano> last_interval_;
131 };
132 
133 class Rate : public RateBase
134 {
135 public:
136  RCLCPP_SMART_PTR_DEFINITIONS(Rate)
137 
138  RCLCPP_PUBLIC
139  explicit Rate(
140  const double rate,
141  Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
142 
143  RCLCPP_PUBLIC
144  explicit Rate(
145  const Duration & period,
146  Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
147 
148  RCLCPP_PUBLIC
149  virtual bool
150  sleep();
151 
152  [[deprecated("use get_type() instead")]]
153  RCLCPP_PUBLIC
154  virtual bool
155  is_steady() const;
156 
157  RCLCPP_PUBLIC
158  virtual rcl_clock_type_t
159  get_type() const;
160 
161  RCLCPP_PUBLIC
162  virtual void
163  reset();
164 
165  RCLCPP_PUBLIC
166  std::chrono::nanoseconds
167  period() const;
168 
169 private:
170  RCLCPP_DISABLE_COPY(Rate)
171 
172  Clock::SharedPtr clock_;
173  Duration period_;
174  Time last_interval_;
175 };
176 
177 class WallRate : public Rate
178 {
179 public:
180  RCLCPP_PUBLIC
181  explicit WallRate(const double rate);
182 
183  RCLCPP_PUBLIC
184  explicit WallRate(const Duration & period);
185 };
186 
187 } // namespace rclcpp
188 
189 #endif // RCLCPP__RATE_HPP_
RCLCPP_PUBLIC Time now() const
Definition: clock.cpp:74
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
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.
enum rcl_clock_type_e rcl_clock_type_t
Time source type, used to indicate the source of a time measurement.
@ RCL_SYSTEM_TIME
Use system time.
Definition: time.h:68
@ RCL_STEADY_TIME
Use a steady clock time.
Definition: time.h:70