ROS1订阅者回调函数需多次发布才生效问题求助
ROS1发布订阅延迟问题解决方案
问题根源
你的发布端代码存在两个关键问题,导致首次发布的消息无法被订阅者接收:
- 重复初始化节点:每次调用
publish_data都执行rospy.init_node,ROS节点只能初始化一次,多次调用会打乱节点与ROS Master的注册流程,导致发布者状态异常。 - 每次创建新发布者:
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
相关产品推荐
相关产品推荐

