【ROS】如何让ROS中节点实现数据交换Ⅰ--ROS话题通信

简介: 比较常用的目前就这一些,之后的命令现用现学就好了

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。


5efac1ab537f44ea95f1e56e1fa04c5d.jpg


0.ROS文件系统及常用指令


roscore 启动ros核心节点

roscd 将工作空间切换到指定ros功能包

catkin_create_pkg 将工作空间切换到指定ros功能包

**rqt_graph 启动节点间的关系图


8aab9af39ca841738be85e27150742ab.png


rosrun 包名 节点名称 启动节点(rosrun turtlesim turtlesim_node)

roslaunch 包名 launch文件名称 启动Launch文件

比较常用的目前就这一些,之后的命令现用现学就好了


1.话题通信概念


在ros中,机器人的各个部件(雷达|摄像头等部件)相互之间通信需要用到一种通信方式:话题通信,其理论模型为


f7bf10f62f154fe5bba5f4c47d96f7c5.png


这里有一个简单的定义:订阅方与发布方通过同一个话题连接起来相互,发布方提供消息,订阅方获得消息,是一个单向的过程,虽然在这过程中似乎没有出现ros master这个角色,但发布方向订阅方第一次发送消息需要经过rosmaster,再到订阅方.(从上图也可以看出),在此之后就不需要rosmaster了


订阅方与与发布方都可以有多个,启动也无先后顺序


2.利用标准消息类型实现话题通信实现(python)


这里我们采用python实现,在接触到的机器人二次开发中大多用的都是python

当然,二者思想差不多,且ros当中用不同语言写的各个节点之间也是可以直接互相通信的


2.1发布方实现


先来分析下需求


1.初始化ros节点

2.创建发布者对象

3.组织发布逻辑,编写发布数据


接下来总体描述下如何写这段程序,


1.导入rospy,其是一个ros python标准包,以及从标准消息中导入String这个类型

2.初始化当前节点init_node(节点名称)

3.实例化发布对象Publisher(话题名称,消息类型,等待消息队列(可不填 默认10))

4.创建消息对象

5.实例化Rate对象,设置消息频率Rate(HZ)

6.当节点不被关闭时循环执行 is_shutdown()

7.将消息对象赋值,利用pub发布对象发布信息publish(消息对象)

8.在屏幕上打印出发送信息,实现消息反馈loginfo(字符串)

9.设置休眠时间,与上文设置的Rate频率相关


import rospy
from std_msgs.msg import String
rospy.init_node("pub")
pub=rospy.Publisher("che",String,queue_size=10)
msg=String()
rate=rospy.Rate(1)
i=0
while not rospy.is_shutdown():
    msg.data="hello "+(str)(i)
    pub.publish(msg)
    i+=1
    rospy.loginfo(msg.data)
    rate.sleep()


最后为这个py文件加上可执行权限,在当前功能包路径下的CMakelist中将刚刚的python文件添加到这里


c9545384d43944839184312ebab71efa.png


( 并在catkin_ws也就是ros根目录空间下执行source ./devel/setup.bash)在终端执行rosrun 包名 话题名即可运行


98ddefe9fc174df59e9790c37d8ff267.png


这就是话题通信的发布方实现,接下来我们再来看看订阅方是如何实现的


2.2订阅方实现


1.初始化ros节点

2.实例化订阅方对象

3.处理订阅到的消息


接下来总体描述下如何写这段程序,


1.导入rospy,其是一个ros python标准包,以及从标准消息中导入String这个类型

2.初始化当前节点init_node(节点名称)

3.实例化接受对象Subsrciber(话题名称,消息类型,回调函数,等待消息队列(可不填 默认10))

4.这里的回调函数相当于一个函数指针,实例化这个对象的时候会调用回调函数对消息进行一个处理

5.所以回调函数的传入参数就是收到的消息类型,我们把他在屏幕上打印出来就可以了

6.使节点一直处于活跃状态,能处理接收到的消息spin()


import rospy
from std_msgs.msg import String
def callback(msg):
    rospy.loginfo(msg.data)
rospy.init_node("sub")
sub=rospy.Subscriber("che",String,callback,queue_size=10)
rospy.spin()


最后为这个py文件加上可执行权限


在当前功能包路径下的CMakelist中将刚刚的python文件添加到这里(在noetic版本之前不需要执行这一步操作


5d48f3ff11e44f09a937c7dec7d5afcf.png


并在catkin_ws也就是ros根目录空间下执行source ./devel/setup.bash


在终端执行rosrun 包名 话题名即可运行并编译一下

我们也尝试运行下这个代码,方法与上文相同


1.先运行一下pub节点


2ba454ab8b444268ab7a312675f2f742.png


2.新打开一个终端,在运行一下sub节点


006bfca37ba64d85ac3c2dc14836bea9.png


成功啦,这就是利用标准消息参数进行话题通信。


3.利用自定义消息类型实现话题通信(python)


数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息… std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型


这部分内容主要代码是与上文相同,仅将std_msgs.msg替换成了自己设定的库,所以主要是修改配置文件的过程。


1.首先在当前功能包下创建一个msg的文件夹,里面存放你的自定义消息类型


5ec0c64a41674d9ca3a4809e6ac18c01.png


2.创建一个.msg的消息类型,我这里的名字是Person.msg,里面有三个标准类型


string name


int32 age


float32 height


3.在功能包目录下的package.xml中加入这两行(54与59)


5e4b954da0a64f9cb12a1d31a50d2a57.png


其中54行的message_generation是编译时的消息软件包

而59行message_runtime是运行时的消息软件包


4.在CMakeList中找到这些地方并修改


find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
## 配置 msg 源文件
add_message_files(
FILES
Person.msg
)
# 生成消息时依赖于 std_msgs
generate_messages(
DEPENDENCIES
std_msgs
)
#执行时依赖
catkin_package(
CATKIN_DEPENDS  rospy std_msgs message_runtime
)


5.编译一下 可以在/工作空间/devel/lib/python3/dist-packages/包名/msg找到刚刚生成的消息类型


3b2a1d139bb944cca2205fcc0f3f6427.png


6.之后要使用在这个消息包可以直接在代码中导入就可以了


# from ros包名.msg import 消息名称
from lesson2.msg import Person 


3.1自定义消息类型话题通信发布方实现


实现方法与之前的标准消息类型话题通信相同,仅在消息内容定义不同,所以这里就不过多赘述。

消息类型初始化的成员名与自定义消息类型中的成员名相同似乎有点废话hhhh


import rospy
from lesson2.msg import Person
rospy.init_node("pub_person")
pub=rospy.Publisher("che",Person)
p=Person()
p.name="奥特曼"
p.age=8
p.height=1.5
rate=rospy.Rate(1)
while not rospy.is_shutdown():
    pub.publish(p)
    rate.sleep()
    rospy.loginfo("%s,%d,%f",p.name,p.age,p.height)


3.2自定义消息类型话题通信接收方实现


from lesson2.msg import Person
import rospy
def doMsg(p):
    rospy.loginfo("%s,%d,%.2f",p.name,p.age,p.height)
rospy.init_node("sub_person")
#话题通信的话题必须与发布方相同
sub=rospy.Subscriber("che",Person,doMsg)
rospy.spin()


最后配置下CMakeList就可以运行了(在noetic版本之前不需要执行这部操作)

rosrun lesson2 demo02_pub.py
rosrun lesson2 demo02_sub.py

bfa7da74273e4aaab2be1a62d7002289.png


cb3b3b488a71470fb51aa3beb447c86c.png


成功啦,这就是利用自定义参数进行话题通信。

相关实践学习
Docker镜像管理快速入门
本教程将介绍如何使用Docker构建镜像,并通过阿里云镜像服务分发到ECS服务器,运行该镜像。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
目录
相关文章
|
9月前
|
Python
ROS节点检测ArUco标签并记录空间坐标
利用Realsense D435i相机检测ArUco标签,使用Python程序订阅相机的ROS话题,记录Time和标签的XYZ值,储存在一个csv文件中;当出现识别不到标签或者反馈坐标为0,0,0的情况时,不进行记录。
172 0
|
9月前
|
存储 缓存 算法
【ROS】如何让ROS中节点获取数据 III --参数服务器通信及ros常用工具指令介绍
相较于之前的通信模型,参数服务器是最为简单的。在之前的模型中,ROSMASTER都是扮演一个帮二者连接在一起的桥梁。
181 0
|
3月前
|
机器人 C++ Python
[ROS2] --- 通信接口
[ROS2] --- 通信接口
[ROS2] --- 通信接口
|
3月前
|
C++ Python
[ROS2] --- 手动编写一个节点
[ROS2] --- 手动编写一个节点
34 1
|
9月前
|
XML 机器人 C++
【4. ROS的主要通讯方式:Topic话题与Message消息】(2)
【4. ROS的主要通讯方式:Topic话题与Message消息】(2)
148 0
|
9月前
|
传感器 机器人 C++
【4. ROS的主要通讯方式:Topic话题与Message消息】(1)
【4. ROS的主要通讯方式:Topic话题与Message消息】(1)
195 0
|
9月前
|
算法 C语言 C++
【ROS】服务通信、话题通信的应用
现在可以直接使用键盘来控制乌龟运动了
71 0
|
9月前
|
算法 中间件 C语言
【ROS】如何让ROS中节点实现数据交换Ⅱ --服务通信
在ros中,一个节点想要获取某种服务(例如:一个节点想要获取此时的相机数据,节点就需要向相机发送一个请求,而相机接收到请求后可以根据消息类型将数据类型返回),这就是基本的服务通信使用场景。
101 0
|
算法 机器人 定位技术
ROS中阶笔记(八):机器人SLAM与自主导航—机器人自主导航
ROS中阶笔记(八):机器人SLAM与自主导航—机器人自主导航
870 0
ROS中阶笔记(八):机器人SLAM与自主导航—机器人自主导航
|
2月前
|
网络协议 机器人 中间件
单片机和FreeRTOS上跑机器人ROS的应用
单片机和FreeRTOS上跑机器人ROS的应用
74 0

推荐镜像

更多