ROS发布者(Publisher)和订阅者(Subscriber)的python编程实现(讲解超级详细)

       有时候想想,国内有些资源确实比较稀缺,但是我们一样不会落后!学习python和ROS这么久了,一直很少去实战,另外看到基于python编程的ROS话题通信教程实在是稀缺了,或者对小白不是那么的友好,所以写下这篇教程与你一起进步。
       关于ROS很基本的知识,比如:怎么启动roscore;怎么创建工作空间;source环境;python脚本的执行权限等我就不讲解了。主要是代码部分讲解!

一、初始化工作空间

在这里插入图片描述

二、source环境

把下面的内容:

source /home/xiaolong/ros_practice/devel/setup.bash

放在.bashrc末尾,这个不懂得看我之前的博客

传送门: https://blog.csdn.net/qq_45152498/article/details/108652439

三、创建功能包

在这里插入图片描述
创建好的src:

在这里插入图片描述

四、Writing the Publisher Node

在scripts下创建talker.py并确保它有可执行权限

让我先把整体代码给你,让你有一个整体的印象:

#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    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

然后开始一点点分析:

#!/usr/bin/env python
  • 每一个python ROS节点在顶部都有一个声明,它使你的程序被作为python脚本来执行。
import rospy
from std_msgs.msg import String
  • 如果要编写ROS节点,则需要导入rospy。std_msgs.msg的导入是为了使我们可以重用std_msgs/String消息类型进行发布。
pub = rospy.Publisher('chatter', String, queue_size=10)
  • 声明你的节点正在使用消息类型String发布到chatter话题上。String实际上是std_msgs.msg.String类。queue_size=10表示队列长度是10,如果任何订阅者没有足够快地接收它们,则限制已排队消息的数量。
rospy.init_node('talker', anonymous=True)
  • 这个非常重要,因为它告诉rospy你的节点名称。直到rospy获得此信息之前,它才能开始与ROS Master进行通信。节点将使用名称talker。 注意:名称不能包含任何斜杠“/”。 anonymous = True通过在名称的末尾添加随机数来确保你的节点具有唯一名称。
rate = rospy.Rate(10)
  • rate对象可以允许你指定自循环的频率。它会追踪记录自上一次调用rate.sleep()后时间的流逝,并休眠直到一个频率周期的时间。参数为10时,我们期望每秒执行10次循环。 简单理解:以每秒 10 次的频率在 chatter 上发布消息。
while not rospy.is_shutdown():
	hello_str = "hello world %s" % rospy.get_time()
    rospy.loginfo(hello_str)
    pub.publish(hello_str)
    rate.sleep()
  • 此循环是相当标准的rospy构造:检查rospy.is_shutdown()标志,然后进行工作。必须通过is_shutdown()来检查程序是否应该退出(例如Ctrl-C)。hello_str = “hello world %s” % rospy.get_time()定义了发布消息的内容是"hello world 时间"。至于这个 %的用法 ,你可以查查python语法。
rospy.loginfo(hello_str)
  • 此循环调用rospy.loginf(), 它执行三项任务:将消息打印到屏幕上,将消息写入node的日志文件,并将消息写入rosout。 rosout是一个方便的调试工具:你可以使用rqt_console提取消息,而不必查找带有node输出的控制台窗口。
pub.publish(hello_str)
  • 将字符串发布到chatter话题上。
rate.sleep()
  • 该循环调用rate.sleep(),该睡眠刚好足够长是为了在整个循环中保持所需的速度,和rate = rospy.Rate(10)对应。
try:
	talker()
except rospy.ROSInterruptException:
	pass
  • 它会捕获rospy.ROSInterruptException异常,当按Ctrl-C或关闭node时,rospy.sleep()和rospy.rate.sleep()可能会引发该异常。

总结:如何实现一个发布者?
• 初始化ROS节点;
• 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;
• 创建消息数据;
• 按照一定频率循环发布消息。

五、Writing the Subscriber Node

在scripts下创建listener.py并确保它有可执行权限

#!/usr/bin/env python
import rospy
from std_msgs.msg import String

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

    # In ROS, nodes are uniquely named. If two nodes with the same
    # name are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber("chatter", String, callback)

    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    listener()

这个和talker.py类似,除了我们已经引入了一种新的基于回调的机制来订阅消息。

rospy.Subscriber("chatter", String, callback)
rospy.spin()
  • 这声明你的节点订阅了消息类型为std_msgs.msg.String的chatter话题。收到新消息时,将以消息(String)作为第一个参数来调用回调函数。rospy.spin()只是使节点无法退出,直到该节点已关闭。与roscpp不同,rospy.spin()不会影响订阅者回调函数机制,因为它们具有自己的线程。

总结:如何实现一个订阅者?
• 初始化ROS节点;
• 订阅需要的话题;
• 循环等待话题消息,接收到消息后进入回调函数;
• 在回调函数中完成消息处理。

六、测试

1.让我们看看src:

在这里插入图片描述

2.启动ROS Master:

roscore

3.启动发布者和订阅者:

在这里插入图片描述
4.rqt可视化:

在这里插入图片描述

七、探索

1.在运行节点后可以关闭roscore,此时也可以正常发布和接收。但是不启动ROS Master直接运行程序却不行。

2.python脚本可以不用编译直接执行,相当于你不用修改CMakeLists.txt文件。但是编译运行需要添加东西。官方Wiki是说:
在这里插入图片描述
在这里插入图片描述
但是在工作空间catkin_make却不能通过,而下面这样可以:

在这里插入图片描述

3.scripts文件夹可以不要,直接放在topic功能包下,这是因为我们的程序以及功能简单,但是我还是希望你放在scripts下,因为以后你的功能包下基本不会只有python脚本,而没有其它文件。

4.可以用下面两行代替上面一行,这样执行效果一样:

在这里插入图片描述
5.关于回调函数:

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

这说明传递过来的是String对象,而消息内容的话当然是String.data(即data.data)。
注意:String是不能直接更改的,因为这是ROS内部封装好的,你只能引用,要是直接更改岂不是乱套了嘛。就像上面的hello_str = String(),然后hello_str = “hello world %s” % rospy.get_time()
而使用String.data替代hello_str.data是错误的。

注:以上完全是自己摸索出来的,小白看不懂没有关系,还有大家摸索出来其他东西或者和我的类似,或者知道这其中原理的,欢迎交流哟!

八、话题通信机制

1.基本概念:
在这里插入图片描述
2.话题通信机制:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本文内容参考:
ROS官方wiki:http://wiki.ros.org
古月——ROS入门21讲
《ROS机器人开发实践》

如有错误或者不足之处,欢迎大家留言指正!

  • 33
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
### 回答1: 关于ROS的发布和订阅话题,它是ROS中常用的一种通信方式。发布者发布消息到话题中,而订阅者则可以从话题中获取消息。通过话题的发布和订阅机制,节点之间可以进行高效的数据传输和信息共享。具体实现可以使用ROS提供的rospy库来完成。 ### 回答2: ROS是机器人操作系统(Robot Operating System)的简称,是一个用于编写机器人软件的开源框架。在ROS中,发布和订阅话题是非常常见的通信方式。 发布者Publisher)和订阅者(Subscriber)是ROS中的两种角色。发布者负责向话题中发布消息,而订阅者则负责从话题中接收消息。 在ROS中,发布和订阅话题C可以通过以下步骤进行: 1. 创建一个话题C。 在ROS中,可以通过编写一个发布器节点来创建一个话题C。发布器节点负责向话题C中发布消息。 2. 编写一个发布器节点。 发布器节点可以使用ROS提供的编程语言(如C++或Python)来编写。在节点中,需要进行ROS初始化,并创建一个发布者对象来发布消息到话题C。 3. 编写一个订阅器节点。 订阅器节点也需要使用ROS提供的编程语言来编写。在节点中,也需要进行ROS初始化,并创建一个订阅者对象来接收话题C中的消息。 4. 运行发布器节点和订阅器节点。 在终端中,可以使用rosrun命令来分别运行发布器节点和订阅器节点。 5. 订阅器节点接收发布器节点发布的消息。 当发布器节点向话题C中发布消息时,订阅器节点将能够接收到该消息,并对消息进行处理。 通过发布和订阅话题C,可以实现不同节点之间的信息交流。发布者节点可以发布各种类型的消息到话题C中,而订阅者节点可以根据自身的需要从话题C中接收并处理消息。这种基于话题的通信方式使得ROS中不同节点之间能够有效地协作和共享信息,从而更好地完成机器人的各种任务。 ### 回答3: ROS(Robot Operating System)是一个用于构建机器人应用程序的开源框架。在ROS中,发布者订阅者是两个常用的概念,用于实现不同节点的通信。 在ROS中,发布者用于发布一个话题(Topic),而订阅者则用于订阅该话题。话题是ROS中的一种消息机制,通过话题可以在不同节点之间传递数据。 具体到题目中的情况,如果要使用ROS发布和订阅话题c,首先需要创建一个发布者节点和一个订阅者节点,并且定义话题c的消息类型。 对于发布者节点,它会发送某个类型的消息到话题c。代码中需要指定发布者节点要发布的消息类型,以及话题的名称c。然后,在发布者节点中通过调用ROS提供的API函数,将消息发送到话题c。 对于订阅者节点,它会订阅话题c,接收发布者节点发送的消息。同样,代码中需要指定订阅者节点要订阅的消息类型,以及话题的名称c。然后,在订阅者节点中通过调用ROS提供的API函数,接收话题c中的消息。 总的来说,ROS发布和订阅话题c的过程就是发布者节点将消息发送到话题c,而订阅者节点通过订阅话题c接收消息。通过这种方式,不同节点之间可以灵活地进行消息传递和通信,从而实现更复杂的机器人应用程序。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☆下山☆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值