ROS 2 rclcpp + rcl - kilted  kilted
ROS 2 C++ Client Library with ROS Client Library
rate.cpp
1 // Copyright 2023 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/rate.hpp"
16 
17 #include <chrono>
18 #include <stdexcept>
19 
20 namespace rclcpp
21 {
22 
23 Rate::Rate(
24  const double rate, Clock::SharedPtr clock)
25 : clock_(clock), period_(0, 0), last_interval_(clock_->now())
26 {
27  if (rate <= 0.0) {
28  throw std::invalid_argument{"rate must be greater than 0"};
29  }
30  period_ = Duration::from_seconds(1.0 / rate);
31 }
32 
33 Rate::Rate(
34  const Duration & period, Clock::SharedPtr clock)
35 : clock_(clock), period_(period), last_interval_(clock_->now())
36 {
37  if (period <= Duration(0, 0)) {
38  throw std::invalid_argument{"period must be greater than 0"};
39  }
40 }
41 
42 bool
43 Rate::sleep()
44 {
45  // Time coming into sleep
46  auto now = clock_->now();
47  // Time of next interval
48  auto next_interval = last_interval_ + period_;
49  // Detect backwards time flow
50  if (now < last_interval_) {
51  // Best thing to do is to set the next_interval to now + period
52  next_interval = now + period_;
53  }
54  // Update the interval
55  last_interval_ += period_;
56  // If the time_to_sleep is negative or zero, don't sleep
57  if (next_interval <= now) {
58  // If an entire cycle was missed then reset next interval.
59  // This might happen if the loop took more than a cycle.
60  // Or if time jumps forward.
61  if (now > next_interval + period_) {
62  last_interval_ = now + period_;
63  }
64  // Either way do not sleep and return false
65  return false;
66  }
67  // Calculate the time to sleep
68  auto time_to_sleep = next_interval - now;
69  // Sleep (will get interrupted by ctrl-c, may not sleep full time)
70  clock_->sleep_for(time_to_sleep);
71  return true;
72 }
73 
75 Rate::get_type() const
76 {
77  return clock_->get_clock_type();
78 }
79 
80 void
81 Rate::reset()
82 {
83  last_interval_ = clock_->now();
84 }
85 
86 std::chrono::nanoseconds
87 Rate::period() const
88 {
89  return std::chrono::nanoseconds(period_.nanoseconds());
90 }
91 
92 WallRate::WallRate(const double rate)
93 : Rate(rate, std::make_shared<Clock>(RCL_STEADY_TIME))
94 {}
95 
96 WallRate::WallRate(const Duration & period)
97 : Rate(period, std::make_shared<Clock>(RCL_STEADY_TIME))
98 {}
99 
100 } // namespace rclcpp
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
enum rcl_clock_type_e rcl_clock_type_t
Time source type, used to indicate the source of a time measurement.
@ RCL_STEADY_TIME
Use a steady clock time.
Definition: time.h:70