ROS版本: ROS Kinetic
操作系统:Ubuntu16.04 LTS
参考网站
https://blog.csdn.net/ethan_guo/article/details/80226121
当然也可以用python 实现,我们与例程中的方法为例,这里只谈如何实现在类的订阅并讨论其机制。telker代码不变:
#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('hello', String, queue_size=1)
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
以下是listener 代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
import time
pub = rospy.Publisher('pub_with_sub', String, queue_size=10) #发布话题设为全局变量
class listener():
def __init__(self):
print("class comeing!")
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("hello", String, self.callback,queue_size = 1)
# spin() simply keeps python from exiting until this node is stopped
def callback(self,data):
rospy.loginfo( "I heard %s", data.data)
print("call back comeing!")
pub.publish(data.data)
if __name__ == '__main__':
listener()
print("class circulation!!")
rospy.spin()
执行这两端代码,观察输出,可以发现只有在启动时,会执行
print("call back comeing!")
print("class comeing!")
这两段代码,而回调函数中的
print("call back comeing!")
会在每次订阅到发布的消息后执行,这里就涉及到rospy.spin()的工作机制,它并不是一直循环这个listener()类。而是循环进入类后的订阅函数,这个函数叫做ROS消息回调处理函数。可以参考官方网站查看其具体原理。
到这里其实还有一个小问题,那就是关于画图,如果我们想在回调函数中实现画图,或者在回调函数中修改变量的值,而在类的构造函数中执行与此变量有关的操作,那么我们只需要在类中加一个循环即可:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
import time
pub = rospy.Publisher('pub_with_sub', String, queue_size=10) #发布话题设为全局变量
class listener():
def __init__(self):
print("class comeing!")
self.da = []
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("hello", String, self.callback,queue_size = 1)
# spin() simply keeps python from exiting until this node is stopped
#############加入的循环####################
while not rospy.is_shutdown():
print(self.da)#此处可以是画图的语句
##########################################
def callback(self,data):
rospy.loginfo( "I heard %s", data.data)
self.da = data.data
print("call back comeing!")
pub.publish(data.data)
if __name__ == '__main__':
listener()
print("class circulation!!")
rospy.spin()
这时候可以发现,回调函数中得到的变量在构造函数的循环中执行了。实时画图在后面的文章中讨论。
下面介绍一下Python中用全局变量的方法实现.
以ros wiki上面的话题通信教程为例。
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28python%29
这里定义了talker 和 listener :
talker:
#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('pub1', String, queue_size=1)
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
这里我么修改listener,在文件中加入了一个全局变量pub,然后直接将订阅的话题通过
pub再次发布出去,当然,这里只是个测试,实际中肯定是对该消息进行处理后再发布的,写改后的listener如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
import time
pub = rospy.Publisher('pub_with_sub', String, queue_size=10) #发布话题设为全局变量
def callback(data):
rospy.loginfo( "I heard %s", data.data)
pub.publish(data.data)
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("pub1", String, callback,queue_size = 1)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
这时,我们像教程中一样运行这两个程序结果并没有什么区别,但如果我们用rostopic list 查看,就会发现比原教程中多了一个话题,就是问在listener中发布的,接下来,我们创建一个listen_listener.py的文件来订阅这个话题:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
import time
def callback(data):
rospy.loginfo( "I heard %s", data.data)
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("pub_with_sub", String, callback,queue_size = 1)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
ok,别忘了将文件设置为可执行文件,这是后,我们同时打开这三个文件。会发现显示同样的内容。实际上是这样一个结构:
talker发布->listener订阅 再发布 -> listen_listener再订阅!