Common way to Interrupt a rospy.Rate.sleep

asked 2019-05-23 03:41:06 -0500

Jotweh gravatar image

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?

edit retag flag offensive close merge delete

Comments

I am thinking about something like that: https://gist.github.com/Tomatower/02f...

Jotweh gravatar image Jotweh  ( 2019-05-23 03:42:34 -0500 )edit
1

What about using a Timer instead of a Rate to control the rate at which your control loop is run? I'm not entirely sure about rospy, but that would mostly decouple incoming msg processing from your periodic 'loop' without needing to modify Rate and would make use of existing infrastructure.

gvdhoorn gravatar image gvdhoorn  ( 2019-05-23 03:46:25 -0500 )edit

If I use a Timer, I will have to keep track of elapsed time, and loose all the convenience I get from using Rate.

Jotweh gravatar image Jotweh  ( 2019-05-23 03:49:24 -0500 )edit
1

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.

gvdhoorn gravatar image gvdhoorn  ( 2019-05-23 03:53:25 -0500 )edit

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.

Jotweh gravatar image Jotweh  ( 2019-05-23 04:04:27 -0500 )edit

I haven't checked (and it's been a while), but does rospy.Timer(..) accept a lambda? 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.

gvdhoorn gravatar image gvdhoorn  ( 2019-05-23 04:16:08 -0500 )edit