写一个简单的消息发布器和订阅器 Python
写一个学习笔记方便自己以后回查, 其实也是跟着官方教程在走
写一个发布器节点
节点就是一个可以用来联入Ros网络的单位, 我们现在来写个发布器节点, 它会在整个ROS网络里广播信息.
确认setup catkin workdpace 以后, 进入beginner_tutorial程序包
roscd beginner_tutorials
The Code
用script文件夹来保存我们发布器的功能脚本源码
mkdir scripts
cd scripts
下载官网的脚本, 并且给执行权(chmod +x talker.py
)
wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py
chmod +x 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
在CMakeLists.txt文件里加入下面的代码 来确保python的脚本可以安装, 并且用上正确的解析器
catkin_install_python(PROGRAMS scripts/talker.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
The Code Explained
我们分步解释代码,算了解释个卵直接在文件里注释好了.
#!/urs/bin/env python # 只要是python写的,这一行必须要写在文件顶部
# 意思是文件为在env环境设置下以 解释器python 运行
# 个人觉得这里已经就是以anaonda3的python在跑了
# 其实这里是读取第一行的整行,所以如果你在第一行
# 后面加注释(我这里就是个错误示范),那么会报错
# /opt/ros/melodic/bin/rosrun: /home
# /urs/bin/env: bad interpreter:
# No such file or directory
# 所以加注释也只能从第二行开始
# license removed for brevity # 这个无所谓
import rospy # 这里必须要引入这个包,因为基本上所有的基础功能都在里面
# 人家名字也很明白,rospy: rospython, python版的ROS基础功能
from std_msgs.msg import String # ROS 的消息功能的工具基本都在这个包里了,我们这里用 String
def talker():
pub = rospy.Publisher("chatter", String, queue_size=10) # 创建一个发布器对象(发布内容为string,
# 单次发送的长度为10)
# 这个对象发布的话题名字叫'chatter'
rospy.init_node('talker', anonymous=True) # 这里初始化表示这个文件要创建为一个
# ros节点, 名字叫talker(名字其实你随便取)
rate = rospy.Rate(10) # 创建一个rate对象,设置为10赫兹
# 于是在循环里就会以10Hz来循环
# 因为可以调整sleep()函数的执行时间
while not rospy.is_shutdown(): # 如果这个节点没有被关闭
hello_str = "hello world %s" % rospy.get_time() # 消息就是helloworld了
rospy.loginfo(hello_str) # 在log上记录一发这个消息
pub.publish(hello_str) # pub这个发布器对象向ros网络里
# chatter这个话题,发布
# hello_str 这个消息
rate.sleep() # 正常休眠,等待再次循环
if __name__ == '__main__':
try:
talker() # 执行talker函数
except rospy.ROSInterruptException: # 用户如果kill了这个进程
pass # 结束
写一个订阅器节点python
代码
roscd beginner_tutorials/scripts/
wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/listener.py
chmod +x 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()
接下来编辑CMakeLists.txt文件, 变成下面这样:
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
代码解释
下面直接注释了,不分步来解释了:
#!/usr/bin/env python # 这里其实就是叫文件执行的时候在命令行输入
# /usr/bin/env python, 自然就进入了python编程环境
# 我觉得吧, ros读取第一个 # 字符然后弄后面的终端命令
# 再编辑后面的代码来执行
# 其实这里是读取第一行的整行,所以如果你在第一行
# 后面加注释(这里就是个错误示范),那么会报错
# /opt/ros/melodic/bin/rosrun: /home
# /urs/bin/env: bad interpreter:
# No such file or directory
# 所以加注释只能从第二行开始
import rospy # 导入python工具包
from std_msgs.msg import String # 导入信息工具包(我觉得其实导入什么包都行了)
# 只要在CMakeList里包含进来有依赖的都可以的样子
def callback(data):
'''
这是一个callback函数,会在订阅器里一直执行,所以后面由订阅器对象来调用
在日志上记录一发, 我估计订阅器接受到的消息是一个data对象
这个对象里的data属性才是我们python能操作的数据但貌似也是String类型
'''
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
# 其实这里已经可以拿收到的数据了
# return data.data
def listener():
rospy.init_node('listener', anonymous= True) # 这个文件即将创建一个ros节点,名字叫listener,
# 而且允许其它节点同名(本质上不同名的,因为
# 程序后面会自己给它们的名字一个unique编码)
rospy.Subsriber('chatter', String, callback) # 创建一个订阅器订阅'chatter'这个话题,并用
# callback函数处理接受到的消息
rospy.spin() # 如果节点没被停止,就一直挂着
if __name__ == '__main__': # 执行listener函数
listener()
最后进行编译节点
注意要在工作空间下编译
$ cd ~/catkin_ws
$ catkin_make
测试消息发布器和订阅器
这里直接写python的测试了
启动发布器
$ roscore
catkin specific 如果使用catkin,确保你在调用catkin_make后,在运行你自己的程序前,已经source了catkin工作空间下的setup.sh文件:
# In your catkin workspace
$ cd ~/catkin_ws
$ source ./devel/setup.bash
在上一个教程中我们制作了一个叫做"talker"的消息发布器,让我们运行它:
rosrun beginner_tutorials talker.py (Python)
你将看到如下的输出信息:
rosrun beginner_tutorials talker.py
/opt/ros/melodic/bin/rosrun: /home/kuo/Desktop/catkin_ws/src/beginner_tutorials/scripts/talker.py: /urs/bin/env: bad interpreter: No such file or directory
/opt/ros/melodic/bin/rosrun: line 116: /home/kuo/Desktop/catkin_ws/src/beginner_tutorials/scripts/talker.py: Success
艹, 不过没事, 解决它就好, 我发现是因为我后面写了注释的原因把注释换一行就好了
改成这样
另一个文件也一样
我们再次测试, 运行成功~
运行订阅器,也受到消息了~
参考文献
留坑:
讨论一下上面文件的第一行, #!/usr/bin/env
在命令行/usr/bin/env
直接输入上面命令,显示如下:
一眼瞅过去这感觉就是一个环境配置的文档. 那里面其实已经包含了anaconda的执行文件bin x64
所以我估计还是以conda的内核再跑python
当输入 /usr/bin/env python
时:
还是老老实实的python, 我估计这时其实已经是可以用该环境下已经安装的各种包了
看了看目前还是不太清楚如何制定python解释器的相关环境, 特别是anaconda里, 先留坑把, 目前想的是之所以很离谱是因为,python 执行的时候就已经是当前的python核了,不可能在换进程来执行, 第二点就是其实这个python是anaconda base的环境, 之所以import不了torch,是因为这个环境我没装torch,那么问题来了如何让ros使用虚拟环境里的python kernel呢? 我估计要么只能在虚拟环境里再安装一次ROS, 要么去改ROS的配置文件,至于怎么改,目前没精力去研究.