rospy unload to reconnect python node
Essentially what I need here is to reconnect a python node without restarting the process. Ideally this should work:
#!/usr/bin/python
import rosgraph
import time
import os
import rospy
import std_msgs
m = os.environ['ROS_MASTER_URI']
firstime = True
def msg_callback(msg):
rospy.loginfo(msg)
while True:
connected = rosgraph.is_master_online(m)
time.sleep(1)
print("waiting master ...")
if connected:
rospy.init_node("test_node")
sub = rospy.Subscriber("/chatter", std_msgs.msg.String, msg_callback)
r = rospy.Rate(1)
while not rospy.is_shutdown() and rosgraph.is_master_online(m):
rospy.loginfo("alive")
r.sleep()
print("master lost ...")
It does not work, until the moment the only solution I found is restarting the process. My current idea is that I could "clean" the internal state of rospy to "mimic" that "process restarting".
However I do not find the way to execute the rospy.init_node a second time like it were a clean node initialization.
I have tested several approaches:
Using the rospy.shutdown_signal method
using the python imp.reload method to reload the rospy package
With these approaches I am able to execute again the rospy.initnode method without any error, however when I use some other method from rospy I get errors. For instance using rospy.setparam method I get this error:
rospy.set_param("myparamname", myparamvalue)
File "/opt/ros/indigo/lib/python2.7/dist-packages/rospy/client.py", line 502, in set_param
_param_server[param_name] = param_value #MasterProxy does all the magic for us
File "/opt/ros/indigo/lib/python2.7/dist-packages/rospy/msproxy.py", line 148, in __setitem__
self.target.setParam(rospy.names.get_caller_id(), rospy.names.resolve_name(key), val)
File "/usr/lib/python2.7/xmlrpclib.py", line 1224, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python2.7/xmlrpclib.py", line 1578, in __request
verbose=self.__verbose
File "/usr/lib/python2.7/xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib/python2.7/xmlrpclib.py", line 1292, in single_request
self.send_content(h, request_body)
File "/usr/lib/python2.7/xmlrpclib.py", line 1439, in send_content
connection.endheaders(request_body)
File "/usr/lib/python2.7/httplib.py", line 958, in endheaders
self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py", line 818, in _send_output
self.send(msg)
File "/usr/lib/python2.7/httplib.py", line 780, in send
self.connect()
File "/usr/lib/python2.7/httplib.py", line 761, in connect
self.timeout, self.source_address)
File "/usr/lib/python2.7/socket.py", line 571, in create_connection
raise err
error: [Errno 97] Address family not supported by protocol
Asked by Pablo Iñigo Blasco on 2016-06-29 16:42:24 UTC
Comments
This is not supported. I've seen one or two other questions asking the same thing, and they've generally gone un-answered.
Asked by ahendrix on 2016-06-29 16:54:02 UTC
I see. :-(
Asked by Pablo Iñigo Blasco on 2016-06-29 16:59:12 UTC
Perhaps if you tell us why you think you "have to relaunch a node without killing the whole process", we could see whether there is an alternative approach that could work (just to avoid an xy-problem).
Asked by gvdhoorn on 2016-06-30 03:41:28 UTC
Some years after, again with the same issue :-) the idea is essentially being able to reconnect without restarting the python process. I edited the question so the goals may be now clear.
Asked by Pablo Iñigo Blasco on 2020-02-14 13:21:20 UTC
It would still help if you could tell us why you want to do this. You've only clarified what you want to do.
Asked by gvdhoorn on 2020-02-15 07:08:51 UTC
In this case I have a graphic interface developed in pyside that is the main interface of the whole robotic system. It is GUI is designed to be used by non-expert people and it should be able to work standalone (ie: even without the rosmaster working or any network issue)
Asked by Pablo Iñigo Blasco on 2020-02-16 18:15:57 UTC
Ignoring the question whether this is possible or not: ROS 1's networking code was (initially, and mostly) written with "perfect networks" in mind. Whether that is a valid assumption or not is a different question, but this means that dealing with lost connections is not something which is built-in at every level.
There is also an (implicit) assumption about
process==single node
and that restarting the node means restarting the process. In ROS 2, this is all different, but you appear to be using ROS 1.As such, I'm afraid this (ie: reinitialising a node) is simply not supported at the moment (or at least not with the regular
rospy
,roscpp
over the TCPROS and UDPROS transports).Using a transport or client library that does know how to deal with this may be a lot easier than trying to shoe-horn a solution on-top of
rospy
. One of the many JSON / websockets based ones comes to mind. Perhapsroslibpy
withrosbridge_suite
would work better.Asked by gvdhoorn on 2020-02-17 03:47:05 UTC
You could of course also try to track down where this error is being thrown. Could be it's a simple fix.
Asked by gvdhoorn on 2020-02-17 04:16:57 UTC
Thanks for your answer. quite clarifying. I already tried to track down the issues, but it branches too much in dependencies. :-( . For the next application: ROS2.
For this solution I will just use a workaround: I will just show an error message and I will restart the application if the ROS master is lost. At least, waiting for a new master is possible.
Asked by Pablo Iñigo Blasco on 2020-02-19 13:52:20 UTC
An alternative approach might be to use a multi-master setup. It uses UDP for some parts of the communication, and has (I believe) some built-in functionality for dealing with lost connections.
Asked by gvdhoorn on 2020-02-19 13:56:46 UTC