话说ros的话题通信机制让各个节点之间能够轻易地进行交流,实现数据的共享。这跟使用socket第三方库具有异曲同工之妙,但是topic不需要配置host与port,由节点管理器master来处理哪些节点发布topic,哪些节点接收topic,只需要指定相应的topic并在master上注册就能够接收到想要接收的数据。
- 发布者(Publisher):发布者节点通过特定的话题发布消息。
- 订阅者(Subscriber):订阅者节点通过特定的话题接收消息。
- 消息(Message):消息是节点之间传递的信息,具有特定的数据格式。
而实现topic话题通信又非常简单, 以下给出发布者节点的代码,发布的话题为chatter,数据为字符串类型,并且该话题发布的信息队列最多存储10条发布的信息。rate指定的发布信息的频率为10Hz,表示每秒发送10条信息。rospy.is_shutdown()函数用来停止运行程序,该while循环体表示如果程序运行,则不断将消息写入日志并发布消息。
import rospy
from std_msgs.msg import String
def talker():
# 初始化节点
rospy.init_node('talker', anonymous=True)
# 创建发布者,发布到'/chatter'话题
pub = rospy.Publisher('chatter', String, queue_size=10)
rate = rospy.Rate(10) # 10Hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str) # 打印日志
pub.publish(hello_str) # 发布消息
rate.sleep() # 控制发送频率
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
以下给出订阅者节点的代码。这就更容易理解了,首先定义了一个回调函数callback(data),它用来对消息进行处理。我们通过rospy.Subscriber('chatter', String, callback)函数将名称为chatter的topic信息传递给回调函数callback(data),该回调函数会将接收到的data消息打印到屏幕上。
import rospy
from std_msgs.msg import String
# 回调函数
def callback(data):
rospy.loginfo("I heard: %s", data.data)
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber('chatter', String, callback)
rospy.spin()
if __name__ == '__main__':
listener()
ros的话题通信机制基于发布/订阅模型,使得不同节点之间的耦合度降低。发布者和订阅者不需要直接引用对方,只需约定好话题名称。这种松耦合的设计使得各个节点可以独立开发、测试和维护。当需要添加或修改功能时,开发者可以方便地进行调整,而无需对整个系统进行重构。