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