Hi,
It's indeed possible, but I wouldn't recommend it to you, as other node can still be using this service, or the service can probably be restarted in other way (for example, wait a parameter to be on, or wait for an other service to be called).
To make the server kill himself :
What you can do is to set a flag to shutdown the service : (Warning : not safe, the script can terminate before the response is sent, use at your own risk)
from beginner_tutorials.srv import *
import rospy
manual_shutdown = False
def handle_add_two_ints(req):
global manual_shutdown
print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))
response = AddTwoIntsResponse(req.a + req.b)
manual_shutdown = True
return response
def add_two_ints_server():
rospy.init_node('add_two_ints_server')
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
print "Ready to add two ints."
r = rospy.Rate(10)
while not rospy.is_shutdown() and not manual_shutdown:
r.sleep()
rospy.sleep(1)
s.shutdown()
if __name__ == "__main__":
add_two_ints_server()
Also, you can replace the signal_shutdown by what you want or even put the "manual_shutdown
" in the while-loop and do thing after the loop.
I used a while loop instead of rospy.spin()
, you can check why here : https://answers.ros.org/question/1103...
For completion, you can check these questions : https://answers.ros.org/question/1981... or https://answers.ros.org/question/1099...
Edit 2 : To make the client kill the server (make a node kill another node):
You can apply the method 1 above to create a "kill me" service and call it from the client.
Or even simpler, you just have to use the rosnode command :
node1:
import rospy
def node1():
rospy.init_node('node1')
r = rospy.Rate(10)
while not rospy.is_shutdown():
r.sleep()
if __name__ == "__main__":
node1()
node 2:
import rospy
from subprocess import call
def node2():
rospy.init_node('node2')
rospy.sleep(10) # Wait 10 second to kill node1
call(["rosnode", "kill", "node1"], shell=True) # be careful here https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess
if __name__ == "__main__":
node2()
Edit 1 : Some more answers :
(1) My code is not good at all so I edited it, if you don't return immediately after setting manual_shutdown = True
, the client will have an error since the connection is broken (in rospy, all callback are in a thread).
The error :
ERROR: transport error completing
service call: unable to receive data
from sender, check sender's logs for
details
You can try it by adding a rospy.sleep(1)
after the manual_shutdown=True
to see the error
You can try to minimize the effect by putting the flag to True just before the return and putting a rospy.sleep() after the loop, but it's quite a ugly method. I'm still searching a correct way to do this
(2) you can add and you SHOULD add a rospy.sleep() or a rospy.rate() in the loop in Python, otherwise you CPU will work for nothing. You can check with the command top
the CPU usage :
top without rospy.rate(10 ... (more)