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"
34 Duration::Duration(int32_t seconds, uint32_t nanoseconds)
40 Duration::Duration(std::chrono::nanoseconds nanoseconds)
45 Duration::Duration(
const Duration & rhs) =
default;
48 const builtin_interfaces::msg::Duration & duration_msg)
56 : rcl_duration_(duration)
61 Duration::operator builtin_interfaces::msg::Duration()
const
63 builtin_interfaces::msg::Duration msg_duration;
65 constexpr int32_t max_s = std::numeric_limits<int32_t>::max();
66 constexpr int32_t min_s = std::numeric_limits<int32_t>::min();
67 constexpr uint32_t max_ns = std::numeric_limits<uint32_t>::max();
68 const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
69 if (result.rem >= 0) {
71 if (result.quot > max_s) {
72 msg_duration.sec = max_s;
73 msg_duration.nanosec = max_ns;
75 msg_duration.sec =
static_cast<int32_t
>(result.quot);
76 msg_duration.nanosec =
static_cast<uint32_t
>(result.rem);
79 if (result.quot <= min_s) {
80 msg_duration.sec = min_s;
81 msg_duration.nanosec = 0u;
83 msg_duration.sec =
static_cast<int32_t
>(result.quot - 1);
84 msg_duration.nanosec =
static_cast<uint32_t
>(kDivisor + result.rem);
91 Duration::operator=(
const Duration & rhs) =
default;
94 Duration::operator=(
const builtin_interfaces::msg::Duration & duration_msg)
137 bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
139 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
140 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
142 if (lhsns > 0 && rhsns > 0) {
143 if (abs_lhs + abs_rhs > max) {
144 throw std::overflow_error(
"addition leads to int64_t overflow");
146 }
else if (lhsns < 0 && rhsns < 0) {
147 if (abs_lhs + abs_rhs > max) {
148 throw std::underflow_error(
"addition leads to int64_t underflow");
156 bounds_check_duration_sum(
159 std::numeric_limits<rcl_duration_value_t>::max());
165 bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
167 auto abs_lhs =
static_cast<uint64_t
>(std::abs(lhsns));
168 auto abs_rhs =
static_cast<uint64_t
>(std::abs(rhsns));
170 if (lhsns > 0 && rhsns < 0) {
171 if (abs_lhs + abs_rhs > max) {
172 throw std::overflow_error(
"duration subtraction leads to int64_t overflow");
174 }
else if (lhsns < 0 && rhsns > 0) {
175 if (abs_lhs + abs_rhs > max) {
176 throw std::underflow_error(
"duration subtraction leads to int64_t underflow");
184 bounds_check_duration_difference(
187 std::numeric_limits<rcl_duration_value_t>::max());
194 bounds_check_duration_scale(int64_t dns,
double scale, uint64_t max)
196 auto abs_dns =
static_cast<uint64_t
>(std::abs(dns));
197 auto abs_scale = std::abs(scale);
198 if (abs_scale > 1.0 && abs_dns >
199 static_cast<uint64_t
>(
static_cast<long double>(max) /
static_cast<long double>(abs_scale)))
201 if ((dns > 0 && scale > 0) || (dns < 0 && scale < 0)) {
202 throw std::overflow_error(
"duration scaling leads to int64_t overflow");
204 throw std::underflow_error(
"duration scaling leads to int64_t underflow");
210 Duration::operator*(
double scale)
const
212 if (!std::isfinite(scale)) {
213 throw std::runtime_error(
"abnormal scale in rclcpp::Duration");
215 bounds_check_duration_scale(
218 std::numeric_limits<rcl_duration_value_t>::max());
219 long double scale_ld =
static_cast<long double>(scale);
222 static_cast<long double>(rcl_duration_.
nanoseconds) * scale_ld));
234 return Duration(std::numeric_limits<int32_t>::max(), 999999999);
240 return std::chrono::duration<double>(std::chrono::nanoseconds(rcl_duration_.
nanoseconds)).count();
247 throw std::runtime_error(
"rmw_time_t cannot be negative");
254 const auto div_result = std::div(rcl_duration_.
nanoseconds, kDivisor);
255 result.sec =
static_cast<uint64_t
>(div_result.quot);
256 result.nsec =
static_cast<uint64_t
>(div_result.rem);
262 Duration::from_rmw_time(rmw_time_t duration)
267 if (duration.sec > limit_sec || duration.nsec > limit_ns) {
272 uint64_t total_ns =
RCL_S_TO_NS(duration.sec) + duration.nsec;
273 if (total_ns > limit_ns) {
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.
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_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.