'ROS Error. "Error processing request: signal only works in main thread"
I am working with Robot Operating System (ROS) and am attempting to make a server/client where the server will boot up ROS nodes that are specified by the client. To perform the "boot up" I am using roslaunch based on the recommendations found here: http://wiki.ros.org/roslaunch/API%20Usage
I can run the roscore in a window and then I can run the server which boots up fine. However, as soon as I try to send the node names I want to boot up via the client, I get the following error:
"Error processing request: signal only works in main thread"
It then points to a bunch of files in various areas that I have not yet tracked down.
I have tried using a simple roslaunch call on each of the launch files I made individually for the nodes I want to launch (in this case turtlesim_node and turtle_teleop_key) and they boot up fine and work by just running roslaunch [package] turtlesim_launch.launch, etc.
Below is the code for my server:
#!/usr/bin/env python
#Filename: primary_server.py
import rospy
import roslaunch
from robot_man.srv import *
class StartUpServer(object):
def __init__(self):
self._nodes = []
def handle_startup(self, names):
self._temp = names.nodes.split(",") #This reades in the
# information from the srv file sent by the client and
# separates each node/package pair
#This loop separates the input from pairs of 2 corresponding
# to the package and node names the user inputs
for i in range(len(self._temp)):
self._nodes.append(self._temp[i].split())
#This loop will launch each node that the user has specified
for package, executable in self._nodes:
print('package is: {0}, executable is: {1}'.format(package, executable))
node = roslaunch.core.Node(package, executable)
launch = roslaunch.scriptapi.ROSLaunch()
launch.start()
process = launch.launch(node)
print('running node: %s'%executable)
return StartUpResponse(self._nodes) #I will change this later
if __name__ == '__main__':
rospy.init_node('startup_node')
server = StartUpServer()
rospy.Service('startup', StartUp, server.handle_startup)
print('The servers are up and running')
rospy.spin()
Here is the code for my client:
#!/usr/bin/env python
#Filename: primary_client_startup.py
import rospy
from robot_man.srv import *
def main(nodes):
rospy.wait_for_service('startup')
proxy = rospy.ServiceProxy('startup', StartUp)
response = proxy(nodes)
return response
if __name__ == '__main__':
nodes = input('Please enter the node packages followed by \
node names separated by spaces. \n To activate multiple nodes \
separate entries with a comma > ')
main(nodes)
Here is my srv file:
#This should be a string of space/comma separated values
string nodes
---
#This should return "success" if node/s start up successfully, else "fail"
string status
And finally, here are the two launch files I have made to launch the turtle simulator:
turtlesim_launch.launch
<launch>
<node name="turtlesim_node" pkg="turtlesim" type="turtlesim_node" />
</launch>
turtle_teleop_launch.launch
<launch>
<node name="turtle_teleop_key" pkg="turtlesim" type="turtle_teleop_key" />
</launch>
I have done a bit of google searching and found no similar problems for ROS (though there are some similar errors for Django and the like but they don't relate).
I appreciate the help!
P.S. It is worth noting that I make it to line 34 when the error occurs (process = launch.launch(node)).
Solution 1:[1]
actually that is mentioned in the documentation
You're not calling init_node() from the Python Main thread. Python only allows signals to be registered from the Main thread.
Look here rospyOverviewInitialization and Shutdown
Solution 2:[2]
A solution that works (but is quite dirty) is to remove the signal handler registration function:
def dummy_function(): pass
roslaunch.pmon._init_signal_handlers = dummy_function
This way you'll lose the ability to kill the node with CTRL+C, but at least you can start it.
Solution 3:[3]
I believe the problem is that you are trying to launch a node in a callback, which as user3732793 says isn't allowed.
If you use append to Queue
(or just a list) in the callback, then instead of just rospy.spin()
check for items in the queue and then launch if they are there. I believe it will work.
Here is an example
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | user3732793 |
Solution 2 | leosh |
Solution 3 | Batch |