Common way to Interrupt a rospy.Rate.sleep
In some cases it is important to early interrupt a periodic loop, designed as
rate = rospy.Rate(1)
while True:
process()
rate.sleep()
Most of the time, the goal is to limit the processing done within the node, If from another non-ROS-thread (or subscribed topic for that matter) some condition occurs, the loop will still continue to send.
Imagine for example periodic (non-ros) control-commands to a robot sent 1/sec to not overload the communication link. But when a new steering command arrives, I want to immediately and threadsafe wake up my mainloop.
I was thinking about an InterruptableRate
kind of thing working like
rate = InterruptableRate(1)
while True:
process()
# might wake up early due to an interrupt
rate.sleep()
# from another Thread
rate.interrupt()
Is there a canonical way of doing that? Is anybody interested in that kind of Thing?
I am thinking about something like that: https://gist.github.com/Tomatower/02f...
What about using a
Timer
instead of aRate
to control the rate at which your control loop is run? I'm not entirely sure aboutrospy
, but that would mostly decouple incoming msg processing from your periodic 'loop' without needing to modifyRate
and would make use of existing infrastructure.If I use a Timer, I will have to keep track of elapsed time, and loose all the convenience I get from using Rate.
What does
Rate
do for you that you'd have to do yourself then? I'm talking about rospy.Timer just to be extra clear.Edit: just realised that I assumed that you run your control law as part of the subscription handler. That is of course not necessarily so.
Figured that out after I wrote my answer :) But basically I need to write more code, I do have to convert my code into callbacks and by that have to either create classes for everything or use globals (for data). It would be nice to keep to the super simple-stupid interface of
rate.sleep
, But still not be hard-bound by it.I haven't checked (and it's been a while), but does
rospy.Timer(..)
accept alambda
? You could use a closure in that case to capture any variables you'd need/want (SO post with an example).But this all starts to sound a bit like an xy-problem.
Not to say that an interruptable
Rate::sleep()
would not make sense though.