ROS 2 rclcpp + rcl - kilted  kilted
ROS 2 C++ Client Library with ROS Client Library
time.cpp
1 // Copyright 2017 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 <limits>
16 #include <string>
17 #include <utility>
18 
19 #include "rclcpp/clock.hpp"
20 #include "rclcpp/duration.hpp"
21 
22 #include "builtin_interfaces/msg/time.hpp"
23 
24 #include "rcl/time.h"
25 
26 #include "rclcpp/exceptions.hpp"
27 
28 #include "rcutils/logging_macros.h"
29 
30 #include "rclcpp/utilities.hpp"
31 
32 namespace
33 {
34 
36 init_time_point(rcl_clock_type_t & clock_type)
37 {
38  rcl_time_point_t time_point;
39  time_point.clock_type = clock_type;
40 
41  return time_point;
42 }
43 
44 } // namespace
45 
46 namespace rclcpp
47 {
48 
49 Time::Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type)
50 : rcl_time_(init_time_point(clock_type))
51 {
52  if (seconds < 0) {
53  throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
54  }
55 
56  rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(seconds));
57  rcl_time_.nanoseconds += nanoseconds;
58 }
59 
60 Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
61 : rcl_time_(init_time_point(clock_type))
62 {
63  if (nanoseconds < 0) {
64  throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
65  }
66 
67  rcl_time_.nanoseconds = nanoseconds;
68 }
69 
70 Time::Time(const Time & rhs) = default;
71 
72 Time::Time(Time && rhs) noexcept = default;
73 
75  const builtin_interfaces::msg::Time & time_msg,
76  rcl_clock_type_t clock_type)
77 : rcl_time_(init_time_point(clock_type))
78 {
79  if (time_msg.sec < 0) {
80  throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
81  }
82 
83  rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(time_msg.sec));
84  rcl_time_.nanoseconds += time_msg.nanosec;
85 }
86 
87 Time::Time(const rcl_time_point_t & time_point)
88 : rcl_time_(time_point)
89 {
90  // noop
91 }
92 
93 Time::~Time() = default;
94 
95 Time::operator builtin_interfaces::msg::Time() const
96 {
97  return convert_rcl_time_to_sec_nanos(rcl_time_.nanoseconds);
98 }
99 
100 Time &
101 Time::operator=(const Time & rhs) = default;
102 
103 Time &
104 Time::operator=(const builtin_interfaces::msg::Time & time_msg)
105 {
106  *this = Time(time_msg);
107  return *this;
108 }
109 
110 Time &
111 Time::operator=(Time && rhs) noexcept = default;
112 
113 bool
114 Time::operator==(const rclcpp::Time & rhs) const
115 {
116  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
117  throw std::runtime_error("can't compare times with different time sources");
118  }
119 
120  return rcl_time_.nanoseconds == rhs.rcl_time_.nanoseconds;
121 }
122 
123 bool
124 Time::operator!=(const rclcpp::Time & rhs) const
125 {
126  return !(*this == rhs);
127 }
128 
129 bool
130 Time::operator<(const rclcpp::Time & rhs) const
131 {
132  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
133  throw std::runtime_error("can't compare times with different time sources");
134  }
135 
136  return rcl_time_.nanoseconds < rhs.rcl_time_.nanoseconds;
137 }
138 
139 bool
140 Time::operator<=(const rclcpp::Time & rhs) const
141 {
142  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
143  throw std::runtime_error("can't compare times with different time sources");
144  }
145 
146  return rcl_time_.nanoseconds <= rhs.rcl_time_.nanoseconds;
147 }
148 
149 bool
150 Time::operator>=(const rclcpp::Time & rhs) const
151 {
152  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
153  throw std::runtime_error("can't compare times with different time sources");
154  }
155 
156  return rcl_time_.nanoseconds >= rhs.rcl_time_.nanoseconds;
157 }
158 
159 bool
160 Time::operator>(const rclcpp::Time & rhs) const
161 {
162  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
163  throw std::runtime_error("can't compare times with different time sources");
164  }
165 
166  return rcl_time_.nanoseconds > rhs.rcl_time_.nanoseconds;
167 }
168 
169 Time
171 {
172  if (rclcpp::add_will_overflow(rhs.nanoseconds(), this->nanoseconds())) {
173  throw std::overflow_error("addition leads to int64_t overflow");
174  }
175  if (rclcpp::add_will_underflow(rhs.nanoseconds(), this->nanoseconds())) {
176  throw std::underflow_error("addition leads to int64_t underflow");
177  }
178  return Time(this->nanoseconds() + rhs.nanoseconds(), this->get_clock_type());
179 }
180 
181 Duration
182 Time::operator-(const rclcpp::Time & rhs) const
183 {
184  if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
185  throw std::runtime_error(
186  std::string("can't subtract times with different time sources [") +
187  std::to_string(rcl_time_.clock_type) + " != " +
188  std::to_string(rhs.rcl_time_.clock_type) + "]");
189  }
190 
191  if (rclcpp::sub_will_overflow(rcl_time_.nanoseconds, rhs.rcl_time_.nanoseconds)) {
192  throw std::overflow_error("time subtraction leads to int64_t overflow");
193  }
194 
195  if (rclcpp::sub_will_underflow(rcl_time_.nanoseconds, rhs.rcl_time_.nanoseconds)) {
196  throw std::underflow_error("time subtraction leads to int64_t underflow");
197  }
198 
199  return Duration::from_nanoseconds(rcl_time_.nanoseconds - rhs.rcl_time_.nanoseconds);
200 }
201 
202 Time
204 {
205  if (rclcpp::sub_will_overflow(rcl_time_.nanoseconds, rhs.nanoseconds())) {
206  throw std::overflow_error("time subtraction leads to int64_t overflow");
207  }
208  if (rclcpp::sub_will_underflow(rcl_time_.nanoseconds, rhs.nanoseconds())) {
209  throw std::underflow_error("time subtraction leads to int64_t underflow");
210  }
211 
212  return Time(rcl_time_.nanoseconds - rhs.nanoseconds(), rcl_time_.clock_type);
213 }
214 
215 int64_t
217 {
218  return rcl_time_.nanoseconds;
219 }
220 
221 double
223 {
224  return std::chrono::duration<double>(std::chrono::nanoseconds(rcl_time_.nanoseconds)).count();
225 }
226 
229 {
230  return rcl_time_.clock_type;
231 }
232 
233 Time
234 operator+(const rclcpp::Duration & lhs, const rclcpp::Time & rhs)
235 {
237  throw std::overflow_error("addition leads to int64_t overflow");
238  }
240  throw std::underflow_error("addition leads to int64_t underflow");
241  }
242  return Time(lhs.nanoseconds() + rhs.nanoseconds(), rhs.get_clock_type());
243 }
244 
245 Time &
247 {
248  if (rclcpp::add_will_overflow(rhs.nanoseconds(), this->nanoseconds())) {
249  throw std::overflow_error("addition leads to int64_t overflow");
250  }
251  if (rclcpp::add_will_underflow(rhs.nanoseconds(), this->nanoseconds())) {
252  throw std::underflow_error("addition leads to int64_t underflow");
253  }
254 
255  rcl_time_.nanoseconds += rhs.nanoseconds();
256  if (rcl_time_.nanoseconds < 0) {
257  throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
258  }
259 
260  return *this;
261 }
262 
263 Time &
265 {
266  if (rclcpp::sub_will_overflow(rcl_time_.nanoseconds, rhs.nanoseconds())) {
267  throw std::overflow_error("time subtraction leads to int64_t overflow");
268  }
269  if (rclcpp::sub_will_underflow(rcl_time_.nanoseconds, rhs.nanoseconds())) {
270  throw std::underflow_error("time subtraction leads to int64_t underflow");
271  }
272 
273  rcl_time_.nanoseconds -= rhs.nanoseconds();
274  if (rcl_time_.nanoseconds < 0) {
275  throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
276  }
277 
278  return *this;
279 }
280 
281 Time
283 {
284  return Time(std::numeric_limits<int32_t>::max(), 999999999, clock_type);
285 }
286 
287 builtin_interfaces::msg::Time
289 {
290  builtin_interfaces::msg::Time ret;
291  constexpr rcl_time_point_value_t kRemainder = RCL_S_TO_NS(1);
292  const auto result = std::div(time_point, kRemainder);
293  if (result.rem >= 0) {
294  ret.sec = static_cast<std::int32_t>(result.quot);
295  ret.nanosec = static_cast<std::uint32_t>(result.rem);
296  } else {
297  ret.sec = static_cast<std::int32_t>(result.quot - 1);
298  ret.nanosec = static_cast<std::uint32_t>(kRemainder + result.rem);
299  }
300  return ret;
301 }
302 
303 } // namespace rclcpp
rcl_duration_value_t nanoseconds() const
Get duration in nanosecods.
Definition: duration.cpp:249
static Duration from_nanoseconds(rcl_duration_value_t nanoseconds)
Create a duration object from an integer number representing nanoseconds.
Definition: duration.cpp:314
RCLCPP_PUBLIC Time & operator-=(const rclcpp::Duration &rhs)
Definition: time.cpp:264
RCLCPP_PUBLIC Time & operator+=(const rclcpp::Duration &rhs)
Definition: time.cpp:246
RCLCPP_PUBLIC bool operator>=(const rclcpp::Time &rhs) const
Definition: time.cpp:150
RCLCPP_PUBLIC double seconds() const
Get the seconds since epoch.
Definition: time.cpp:222
virtual RCLCPP_PUBLIC ~Time()
Time destructor.
RCLCPP_PUBLIC Duration operator-(const rclcpp::Time &rhs) const
Definition: time.cpp:182
RCLCPP_PUBLIC rcl_time_point_value_t nanoseconds() const
Get the nanoseconds since epoch.
Definition: time.cpp:216
RCLCPP_PUBLIC bool operator<(const rclcpp::Time &rhs) const
Definition: time.cpp:130
RCLCPP_PUBLIC Time & operator=(const Time &rhs)
RCLCPP_PUBLIC rcl_clock_type_t get_clock_type() const
Get the clock type.
Definition: time.cpp:228
RCLCPP_PUBLIC bool operator<=(const rclcpp::Time &rhs) const
Definition: time.cpp:140
static RCLCPP_PUBLIC Time max(rcl_clock_type_t clock_type=RCL_SYSTEM_TIME)
Get the maximum representable value.
Definition: time.cpp:282
RCLCPP_PUBLIC bool operator==(const rclcpp::Time &rhs) const
Definition: time.cpp:114
RCLCPP_PUBLIC Time operator+(const rclcpp::Duration &rhs) const
Definition: time.cpp:170
RCLCPP_PUBLIC bool operator>(const rclcpp::Time &rhs) const
Definition: time.cpp:160
RCLCPP_PUBLIC Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type=RCL_SYSTEM_TIME)
Time constructor.
Definition: time.cpp:49
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC builtin_interfaces::msg::Time convert_rcl_time_to_sec_nanos(const rcl_time_point_value_t &time_point)
Convert rcl_time_point_value_t to builtin_interfaces::msg::Time.
Definition: time.cpp:288
bool add_will_underflow(const T x, const T y)
Safely check if addition will underflow.
Definition: utilities.hpp:265
bool sub_will_overflow(const T x, const T y)
Safely check if subtraction will overflow.
Definition: utilities.hpp:282
bool add_will_overflow(const T x, const T y)
Safely check if addition will overflow.
Definition: utilities.hpp:248
bool sub_will_underflow(const T x, const T y)
Safely check if subtraction will underflow.
Definition: utilities.hpp:299
A single point in time, measured in nanoseconds, the reference point is based on the source.
Definition: time.h:156
rcl_clock_type_t clock_type
Clock type of the point in time.
Definition: time.h:160
rcl_time_point_value_t nanoseconds
Nanoseconds of the point in time.
Definition: time.h:158
enum rcl_clock_type_e rcl_clock_type_t
Time source type, used to indicate the source of a time measurement.
rcutils_time_point_value_t rcl_time_point_value_t
A single point in time, measured in nanoseconds since the Unix epoch.
Definition: time.h:46
#define RCL_S_TO_NS
Convenience macro to convert seconds to nanoseconds.
Definition: time.h:32