4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
热卖商品
新闻详情
ROS话题和服务_足迹-CSDN博客
来自 : CSDN技术社区 发布时间:2021-03-25
基本概念

ROS中有四种通信方式 Topic(话题)、Service(服务)、Parameter Serivce(参数服务器)、Actionlib(动作库)。

所谓通信 ros中每个程序包是一个node(节点) 通信就是节点与节点间的数据传输 在这里简要介绍一下话题与服务

话题与服务的简单比较 Topic话题Service服务

节点A—— 话题T 节点A发布话题T

话题T—— 节点B 节点B订阅话题T

节点A—— 服务节点S 节点A请求服务S

服务节点S ——节点A  服务S响应节点A

异步通讯   

A发了朋友圈 B刷朋友圈的时候看到了

A发布话题 B订阅话题 朋友圈是话题T

同步通讯 

A发了朋友圈 并让S去给A点赞 S点赞完告诉A。

A请求S点赞 B响应A的请求。A是客户端节点 S是服务节点

话题内容的数据格式——msg

服务的通信数据格式——srv用于连续高频的数据发布和接收 雷达测障碍物、里程计等用于偶尔调用的功能或执行某一项功能 拍照、语言识别等实现

在catkin_ws下我们创建一个新的ros包

cd catkin_wscatkin_create_pkg h_h std_msgs rospy roscpp

这条命令的意思是 切换到catkin_ws目录下 创建ROS包(roscreate-pkg) 包的名称是h_h 带有std_msgs rospy roscpp三个依赖项 会在src下生成h_h的文件夹 h_h文件夹下有include、src两个文件夹和CMakeLists.txt、package.xml两个文件

在表格中提到了数据格式 msg和srv。在实现话题通信和服务通信之前 先来看一看msg数据格式。

使用msg

步骤 建立.msg文件——修改package.xml——修改CMakeLists.txt——编译

建立.msg文件

cd ~/catkin_ws/src/h_h //创建的包的目录下mkdir msg //新建msg文件夹touch abc.msg //建立abc.msg的文件

双击打开abc.msg 记住这个名字 定义数据类型 举例

\"\"

字符串的s 浮点型的x 浮点型的y。

修改package.xml

我们打开h_h文件夹下的package.xml文件 将下面两句话取消注释

 build_depend message_generation /build_depend exec_depend message_runtime /exec_depend 

第一句用于build 构建 、第二句用于exec 执行 。

有效的package.xml文件

 ?xml version 1.0 ? package format 2 name h_h /name version 0.0.0 /version description The h_h package /description maintainer email jtl todo.todo jtl /maintainer license TODO /license build_depend message_generation /build_depend exec_depend message_runtime /exec_depend buildtool_depend catkin /buildtool_depend build_depend roscpp /build_depend build_depend rospy /build_depend build_depend std_msgs /build_depend build_export_depend roscpp /build_export_depend build_export_depend rospy /build_export_depend build_export_depend std_msgs /build_export_depend exec_depend roscpp /exec_depend exec_depend rospy /exec_depend exec_depend std_msgs /exec_depend export /export /package 

修改CMakeLists.txt

同样在h_h文件夹下 打开CMakeLists.txt 取消一些注释并添加

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation ##新添加)
 add_message_files( ##取消注释 FILES ##取消注释 abc.msg ##新添加 就是我们新建的.msg文件 )
 generate_messages( ##取消注释 DEPENDENCIES ##取消注释 std_msgs ##取消注释 )
catkin_package( CATKIN_DEPENDS message_runtime roscpp rospy std_msgs #取消注释 添加message_runtime)

编译 修改完package.xml和CMakeLists.txt 我们回到catkin_ws 目录下进行编译 catkin_make

cd /catkin_wscatkin_make
话题发布和订阅实现

我们在h_h文件夹下 新建test文件夹

roscd h_h/mkdir testcd test

在test文件夹下新建talker.py

#!/usr/bin/env python#coding utf-8import rospy #添加rospy的库from std_msgs.msg import String #系统的std_msgs文件夹下有已经定义的String类 没用到from h_h.msg import * #h_h文件夹下msg文件夹下 abc.msg 这句话就是把abc加载进来def talker(): #节点发布‘detection’话题 使用了abc类型 queue_size 是缓存的长度 pub rospy.Publisher( detection ,abc,queue_size 10) #初始化节点 talker anonymous True用于保证节点名称唯一 rospy.init_node( talker , anonymous True) rate rospy.Rate(1) # 1hz while not rospy.is_shutdown(): #循环发送 #rospy.get_time() 获得时间 hello_str hello world %s % rospy.get_time() #打印日志信息表 rospy.loginfo(hello_str) x 1.0 y 2.0 #话题发布了三个参数 pub.publish(hello_str,x,y) #速率控制 rate.sleep()if __name__ __main__ : try: talker() except rospy.ROSInterruptException: pass

代码中有注释 这里详细说一下参数的传递 我们之前在h_h/msg/文件夹下建立了abc.msg 在头文件中加载abc 然后在pub rospy.Publisher( detection ,abc,queue_size 10)中第一次提到了abc 我们发布话题需要有abc类型的参数传递。

最后在pub.publish(hello_str,x,y)中向外发布了三个参数hello_str,x,y 记得我们在abc.msg中填入了什么 string s float32 x float32 y。所以publish发布的三个参数正好对应abc.msg中的参数。

在test文件夹下新建listener.py

#!/usr/bin/env python#coding utf-8import rospy #添加rospy的库from std_msgs.msg import String #系统的std_msgs文件夹下有已经定义的String类 没用到from h_h.msg import * #h_h文件夹下msg文件夹下 abc.msg 这句话就是把abc加载进来def callback(data): #参数传递 data中就是abc.msg中的参数 rospy.loginfo( I heard %s , data.s) print(data.x,data.y)def listener(): #初始化节点 listener 保证节点唯一 因此可以有多个listener.py可以同时运行 rospy.init_node( listener , anonymous True) #节点订阅detection’话题 使用了abc类型 调用callback函数 rospy.Subscriber( detection , abc, callback) #rospy.spin()简单保持你的节点一直运行 直到程序关闭 rospy.spin()if __name__ __main__ : listener()

我们来看一下运行结果

分别在三个终端中输入

roscore
rosrun h_h talker.py
rosrun h_h listener.py

结果如图

\"\"\"\"

我们可以看到在talker中  打印了日志信息 在listener中打印了日志信息 也输出了data.x和data.y。

使用srv

这一步与msg的方法极其相似

步骤 建立.srv文件——修改package.xml——修改CMakeLists.txt——编译

建立.srv文件

cd ~/catkin_ws/src/h_h //创建的包的目录下mkdir srv //新建srv文件夹touch qq.srv //建立qq.srv的文件

双击打开qq.srv 同样记住这个名字 定义数据类型 举例

\"\"

注意有float32 a 和float32 b 中间‘---’ 下面是float32 Sum和string qq。简单说明一下

srv类型的数据传递是双向的 上面部分a和b是客户端传递给服务器的数据 ‘---’ 的下面部分是服务器回传给客户端的数据。

修改xml文件同msg类型的一模一样;

修改CMakeLists.txt同msg类型的类似 唯一的不同点是不需要add_message_files而需要add_service_files

 add_service_files( #取消注释 FILES #取消注释 qq.srv #添加 我们新建的.srv文件 )

当然如果msg类型和srv类型都有 则这两个都需要 CMakeLists.txt 如下。

cmake_minimum_required(VERSION 2.8.3)project(h_h)find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)## Generate messages in the msg folder add_message_files( FILES abc.msg )## Generate services in the srv folder add_service_files( FILES qq.srv )## Generate added messages and services with any dependencies listed here generate_messages( DEPENDENCIES std_msgs )catkin_package( CATKIN_DEPENDS message_runtime roscpp rospy std_msgs)include_directories( ${catkin_INCLUDE_DIRS})

编译 修改完package.xml和CMakeLists.txt 我们回到catkin_ws 目录下进行编译 catkin_make

cd /catkin_wscatkin_make
服务请求和响应的实现

同样在test文件夹下 新建h_h_server.py:

#!/usr/bin/env python#coding utf-8#加载h_h.srv文件夹下的内容 即qq.srvfrom h_h.srv import *import rospyNAME add_two_ints_server def add_two_ints(req): #从客户端读入req req.a和req.b对应了qq.srv中的a和b print( Returning [%s %s %s] % (req.a, req.b, (req.a req.b))) sum req.a req.b q 1234567 #从服务器返回两个参数给客户端 sum和q是qq.srv中的Sum和qq return qqResponse(sum,q)def add_two_ints_server(): rospy.init_node(NAME) #初始化一个节点 #构建一个服务 add_two_ints 是服务的名称 qq是参数(qq.srv) add_two_ints是调用函数 s rospy.Service( add_two_ints , qq, add_two_ints) print Ready to add Two Ints # 保持运行 rospy.spin()if __name__ __main__ : add_two_ints_server()

新建h_h_clinet.py:

#!/usr/bin/env python#coding utf-8import sysimport osfrom h_h.srv import *import rospy## add two numbers using the add_two_ints service## param x int: first number to add## param y int: second number to adddef add_two_ints_client(x, y): #等待服务 rospy.wait_for_service( add_two_ints ) try: #创建服务的处理句柄 即客户端调用 add_two_ints 服务 qq是参数数据格式 add_two_ints rospy.ServiceProxy( add_two_ints , qq) print( Requesting %s %s % (x, y)) # simplified style 简单方式 将两个参数传给服务器 返回resp1是服务器的返回值 resp1 add_two_ints(x, y) # formal style 正式的方式 resp2是服务器的返回值 resp2 add_two_ints.call(qqRequest(x, y)) #校验 if not resp1.Sum (x y): raise Exception( test failure, returned sum was %s % resp1.Sum) if not resp2.Sum (x y): raise Exception( test failure, returned sum was %s % resp2.Sum) #返回值 resp1.Sum 对应qq.srv中的Sum 并没有返回resp1.qq return resp1.Sum except rospy.ServiceException, e: print( Service call failed: %s % e)def usage(): return %s [x y] % sys.argv[0]if __name__ __main__ : #rosrun时候的输入附带参数 argv rospy.myargv() if len(argv) 1: import random x random.randint(-50000, 50000) y random.randint(-50000, 50000) elif len(argv) 3: try: x int(argv[1]) y int(argv[2]) except: print usage() sys.exit(1) else: print usage() sys.exit(1) print ( %s %s %s % (x, y, add_two_ints_client(x, y)))

我们来看一下运行结果

分别在三个终端中输入

roscore
rosrun h_h h_h_server.py 
rosrun h_h h_h_clinet.py 

结果如图

\"\"

\"\"

在clinet中请求了两次服务器的响应 简单方法和正式方法 服务器的程序每运行一个clinet要运算两次。

 

 

\"\" \"\" \"\" 点赞 7 \"\" \"\" 评论 1

本文链接: http://wasros.immuno-online.com/view-750556.html

发布于 : 2021-03-25 阅读(0)
公司介绍
品牌分类
联络我们
服务热线:4000-520-616
(限工作日9:00-18:00)
QQ :1570468124
手机:18915418616
官网:http://