ROS写一个简单的消息发布器和订阅器 (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

chmod +x的解释

这里代码不长直接手打

#!/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

在这里插入图片描述
艹, 不过没事, 解决它就好, 我发现是因为我后面写了注释的原因把注释换一行就好了
在这里插入图片描述
改成这样
在这里插入图片描述
另一个文件也一样
在这里插入图片描述

我们再次测试, 运行成功~
在这里插入图片描述
运行订阅器,也受到消息了~
在这里插入图片描述

参考文献

ros官方教程







留坑:

讨论一下上面文件的第一行, #!/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的配置文件,至于怎么改,目前没精力去研究.


2020-12-10 填坑

这里填上面的坑了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值