init_node in multiprocessing.Process

asked 2019-01-16 02:12:05 -0500

zkytony gravatar image

updated 2019-01-16 02:13:20 -0500

My program uses Tkinter as GUI which needs to be the main process. I want to display image obtained from Kinect topic on this GUI, therefore I need to call init_node when running this process. Also, I have some underlying procedure that will control the robot's arm to change the environment, which will lead to some changes on the GUI (drawing some shapes). Since this procedure needs to control robot's arm, it needs to be part of a ROS node. Currently I am using multiprocessing.Process to run this procedure. What I have found is that, if I call init_node() in the main process, the code that is running in multiprocessing.Process won't be able to subscribe to any ROS topic (it is not bound to any node!)

To illustrate, the structure of my code looks like

from multiprocessing import Process
class Procedure
    def __init__(self, gui):
        self._gui = gui
        ....
    def run(self):
        ....  # the PROBLEM is, code here has no access to ROS's resource (e.g. cannot get message from topics, etc.)

class GUI:
    ...
    def update_kinect_image_periodically(self, freq=5):
          # Uses Tkinter's after() function to update kinect image, obtained from some ROS topic.

def main():
    rospy.init_node("my_node")
    gui = GUI()
    gui.update_image_periodically()
    procedure = Procedure(gui)
    p = Process(target=procedure.run, args=())
    p.start()
    gui.mainloop()  # will keep GUI running
    p.terminate()

I thought this problem occurs because Process creates a new process, which has not been declared as a ROS node. However, when I try to call init_node within Procedure.run, I get the error ROSException: rospy.init_node() has already been called with different arguments ... Well, this makes sense too, because you cannot call init_node twice (for different nodes) in one Python script. So, how can I accomplish what I want to do?

I appreciate any help!

edit retag flag offensive close merge delete

Comments

1

IIRC, Process uses fork(), which doesn't work too well with rospy. There have been quite a few Q&As about that on this forum, please use Google to search for them (site:answers.ros.org <other search terms>).

gvdhoorn gravatar image gvdhoorn  ( 2019-01-16 03:16:10 -0500 )edit

Also: threading works with rospy. I'm not an expert, but I don't understand the need to use a separate process here.

gvdhoorn gravatar image gvdhoorn  ( 2019-01-16 03:16:41 -0500 )edit

Thanks for your comments! I was using threading but the the kinect images on the GUI were not updated smoothly. I suspected that it was due to too much computation in the Procedure, so I was trying to see if I can run the two things in separate processes.

zkytony gravatar image zkytony  ( 2019-01-16 10:59:52 -0500 )edit

I worked around this problem by putting the GUI into another file, and have the Procedure communicate (sending objects) with the GUI via files saved on the disk. Not the best option I suppose but works for now...

zkytony gravatar image zkytony  ( 2019-01-16 11:39:13 -0500 )edit