20 #include "rclcpp/clock.hpp"
21 #include "rclcpp/time.hpp"
23 #include "builtin_interfaces/msg/duration.hpp"
27 #include "rclcpp/exceptions.hpp"
29 #include "rcutils/logging_macros.h"
31 #include "rclcpp/utilities.hpp"
36 Duration::Duration(int32_t seconds, uint32_t nanoseconds)
42 Duration::Duration(std::chrono::nanoseconds nanoseconds)
47 Duration::Duration(
const Duration & rhs) =
default;
50 const builtin_interfaces::msg::Duration & duration_msg)
58 : rcl_duration_(duration)
63 Duration::operator builtin_interfaces::msg::Duration()
const
65 builtin_interfaces::msg::Duration msg_duration;
67 constexpr int32_t max_s = std::numeric_limits<int32_t>::max();
68 constexpr int32_t min_s = std::numeric_limits<int32_t>::min();
69 constexpr uint32_t max_ns = std::numeric_limits<uint32_t>::max();
70 const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
71 if (result.rem >= 0) {
73 if (result.quot > max_s) {
74 msg_duration.sec = max_s;
75 msg_duration.nanosec = max_ns;
77 msg_duration.sec =
static_cast<int32_t
>(result.quot);
78 msg_duration.nanosec =
static_cast<uint32_t
>(result.rem);
81 if (result.quot <= min_s) {
82 msg_duration.sec = min_s;
83 msg_duration.nanosec = 0u;
85 msg_duration.sec =
static_cast<int32_t
>(result.quot - 1);
86 msg_duration.nanosec =
static_cast<uint32_t
>(kDivisor + result.rem);
93 Duration::operator=(
const Duration & rhs) =
default;
96 Duration::operator=(
const builtin_interfaces::msg::Duration & duration_msg)
139 bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
141 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
142 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
144 if (lhsns > 0 && rhsns > 0) {
145 if (abs_lhs + abs_rhs > max) {
146 throw std::overflow_error(
"addition leads to int64_t overflow");
148 }
else if (lhsns < 0 && rhsns < 0) {
149 if (abs_lhs + abs_rhs > max) {
150 throw std::underflow_error(
"addition leads to int64_t underflow");
158 bounds_check_duration_sum(
161 std::numeric_limits<rcl_duration_value_t>::max());
174 bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
176 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
177 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
179 if (lhsns > 0 && rhsns < 0) {
180 if (abs_lhs + abs_rhs > max) {
181 throw std::overflow_error(
"duration subtraction leads to int64_t overflow");
183 }
else if (lhsns < 0 && rhsns > 0) {
184 if (abs_lhs + abs_rhs > max) {
185 throw std::underflow_error(
"duration subtraction leads to int64_t underflow");
193 bounds_check_duration_difference(
196 std::numeric_limits<rcl_duration_value_t>::max());
210 bounds_check_duration_scale(int64_t dns,
double scale, uint64_t max)
212 auto abs_dns =
static_cast<uint64_t
>(std::abs(dns));
213 auto abs_scale = std::abs(scale);
214 if (abs_scale > 1.0 && abs_dns >
215 static_cast<uint64_t
>(
static_cast<long double>(max) /
static_cast<long double>(abs_scale)))
217 if ((dns > 0 && scale > 0) || (dns < 0 && scale < 0)) {
218 throw std::overflow_error(
"duration scaling leads to int64_t overflow");
220 throw std::underflow_error(
"duration scaling leads to int64_t underflow");
226 Duration::operator*(
double scale)
const
228 if (!std::isfinite(scale)) {
229 throw std::runtime_error(
"abnormal scale in rclcpp::Duration");
231 bounds_check_duration_scale(
234 std::numeric_limits<rcl_duration_value_t>::max());
235 long double scale_ld =
static_cast<long double>(scale);
238 static_cast<long double>(rcl_duration_.
nanoseconds) * scale_ld));
242 Duration::operator*=(
double scale)
244 *
this = *
this * scale;
257 return Duration(std::numeric_limits<int32_t>::max(), 999999999);
263 return std::chrono::duration<double>(std::chrono::nanoseconds(rcl_duration_.
nanoseconds)).count();
270 throw std::runtime_error(
"rmw_time_t cannot be negative");
277 const auto div_result = std::div(rcl_duration_.
nanoseconds, kDivisor);
278 result.sec =
static_cast<uint64_t
>(div_result.quot);
279 result.nsec =
static_cast<uint64_t
>(div_result.rem);
285 Duration::from_rmw_time(rmw_time_t duration)
290 if (duration.sec > limit_sec || duration.nsec > limit_ns) {
295 uint64_t total_ns =
RCL_S_TO_NS(duration.sec) + duration.nsec;
296 if (total_ns > limit_ns) {
321 builtin_interfaces::msg::Time
322 operator+(
const builtin_interfaces::msg::Time & lhs,
const rclcpp::Duration & rhs)
325 throw std::runtime_error(
"message time is negative");
329 rcl_time =
RCL_S_TO_NS(
static_cast<int64_t
>(lhs.sec));
330 rcl_time += lhs.nanosec;
333 throw std::overflow_error(
"addition leads to int64_t overflow");
336 throw std::underflow_error(
"addition leads to int64_t underflow");
344 builtin_interfaces::msg::Time
345 operator-(
const builtin_interfaces::msg::Time & lhs,
const rclcpp::Duration & rhs)
348 throw std::runtime_error(
"message time is negative");
352 rcl_time =
RCL_S_TO_NS(
static_cast<int64_t
>(lhs.sec));
353 rcl_time += lhs.nanosec;
356 throw std::overflow_error(
"addition leads to int64_t overflow");
359 throw std::underflow_error(
"addition leads to int64_t underflow");
rcl_duration_value_t nanoseconds() const
Get duration in nanosecods.
double seconds() const
Get duration in seconds.
static Duration from_nanoseconds(rcl_duration_value_t nanoseconds)
Create a duration object from an integer number representing nanoseconds.
static Duration max()
Get the maximum representable value.
rmw_time_t to_rmw_time() const
Convert Duration into rmw_time_t.
static Duration from_seconds(double seconds)
Create a duration object from a floating point number representing seconds.
Duration(int32_t seconds, uint32_t nanoseconds)
Duration constructor.
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.
bool add_will_underflow(const T x, const T y)
Safely check if addition will underflow.
bool sub_will_overflow(const T x, const T y)
Safely check if subtraction will overflow.
bool add_will_overflow(const T x, const T y)
Safely check if addition will overflow.
bool sub_will_underflow(const T x, const T y)
Safely check if subtraction will underflow.
A duration of time, measured in nanoseconds and its source.
rcl_duration_value_t nanoseconds
Duration in nanoseconds and its source.
#define RCL_NS_TO_S
Convenience macro to convert nanoseconds to seconds.
rcutils_time_point_value_t rcl_time_point_value_t
A single point in time, measured in nanoseconds since the Unix epoch.
rcutils_duration_value_t rcl_duration_value_t
A duration of time, measured in nanoseconds.
#define RCL_S_TO_NS
Convenience macro to convert seconds to nanoseconds.