0
$\begingroup$

Rosanswers logo

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()

Originally posted by pitosalas on ROS Answers with karma: 628 on 2018-08-01

Post score: 2


Original comments

Comment by jayess on 2018-08-01:
Are you checking rospy.is_shutdown() during your loops? http://wiki.ros.org/rospy/Overview/Initialization%20and%20Shutdown#Testing_for_shutdown

Comment by pitosalas on 2018-08-01:
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

Comment by gvdhoorn on 2019-02-16:
@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).

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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.


Originally posted by Geoff with karma: 4203 on 2018-08-01

This answer was ACCEPTED on the original site

Post score: 6


Original comments

Comment by pitosalas on 2018-08-01:
Thanks for the excellent insights. Basically only at is_shutdown is there’s a chance to detect a possible control-c.

Comment by Geoff on 2018-08-01:
Not entirely true. Calls such as rospy.spin() and rate.sleep() will also detect a Ctrl-C.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.