-
Notifications
You must be signed in to change notification settings - Fork 175
feat: timers API #480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: timers API #480
Conversation
Signed-off-by: Michael X. Grey <[email protected]>
a2af202
to
2d20c4e
Compare
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
@esteve This is embarrassing since I was vocally supportive of committing the cargo lockfiles, but now I'm thinking that might have been a mistake. I'm noticing two issues in practice:
I've had to resort to manually deleting the I'd suggest we remove the lockfiles from the git history or else this is going to cause a great deal of ongoing annoyance where everyone is constantly reverting lockfiles before committing 😞 |
Signed-off-by: Michael X. Grey <[email protected]>
@knmcguire Sorry to summon you into this random PR but it seems a new CI failure has popped up for Windows. I have a feeling this is due to this recent PR in colcon-cargo, and we'll see this failure show up for the |
Thanks for letting me know ! I don't get messages of the CI failures on windows so I was unaware of this. I'll dig into it and make a PR The cargo lock did solve some things for the windows CI though so if that is removed we might need to deal with those failures, but let's see when it comes. |
See this PR: #495 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks very good for the most part! I just noticed some unsafe
calls that didn't have Safety comments associated with them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Managed to get this demo to run on my machine (ubuntu on wsl2) 😄
I'm not comfortable to do a full indepth review yet... but I've added some thoughts.
examples/timer_demo/Cargo.toml
Outdated
name = "examples_timer_demo" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe good to have a bin here so that we can run it through ROS2 command?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this what you had in mind?
Since the example is in src/main.rs
, by default it will generate a binary with the same name as the package, examples_timer_demo
. But I see in the other example packages there's a certain naming pattern for the binaries, so now I've copied that pattern here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahhh gotcha.
And yes exactly like that. naming consistency is good :)
examples/timer_demo/src/main.rs
Outdated
let _timer = worker.create_timer_repeating(timer_period, move |count: &mut usize| { | ||
*count += 1; | ||
println!( | ||
"Drinking 🧉 for the {}th time every {:?}.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me and is a nice example :)
Does ROS2 have an example like this actually? Not used in the tutorials right?
I guess the only nitpick would be, that all other python/cpp examples use create_timer()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this reply.
) | ||
} | ||
|
||
/// Create a [`Timer`] with a repeating callback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was first confused on why there were some much commented out lines, but then I realized that this was for the documentation. Nice!
/// The executor needs to be [spinning][1] for a timer's callback to be triggered. | ||
/// | ||
/// Timers can be created by a [`Node`] using one of these methods: | ||
/// - [`NodeState::create_timer_repeating`][2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This goes a bit too deep for my knowledge I'm afraid. But are these timer naming's consistent with the api of rclcpp or rclpy ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming is intentionally not the same because in rclrs we're introducing the concept of a one-shot timer, which is different from a repeating timer.
The type system of the Rust language makes a strong distinction between the traits FnMut()
and FnOnce()
. Repeating timers can use callbacks with the FnMut()
trait but cannot use callbacks with the FnOnce()
trait. One-shot timers are able to use callbacks with the FnOnce()
trait, but we have to guarantee that the callback will only get triggered one time, and then after that the timer must be inert (not contain any callback).
Because of this we end up with three possible kinds of timers:
- Repeating
- One-shot
- Inert
rclcpp and rclpy don't have this distinction because they have no concept of FnMut
versus FnOnce
, and I don't think they even support a concept of one-shot timer, although the subject has been discussed before.
In my mind this is the kind of divergence that is expected between the client libraries of different languages, in order to reflect differences in what those languages offer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aha.... yes
In hindsight I can indeed see quite differences between the c++ and python tutorials as there are some differences with that as well. Then focusing on api naming consistency shouldn't be the goal as long as it is feature complete.
thanks for the explanation! I missed/forgot this.
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
CI is currently failing because of an upstream issue which is fixed by ros2-rust/rosidl_runtime_rs#13 |
Co-authored-by: Agustin Alba Chicar <[email protected]> Co-authored-by: Jesús Silva <[email protected]> Signed-off-by: Agustin Alba Chicar <[email protected]> Signed-off-by: Jesús Silva <[email protected]> Signed-off-by: Michael X. Grey <[email protected]>
When I did a squash merge to resolve merge conflicts from #446, I lost the commit history from #440 which this PR was based off of. I've added 775b170 which should prompt GitHub to credit @agalbachicar and @JesusSilvaUtrera when this PR gets squash-merged, but I would appreciate if whichever maintainer merges this PR can double-check that the final commit message includes
|
pub(crate) fn create<'a>( | ||
period: Duration, | ||
clock: Clock, | ||
callback: AnyTimerCallback<Scope>, | ||
commands: &Arc<WorkerCommands>, | ||
context: &ContextHandle, | ||
) -> Result<Arc<Self>, RclrsError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there is any risk for odd behavior here when a user decides to create a timer with the NodeClock
?
Specifically, because we keep an Arc
to the underlying rcl_clock
that is wrapped by both Timer
s and Clock
s, if a user was to create a Timer
with the Node
clock it would be kept alive even after the Node
is destroyed.
This is possibly desirable for steady clocks, but there is an odd edge case if the Clock
is using RosTime
when use_sim_time:=true
.
Since RosTime
is updated through a /clock
subscription but the Node
has been destroyed, I suspect the Timer
silently won't be updated anymore, making it effectively useless.
I don't have a clear solution for this (maybe making the ownership to the Node's clock Weak
and offering an API to know whether the underlying clock still exists? But this is also not great) so I'm curious to know what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One simple solution would be to add a node: Node
or node: Arc<NodeHandle>
field to the Timer
struct so that the node is guaranteed to remain valid for as long as the Timer
is valid.
OTOH if a Timer is meant to use the Node's clock and the Node gets dropped, it kind of makes logical sense that the Timer simply stops being triggered since the Node no longer has time. But it's probably not the behavior that a user expects.
IIRC we are only allowing Timers to be created through Nodes, so I see nothing wrong with adding the node
field like most other primitives have to express that dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've given TimerState
a dependency on Node
when using NodeTime
: 2e2dce0
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
@mxgrey sorry it took so long, can you fix the conflicts? Now that rclrs 0.5.0 is out, we can merge this soon. Thanks. |
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
@esteve no worries, merge conflicts are fixed! |
Signed-off-by: Michael X. Grey <[email protected]>
Signed-off-by: Michael X. Grey <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mxgrey thanks!
@jhdcs I hope it's ok with you, I'll merge this PR. Given the US government shutdown, that @jhdcs can't work on Thanks @mxgrey for the great work, and @jhdcs @knmcguire @luca-della-vedova for their reviews. |
This PR splits the
timer.rs
module out of #446 so it can be reviewed separately after #446 is merged.