# multiprocessing: rospy.init_node() has already been called

I have a python script which initializes a node through rospy.init_node() and in a later line it does the following:

robot2 = multiprocessing.Process(target=robot, kwargs={'robot_ip': ip2, 'uri': uri})
robot2.start()


which involves starting a new roscore with a new uri, changing the environmental variable by os.environ["ROS_MASTER_URI"] = "http://localhost:" + uri and initializing a new node with rospy.init_node(). However, for the second node the it gives the error that rospy.init_node() is already called.

My expectation however is that since the second node is made after in a seperate process, with separate roscore, and separate environmental variable, this error should not come.

An example similar to my code is the following:

class TheRobot(object):
def __init__(self,
robot_ip='172.16.1.2',
**kwargs):

self.uri  = str(uri)
os.environ["ROS_MASTER_URI"] = "http://localhost:" + self.uri
venv = os.environ.copy()
self.roscore_proc = subprocess.Popen(["roscore", '-p', self.uri],
stdout=None,
stderr=sys.stderr,
preexec_fn=os.setsid
)
rospy.init_node('robot_setup_node_{}'.format(self.uri))

class DoubleRobot(TheRobot):
def __init__(self,
ip1='172.16.0.2',
ip2='172.16.1.2',
uri=None,
**kwargs):

super().__init__(robot_ip=ip1, uri=uri)
robot2 = multiprocessing.Process(target=TheRobot, kwargs={'robot_ip': ip2, 'uri': uri+1})
robot2.start()

twin_panda = DoubleRobot(ip1='172.16.0.2', ip2='172.16.1.2', uri=11314)


a similar question but without multiprocessing can be found here but it did not help. In general,I'd be grateful for any suggestion for the above purpose, or for any other alternative.

edit retag close merge delete

The suggestion would be: do not use multiprocessing with rospy.

( 2020-09-15 05:32:45 -0500 )edit

@gvdhoorn the better alternative is maybe python subprocess right? It's strange though if the two are having separate roscores but can't have separate rospy node

( 2020-09-15 06:23:00 -0500 )edit
1

It's strange though if the two are having separate roscores but can't have separate rospy node

Popen is something entirely different from how multiprocessing works.

The first uses regular system calls to start a new process (ie: the OS starts a new process). The second uses fork(..)ing.

That's a different approach, and cannot be simply considered to be "multiple processes".

( 2020-09-15 06:26:50 -0500 )edit

@gvdhoorn interesting, thanks for the note! Although I'm not sure what to use without interrupting the main process that runs the first robot. It might be safest to just use another computer to have the second robot running. Or do you think subprocess could still be applicable for the second robot in the same computer?

( 2020-09-15 06:36:12 -0500 )edit

I have no idea what your requirements are, nor what you are doing exactly now, so I cannot really make any recommendations.

( 2020-09-15 07:17:21 -0500 )edit

So basically I have two Franka Emika robots that I want them to work together and both are controlled through ros_control. The only technical issue that I could think likely was if the network card on my computer may cause too many packet loss but I have already tested this. On my main thread I want to decide which robot to control by changing the uri environmental variable and publish the control command (roughly speaking). In general though one of the robots for most of the time will remain still and I just want the other one to work with no interruption or issue.This should work for sure if I have both robots connected to separate computers but for convenience I want to give it a try and see if it will work on a single computer.

( 2020-09-15 10:09:04 -0500 )edit

Sort by » oldest newest most voted

Solved it with the following:

    context = 'spawn'
ctx = mp.get_context(context)
robot2 = ctx.Process(target=robot1, kwargs={'robot_ip': ip2, 'uri': uri+1})
robot2.daemon = True
robot2.start()


However, in the same script on top I have to also add:

paths = [...some paths, ...]
for path in reversed(paths):
sys.path.insert(0, os.path.expanduser(path))


which I'm not sure if there's a better solution for it. but it works.

more