1.编写发布节点
$ roscd beginner_tutorials #切换到package文件夹下
$ mkdir scripts # 新建存放Python脚本的文件夹
$ cd scripts #切换
#例程中的文件下载。talker.py publisher脚本
$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py
$ chmod +x talker.py # 对文件添加可执行指令
talker.py 文件中内容说明:
#!/usr/bin/env python
# license removed for brevity
import rospy # 编写ROS节点,则需要导入rospy
from std_msgs.msg import String # std_msgs.msg 导入是为了我们可以 reuse std_msgs / String消息类型(一个简单的字符串容器
#container)进行发布。
def talker():
#这部分代码定义了讲talker与其余ROS的接口。
# 声明节点使用消息类型String发布到chatter topic 。 这里的字符串实际上是类std_msgs.msg.String
#queue_size参数在ROS hydro中是新的参数 ,如果任何订户没有fast enough接收它们,则限制排队消息的数量。 在旧的ROS发行版中,只省略
#这个参数
pub = rospy.Publisher('chatter', String, queue_size=10)
# 声明节点的名字,直到rospy有这个信息,它才能开始与ROS Master通信。
# 名称必须是base name,即它不能包含任何斜杠“/”。
# anonymous = True通过在NAME末尾添加随机数来确保节点具有唯一名称。
rospy.init_node('talker', anonymous=True)
# 此行创建Rate对象速率。
# 借助其方法sleep(),它提供了一种以所需速率循环的便捷方式。 它的参数为10,我们期望每秒循环10次(处理时间不超过1/10秒)
rate = rospy.Rate(10) # 10hz
# 这个循环是一个相当标准的rospy构造:检查rospy.is_shutdown()标志然后工作。
#检查is_shutdown()以检查程序是否应该退出(例如,如果有Ctrl-C或其他)。 在这种情况下,“work”是对pub.publish(hello_str)的
#调用,它将字符串发布到chatter主题。 循环调用rate.sleep(),它sleep时间足够长,可以通过循环保持所需的速率。
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
# 这个循环还调用rospy.loginfo(str),它执行三重任务:消息被打印到屏幕,它被写入Node的日志文件,并被写入rosout。
# rosout对于调试非常方便:可以使用rqt_console来提取消息,而不必使用Node的输出找到控制台窗口。
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
除了标准的Python __main__检查之外,这还会捕获一个rospy.ROSInterruptException异常,当按下Ctrl-C或者你的节点关闭时,rospy.sleep()和rospy.Rate.sleep()方法可以抛出该异常。 引发此异常的原因是,您不会在sleep()之后意外地继续执行代码。
2.编写订阅节点
$ roscd beginner_tutorials/scripts/
$ wget https://raw.github.com/ros/ros_tutorials/kineticdevel/rospy_tutorials/001_talker_listener/listener.py
$ chmod +x listener.py
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
# node 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)
# 这声明节点订阅了std_msgs.msgs.String类型的chatter主题。收到新消息时,将调用回调,并将消息作为第一个参数。
# 我们也稍微改变了对rospy.init_node()的调用。 我们添加了anonymous = True关键字参数。 ROS要求每个节点都有唯一的名称。
# 如果出现具有相同名称的节点,则会突然显示前一个节点。 这样可以很容易地将故障节点从网络中踢出。 anonymous = True标志告诉
# rospy为节点生成一个唯一的名称,以便可以轻松运行多个listener.py节点。
# spin() simply keeps python from exiting until this node is stopped
# 最后添加,rospy.spin()只是让节点退出,直到节点关闭。 与roscpp不同,rospy.spin()不会影响订阅者回调函数,因为它们
# 有自己的线程。
rospy.spin()
if __name__ == '__main__':
listener()
3.编译现在的节点
使用CMake作为构建系统,即使是Python节点也必须使用它。 这是为了确保创建消息和服务的自动生成的Python代码。
转到catkin工作区并运行catkin_make:
$ cd ~/catkin_ws
$ catkin_make
测试Publisher和Subscriber (Python)
$ roscore
新开一个终端:
# In your catkin workspace
$ cd ~/catkin_ws
$ source ./devel/setup.bash
$ rosrun beginner_tutorials talker.py
再开一个终端:
# In your catkin workspace
$ cd ~/catkin_ws
$ source ./devel/setup.bash
$ rosrun beginner_tutorials listener.py
效果为: