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.
Are you checking
rospy.is_shutdown()
during your loops? http://wiki.ros.org/rospy/Overview/In...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: @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).