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

ROS1订阅者回调函数需多次发布才生效问题求助

ROS1发布订阅延迟问题解决方案

问题根源

你的发布端代码存在两个关键问题,导致首次发布的消息无法被订阅者接收:

  1. 重复初始化节点:每次调用publish_data都执行rospy.init_node,ROS节点只能初始化一次,多次调用会打乱节点与ROS Master的注册流程,导致发布者状态异常。
  2. 每次创建新发布者:rospy.Publisher在函数内部实例化,每次发布都新建一个发布者对象,ROS需要时间完成该发布者与Master的注册同步,首次发布时同步未完成,消息直接丢失,后续发布时注册完成才会被订阅者收到。

修复后的发布端代码

将节点初始化和发布者创建逻辑移到函数外部,确保只执行一次:

import rospy
from std_msgs.msg import UInt16

# 全局字典存储各主题的发布者,避免重复创建
topic_publishers = {}

def init_publisher_node():
    # 仅初始化一次节点
    rospy.init_node('Talker', anonymous=True)
    # 提前创建所有伺服主题的发布者(可选,也可按需创建)
    for servo_num in range(1, 7):
        topic_name = f"Servo{servo_num}"
        topic_publishers[topic_name] = rospy.Publisher(topic_name, UInt16, queue_size=100)
    # 给发布者预留注册同步时间
    rospy.sleep(0.5)

def publish_data(topic, message):
    # 如果主题未创建发布者,动态创建
    if topic not in topic_publishers:
        topic_publishers[topic] = rospy.Publisher(topic, UInt16, queue_size=100)
    # 发布消息
    topic_publishers[topic].publish(message)
    rospy.loginfo("MSG PUB LUL")

if __name__ == '__main__':
    init_publisher_node()
    # 示例:发布Servo1的测试消息
    test_msg = UInt16(data=50)
    publish_data("Servo1", test_msg)
    # 可选:保持节点存活一段时间,确保消息发送完成
    rospy.Rate(10).sleep()

关键修改说明

  • 节点初始化仅执行一次:rospy.init_node放在单独的初始化函数中,程序启动时只调用一次,保证节点状态稳定。
  • 复用发布者对象:用字典缓存发布者,避免重复创建,确保发布者与Master的连接持续有效。
  • 添加注册等待时间:初始化发布者后短暂sleep,确保发布者完成在Master上的注册,避免第一条消息丢失。

订阅端代码验证

你的订阅端代码逻辑正常,无需修改。修复发布端后,每次发布消息时,订阅者的回调函数会立即触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:57:38