rclcpp: rclcpp::Duration does not include a sleep() method
Bug report
Required Info:
- Operating System: Ubuntu
- Installation type: N/A
- Version or commit hash: Main
- DDS implementation: N/A
- Client library (if applicable): rclcpp
Feature request
Feature description
Add a sleep() method to Duration analog to Rate to sleep for a specified duration rather than at a given rate, when semantically more logical.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 18 (12 by maintainers)
I would strongly recommend that if we make sure that the simplest way to sleep that is our recommended pattern will follow the ROS clock. If we make the bare function
rclcpp::sleep_forthe default pattern then many algorithms will fail in subtle ways when run on simulated time. These bugs will be very hard to debug and will cause future problems. I’d almost recommend that we make this bare function implementation only and provide the user aware sleep at the Node level recommended for the users which can be made ROS Timesource/Clock aware. And looking at this we should make the Rate sleep time source aware too.I guess that’s the part that doesn’t make much sense to me; a time interval (a
Duration) doesn’t sleep. The thread it is on, or the Rate, does sleep, and can take aDurationas the amount of time to sleep. But I just don’t think it makes logical sense for the Duration itself to sleep. Making an analogy to the C++std::chronoAPI, there is nosleepmethod on duration. However, sleep_for receives a duration, which makes sense to me.Maybe your use case could be served by adding a new constructor overload on the
Rateclass to take aDuration, rather than onlystd::chrono::nanoseconds? Or maybe adding a new overload of sleep_for that takes aDuration?pinging @ros2/team to get other opinions here.
I think @tfoote’s feeling (and my own) is that we should not provide a way to sleep that does not respect ROS Time. Adding
sleep()toDurationwould be doing that. So I think we’re saying that’s not a good idea.We already have
rclcpp::sleep_for(chrono duration), but perhaps we should deprecate that and/or put it into a detail namespace as well.In the vein of avoiding subtle bugs, as @tfoote put it:
Perhaps a compromise would be a
Duration::wall_sleep()which is documented to specifically sleep according the system time and not adhere to sim time or shutdown. Then again that could be emulated easily withstd::this_thread::sleep_for(rclcpp::Duration(1).nanoseconds()), so maybe it’s not that valuable.Further more, now that chrono exists and Duration conceptually is not related to a clock at all, maybe we should not have a duration object in rclcpp, instead using
std::chrono::durationand having free functions to convert those to and from ourDuration.msgtype where needed.This discussion is orthogonal to the proposal here (though it is something I’d like to discuss in the future).
For this particular proposal, I think we have agreement to have both a new
rclcpp::sleep_for(const Duration &)and a newRate(const Duration &)method. @SteveMacenski if you’d like to propose a patch, I’d be happy to review.An example would be if you wanted to throttle an update loop (which I know this example is internally implemented in
Ratebut could be simplified using aDurationsleep). You aim to throttle a loop to 10hz but the workers are only taking 20ms to compute a task. You take a time when you start the loop and after you finish the work. ThisDurationthen has the amount of time taken. Subtracting that duration from the 10 hz would give you the sleep duration to then callsleep()on.Sometimes you also just want to sleep for a specific duration of time. If I wanted to sleep for
0.3463seconds (context: scheduler, waiting for an event to occur of a known time, etc), sure I could invert it and throw it into rate, but semantically would be more readable to haveDurationbe able to sleep.Finally, ROS 1’s duration had a sleep, so it would be nice to just have feature parity. I don’t think it hurts anything to have a Duration
sleep().