19 #include "rclcpp/clock.hpp"
20 #include "rclcpp/time.hpp"
22 #include "builtin_interfaces/msg/duration.hpp"
26 #include "rclcpp/exceptions.hpp"
28 #include "rcutils/logging_macros.h"
30 #include "rclcpp/utilities.hpp"
35 Duration::Duration(int32_t seconds, uint32_t nanoseconds)
41 Duration::Duration(std::chrono::nanoseconds nanoseconds)
46 Duration::Duration(
const Duration & rhs) =
default;
49 const builtin_interfaces::msg::Duration & duration_msg)
57 : rcl_duration_(duration)
62 Duration::operator builtin_interfaces::msg::Duration()
const
64 builtin_interfaces::msg::Duration msg_duration;
66 constexpr int32_t max_s = std::numeric_limits<int32_t>::max();
67 constexpr int32_t min_s = std::numeric_limits<int32_t>::min();
68 constexpr uint32_t max_ns = std::numeric_limits<uint32_t>::max();
69 const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
70 if (result.rem >= 0) {
72 if (result.quot > max_s) {
73 msg_duration.sec = max_s;
74 msg_duration.nanosec = max_ns;
76 msg_duration.sec =
static_cast<int32_t
>(result.quot);
77 msg_duration.nanosec =
static_cast<uint32_t
>(result.rem);
80 if (result.quot <= min_s) {
81 msg_duration.sec = min_s;
82 msg_duration.nanosec = 0u;
84 msg_duration.sec =
static_cast<int32_t
>(result.quot - 1);
85 msg_duration.nanosec =
static_cast<uint32_t
>(kDivisor + result.rem);
92 Duration::operator=(
const Duration & rhs) =
default;
95 Duration::operator=(
const builtin_interfaces::msg::Duration & duration_msg)
138 bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
140 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
141 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
143 if (lhsns > 0 && rhsns > 0) {
144 if (abs_lhs + abs_rhs > max) {
145 throw std::overflow_error(
"addition leads to int64_t overflow");
147 }
else if (lhsns < 0 && rhsns < 0) {
148 if (abs_lhs + abs_rhs > max) {
149 throw std::underflow_error(
"addition leads to int64_t underflow");
157 bounds_check_duration_sum(
160 std::numeric_limits<rcl_duration_value_t>::max());
173 bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
175 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
176 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
178 if (lhsns > 0 && rhsns < 0) {
179 if (abs_lhs + abs_rhs > max) {
180 throw std::overflow_error(
"duration subtraction leads to int64_t overflow");
182 }
else if (lhsns < 0 && rhsns > 0) {
183 if (abs_lhs + abs_rhs > max) {
184 throw std::underflow_error(
"duration subtraction leads to int64_t underflow");
192 bounds_check_duration_difference(
195 std::numeric_limits<rcl_duration_value_t>::max());
209 bounds_check_duration_scale(int64_t dns,
double scale, uint64_t max)
211 auto abs_dns =
static_cast<uint64_t
>(std::abs(dns));
212 auto abs_scale = std::abs(scale);
213 if (abs_scale > 1.0 && abs_dns >
214 static_cast<uint64_t
>(
static_cast<long double>(max) /
static_cast<long double>(abs_scale)))
216 if ((dns > 0 && scale > 0) || (dns < 0 && scale < 0)) {
217 throw std::overflow_error(
"duration scaling leads to int64_t overflow");
219 throw std::underflow_error(
"duration scaling leads to int64_t underflow");
225 Duration::operator*(
double scale)
const
227 if (!std::isfinite(scale)) {
228 throw std::runtime_error(
"abnormal scale in rclcpp::Duration");
230 bounds_check_duration_scale(
233 std::numeric_limits<rcl_duration_value_t>::max());
234 long double scale_ld =
static_cast<long double>(scale);
237 static_cast<long double>(rcl_duration_.
nanoseconds) * scale_ld));
241 Duration::operator*=(
double scale)
243 *
this = *
this * scale;
256 return Duration(std::numeric_limits<int32_t>::max(), 999999999);
262 return std::chrono::duration<double>(std::chrono::nanoseconds(rcl_duration_.
nanoseconds)).count();
269 throw std::runtime_error(
"rmw_time_t cannot be negative");
276 const auto div_result = std::div(rcl_duration_.
nanoseconds, kDivisor);
277 result.sec =
static_cast<uint64_t
>(div_result.quot);
278 result.nsec =
static_cast<uint64_t
>(div_result.rem);
284 Duration::from_rmw_time(rmw_time_t duration)
289 if (duration.sec > limit_sec || duration.nsec > limit_ns) {
294 uint64_t total_ns =
RCL_S_TO_NS(duration.sec) + duration.nsec;
295 if (total_ns > limit_ns) {
320 builtin_interfaces::msg::Time
321 operator+(
const builtin_interfaces::msg::Time & lhs,
const rclcpp::Duration & rhs)
324 throw std::runtime_error(
"message time is negative");
328 rcl_time =
RCL_S_TO_NS(
static_cast<int64_t
>(lhs.sec));
329 rcl_time += lhs.nanosec;
332 throw std::overflow_error(
"addition leads to int64_t overflow");
335 throw std::underflow_error(
"addition leads to int64_t underflow");
343 builtin_interfaces::msg::Time
344 operator-(
const builtin_interfaces::msg::Time & lhs,
const rclcpp::Duration & rhs)
347 throw std::runtime_error(
"message time is negative");
351 rcl_time =
RCL_S_TO_NS(
static_cast<int64_t
>(lhs.sec));
352 rcl_time += lhs.nanosec;
355 throw std::overflow_error(
"addition leads to int64_t overflow");
358 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.