You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类实现ROS发布订阅节点异常:订阅节点未生效

问题分析与修复方案

核心问题

你的代码存在两个关键问题:

  1. 发布逻辑阻塞程序:Publisher类的__init__方法包含无限while循环,实例化该类后程序会一直卡在循环里,永远执行不到sub = Subscriber()这一行——订阅者根本没被初始化,所以rostopic info看不到订阅者。
  2. 重复初始化节点:ROS规定一个进程只能调用一次rospy.init_node,你在两个类中都调用了该函数,违反了规范。

修复后的代码

#!/usr/bin/python3

import rospy
from std_msgs.msg import String
import threading

class CommandPublisher:
    def __init__(self):
        self.pub = rospy.Publisher('command', String, queue_size=10)
        self.rate = rospy.Rate(1)
        self.is_running = True

    def publish_loop(self):
        while self.is_running and not rospy.is_shutdown():
            command = f"Time is {rospy.get_time()}"
            rospy.loginfo(command)
            self.pub.publish(command)
            self.rate.sleep()

    def stop(self):
        self.is_running = False

class CommandSubscriber:
    def __init__(self):
        rospy.Subscriber('command', String, self.callback)

    def callback(self, data):
        rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

def main():
    # 全局仅初始化一次ROS节点
    rospy.init_node('command_node', anonymous=True)
    pub = CommandPublisher()
    sub = CommandSubscriber()

    # 用线程启动发布循环,避免阻塞主线程
    pub_thread = threading.Thread(target=pub.publish_loop)
    pub_thread.start()

    try:
        # 主线程进入spin,处理订阅回调
        rospy.spin()
    except KeyboardInterrupt:
        # 捕获中断信号,优雅停止发布线程
        pub.stop()
        pub_thread.join()

if __name__ == "__main__":
    main()

关键改动说明

  • 拆分发布逻辑:将原来写在__init__里的阻塞循环移到单独的publish_loop方法,避免类初始化时直接卡死程序。
  • 线程并行执行:用threading.Thread启动发布循环,让主线程可以正常运行rospy.spin()处理订阅回调。
  • 统一节点初始化:仅在main函数中调用一次rospy.init_node,符合ROS单进程单节点的规范。
  • 优雅退出处理:添加stop方法和中断捕获,保证程序终止时发布线程能正常结束。

验证效果

运行修改后的代码后,执行rostopic info /command就能同时看到发布者和订阅者,订阅者也会正常打印收到的消息。

内容的提问来源于stack exchange,提问作者Sabyasachi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:06:31