ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
2

ROSPY: Interrupting with a control-c

asked 2018-08-01 12:09:50 -0600

pitosalas gravatar image

updated 2019-02-15 09:28:58 -0600

Sometimes when my raspy node is running (launched with rosrun) I can interrupt it with a control-c, and sometimes not. What's the best practice for making sure that my raspy nodes see a control-c and allow me to do a clean shutdown?

Follow-up

What about this case, where I think it all looks correct and nothing in the loop is long running, and yet I often have to do ^c many many times before it responds. Oddly shift ^c seems to interrupt better. I don't even know what shift ^c is!

    rate = rospy.Rate(5)
    count_log = 0

    while not rospy.is_shutdown():
        count_log += 1
        if (count_log % 10 == 0):
            print("\n#%s [%s] %s=%1.2f" % (count_log, self.state,
                                         self.m.closest_dir, self.m.closest_dist))
        if (self.m is None):
            pass
        elif (self.state == "find_wall"):
            self.handle_find_wall()
        elif (self.state == "follow_wall"):
            self.handle_follow_wall()
        elif (self.state == "emer_stop"):
            self.handle_emer_stop()
        rate.sleep()
edit retag flag offensive close merge delete

Comments

1

Are you checking rospy.is_shutdown() during your loops? http://wiki.ros.org/rospy/Overview/In...

jayess gravatar image jayess  ( 2018-08-01 13:00:45 -0600 )edit

Yes, in some cases. But I was looking at sample code and I saw some examples that didn't do that. Also I found that even if I did rosy.is_shutdown() it seemed sometimes like the control-c didn't work. So I thought there might be a best practice for ensuring that I can always kill my nodes

pitosalas gravatar image pitosalas  ( 2018-08-01 13:32:29 -0600 )edit
2

@pitosalas: @Geoff already answered the previous version of your question, and you accepted the answer. It's considered bad form to edit a question after there is an accepted answer. It would be better to post a new question as a follow-up (which I believe you already did: #q315792).

gvdhoorn gravatar image gvdhoorn  ( 2019-02-16 11:39:19 -0600 )edit

1 Answer

Sort by » oldest newest most voted
6

answered 2018-08-01 18:45:32 -0600

Geoff gravatar image

If your node does some long-running processing then that will block interrupting it with control-c. Here is some simple code that demonstrates this:

import rospy
import time

rospy.init_node('blag')
while True:
    print('beginning sleep')
    for i in range(1000):
        for j in range(1000):
            for k in range(500):
                pass
    print('ended sleep')
    if rospy.is_shutdown():
        print('shutdown')
        break
print('finished')

I set up the nested loops so it "processes" for about 5 seconds on my computer. If I press Ctrl-C during that time, it won't actually handle the interrupt until the nested loops finish.

If you need your node to quickly shut down at any time for some reason (e.g. notifying other nodes rapidly), then you need to plan your time-consuming processing. There are a number of strategies you can use. Here are a few:

  • Break your processing down into smaller chunks, and manage them so that you have more frequent checks of if the node has been shut down or not. Depending on the node's functionality, you may also want to preserve processing results in between chunks for some reason. You can process one chunk in each iteration of your node's main ROS loop, for example.

  • Put the processing in a separate thread, and if necessary use a semaphore or similar communication mechanism to control that thread's execution. The main thread would run in a standard ROS processing loop. However this is mostly duplicating the effort of rospy.is_shutdown(), just with more control over how you stop processing.

  • If you are using a recent enough version of Python, then use futures and impress your friends.

  • Just put calls to rospy.is_shutdown() throughout your code. It's a little ugly and could leave some system state in a mess, but it's a simple and effective approach, especially if you don't want to deal with threads.

It's also important to note that if your node is not able to respond to Ctrl-C then it is also not able to respond to new data arriving on topics, service calls, action results, timers, and anything else that you register callbacks for. Any time you block the node (i.e. spend a long time without giving the ROS infrastructure some CPU time) you effectively freeze the node from the point of view of the rest of the system. If you need a node that does long running processing and is responsive to new data, service requests, or similar then you need to use one of the strategies mentioned above to separate long-running processing from the main ROS loop.

edit flag offensive delete link more

Comments

Thanks for the excellent insights. Basically only at is_shutdown is there’s a chance to detect a possible control-c.

pitosalas gravatar image pitosalas  ( 2018-08-01 18:57:39 -0600 )edit

Not entirely true. Calls such as rospy.spin() and rate.sleep() will also detect a Ctrl-C.

Geoff gravatar image Geoff  ( 2018-08-01 19:48:36 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-08-01 12:09:50 -0600

Seen: 6,932 times

Last updated: Feb 15 '19