【问题标题】:ROS Error. "Error processing request: signal only works in main thread"ROS 错误。 “错误处理请求:信号仅在主线程中有效”
【发布时间】:2022-04-22 23:04:36
【问题描述】:

我正在使用机器人操作系统 (ROS),并尝试创建一个服务器/客户端,服务器将在其中启动客户端指定的 ROS 节点。为了执行“启动”,我根据此处的建议使用 roslaunch:http://wiki.ros.org/roslaunch/API%20Usage

我可以在一个窗口中运行 roscore,然后我可以运行启动正常的服务器。但是,一旦我尝试发送要通过客户端启动的节点名称,就会收到以下错误:

“错误处理请求:信号只在主线程中起作用”

然后它指向我尚未追踪的各个区域中的一堆文件。

我已经尝试在我为要启动的节点(在本例中为 turtlesim_node 和 turtle_teleop_key)单独创建的每个启动文件上使用一个简单的 roslaunch 调用,它们可以正常启动并通过运行 roslaunch [package] turtlesim_launch 来工作.launch 等。

下面是我的服务器的代码:

#!/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()

这是我的客户的代码:

#!/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)

这是我的 srv 文件:

#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

最后,这是我为启动海龟模拟器而制作的两个启动文件:

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>

我做了一些谷歌搜索,并没有发现 ROS 的类似问题(虽然 Django 等有一些类似的错误,但它们不相关)。

感谢您的帮助!

附:值得注意的是,当错误发生时,我进入了第 34 行(process = launch.launch(node))。

【问题讨论】:

  • 嘿,Devon,你在这里找到什么优雅的解决方案了吗?

标签: python multithreading ros


【解决方案1】:

实际上是在文档中提到的

您没有从 Python 主线程调用 init_node()。 Python 只允许从主线程注册信号。

看这里rospyOverviewInitialization and Shutdown

【讨论】:

  • 嗯,好电话。您知道使用与我尝试完成的方法类似的方法远程初始化节点的方法吗?
  • 我陷入了同样的陷阱,这就是我发现你的问题的原因。我认为那篇文章wiki.ros.org/ROS/Tutorials/… 中的大型启动文件通常是一个很好的解决方案,或者您会在 Discourse.ros.org 上寻求解决方案。抱歉我其实不知道
  • 没问题。感谢您的反馈!
【解决方案2】:

一个可行(但很脏)的解决方案是删除信号处理程序注册函数:

    def dummy_function(): pass
    roslaunch.pmon._init_signal_handlers = dummy_function

这样你将失去使用 CTRL+C 杀死节点的能力,但至少你可以启动它。

【讨论】:

    【解决方案3】:

    我认为问题在于您试图在回调中启动一个节点,正如 user3732793 所说,这是不允许的。 如果您在回调中使用 append to Queue(或只是一个列表),那么不要只是 rospy.spin() 检查队列中的项目,然后在它们存在时启动它们。我相信它会奏效。 这是example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      相关资源
      最近更新 更多