ROS入门笔记(十一):编写与测试简单的Service和Client (Python)

文章目录

  • 01 导读
  • 02 功能包的创建
  • 03 在功能包中创建自定义服务类型
    • 3.1 定义srv文件
    • 3.2 在package.xml中添加功能包依赖
    • 3.3 在CMakeLists.txt添加编译选项
  • 04 查看自定义的服务消息
  • 05 功能包的源代码编写
    • 5.1 编写Service节点(server.py)
    • 5.2 编写Client节点(client.py)
  • 06 功能包的编译
  • 07 测试service和client
    • 7.1 运行Service
    • 7.2 运行Client

01 导读

C++代码必须通过编译生成可执行文件;

python代码是可执行文件,不需要编译;

  • 开发的功能包都放在catkin_ws这样一个工作空间里;
  • 新建的功能包取名为service_example,实现两个整数求和为例,client端节点向server端节点发送a、b的请求,server端节点返回响应sum=a+b给client端节点;
  • 通信网络结构如图所示:

服务编程流程

  • 创建服务器
  • 创建客户端
  • 添加编译选项
  • 运行可执行程序

02 功能包的创建

在catkin_ws/src/目录下新建功能包service_example,并在创建时显式的指明依赖rospy和std_msgs,依赖std_msgs将作为基本数据类型用于定义我们的服务类型。打开命令行终端,输入命令:

$ cd ~/catkin_ws/src#创建功能包topic_example时,显式的指明依赖rospy和std_msgs,
#依赖会被默认写到功能包的CMakeLists.txt和package.xml中
$ catkin_create_pkg service_example rospy std_msgs

03 在功能包中创建自定义服务类型

  • 服务(srv): 一个srv文件描述一项服务。它包含两个部分:请求和响应。

  • 服务类型的定义文件都是以*.srv为扩展名,srv文件则存放在功能包的srv目录下。

  • 服务通信过程中服务的数据类型需要用户自己定义,与消息不同,节点并不提供标准服务类型。

3.1 定义srv文件

srv文件分为请求和响应两部分,由’—'分隔。

在功能包service_example目录下新建srv目录,然后在service_example/srv/目录中创建AddTwoInts.srv文件

int64 a
int64 b
---
int64 sum

其中 ab 是请求, 而sum 是响应。

3.2 在package.xml中添加功能包依赖

srv文件被转换成为C++,Python和其他语言的源代码:

查看package.xml, 确保它包含一下两条语句:

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

如果没有,添加进去。 注意,在构建的时候,我们只需要"message_generation"。然而,在运行的时候,我们只需要"message_runtime"。

3.3 在CMakeLists.txt添加编译选项

第一步,增加message_generation

打开功能包中的CMakeLists.txt文件,利用find_packag函数,增加对message_generation的依赖,这样就可以生成消息了。 你可以直接在COMPONENTS的列表里增加message_generation,就像这样:

find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation)

有时候你会发现,即使你没有调用find_package,你也可以编译通过。这是因为catkin把你所有的功能包都整合在一起,因此,如果其他的功能包调用了find_package,你的功能包的依赖就会是同样的配置。但是,在你单独编译时,忘记调用find_package会很容易出错。

第二步,删掉#,去除对下边语句的注释:

找到如下代码块:

# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

用你自己定义的srv文件名(AddTwoInts.srv)替换掉那些Service*.srv文件,修改好后的代码如下:

add_service_files(FILESAddTwoInts.srv
)

第三步,msg和srv都需要的步骤

CMakeLists.txt中找到如下部分:

# generate_messages(
#   DEPENDENCIES
# #  std_msgs  # Or other packages containing msgs
# )

去掉注释并附加上所有你消息文件所依赖的那些含有.msg文件的功能包(这个例子是依赖std_msgs,不要添加roscpp,rospy),结果如下:

generate_messages(DEPENDENCIESstd_msgs
)

原因:generate_messages的作用是自动创建我们自定义的消息类型 .msg与服务类型 .srv相对应的 .h,由于我们定义的服务类型使用了std_msgs中的int64基本类型,所以必须向generate_messages指明该依赖。

第四步,由于增加了新的消息,所以我们需要重新编译我们的功能包:

目的:查看配置是否有问题

$ cd ~/catkin_ws
$ catkin_make -DCATKIN_WHITELIST_PACKAGES="service_example"

所有在msg路径下的.msg文件都将转换为ROS所支持语言的源代码。生成的C++头文件将会放置在~/catkin_ws/devel/include/service_example/。 Python脚本语言会在 ~/catkin_ws/devel/lib/python2.7/dist-packages/service_example/msg 目录下创建。

04 查看自定义的服务消息

通过<功能包名/服务类型名>找到该服务,打开命令行终端,输入命令:

$ source ~/catkin_ws/devel/setup.bash$ rossrv show service_example/AddTwoInts

05 功能包的源代码编写

功能包中需要编写两个独立可执行的节点,一个节点用来作为client端发起请求,另一个节点用来作为server端响应请求,所以需要在新建的功能包service_example/scripts目录下新建两个文件server.py和client.py,并将下面的代码分别填入。

5.1 编写Service节点(server.py)

将创建一个简单的service节点(“server”),该节点将接收到两个整形数字,并返回它们的和。

如何实现一个服务器

  • 初始化ROS节点;
  • 创建Server实例;
  • 循环等待服务请求,进入回调函数;
  • 在回调函数中完成服务功能的处理,并反馈应答数据。

在service_example包中创建scripts / server.py文件:

#!/usr/bin/env pythonfrom service_example.srv import AddTwoInts,AddTwoIntsResponse
import rospydef handle_add_two_ints(req):print "Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))#因为我们已经将服务的类型声明为AddTwoInts,所以它会为您生成AddTwoIntsRequest对象(可以自由传递)return AddTwoIntsResponse(req.a + req.b)    # AddTwoIntsResponse由服务生成的返回函数def add_two_ints_server():rospy.init_node('add_two_ints_server')  # 声明节点为add_two_ints_server#定义服务器节点名称,服务类型,处理函数#处理函数调用实例化的AddTwoIntsRequest接收请求和返回实例化的AddTwoIntsResponses = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)print "Ready to add two ints."rospy.spin()   # 就像订阅者示例一样,rospy.spin()使代码不会退出,直到服务关闭;if __name__ == "__main__":add_two_ints_server()

在~/catkin_ws/src/service_example下,让节点可执行:

$ chmod +x scripts/server.py

5.2 编写Client节点(client.py)

如何实现一个客户端

  • 初始化ROS节点;
  • 创建一个Client实例;
  • 发布服务请求数据;
  • 等待Server处理之后的应答结果。

在service_example包中创建scripts / client.py文件,并在其中粘贴以下內容:

#!/usr/bin/env python"""
导入sys模块,sys.argv的功能是在外部向程序的内部传递参数。sys.argv(number),number=0的时候是脚本的名称
"""
import sys
import rospy
from service_example.srv import *def add_two_ints_client(x, y):# 等待接入服务节点# 第二句是调用wait_for_service,阻塞直到名为“add_two_ints”的服务可用。rospy.wait_for_service('add_two_ints')try: # 创建服务的处理句柄,可以像调用函数一样,调用句柄add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)resp1 = add_two_ints(x, y)return resp1.sum #如果调用失败,可能会抛出rospy.ServiceExceptionexcept rospy.ServiceException, e:            print "Service call failed: %s"%edef usage():return "%s [x y]"%sys.argv[0]if __name__ == "__main__":if len(sys.argv) == 3:x = int(sys.argv[1])y = int(sys.argv[2])else:print usage()sys.exit(1)print "Requesting %s+%s"%(x, y)print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))

在~/catkin_ws/src/service_example节点可执行:

$ chmod +x scripts/client.py

代码解析:

我们可以像普通函数一样使用这个句柄并调用它:

resp1 = add_two_ints(x, y)
return resp1.sum

因为我们已经将服务的类型声明为AddTwoInts,所以它会为你生成AddTwoIntsRequest对象(可以自由传递)。返回值是AddTwoIntsResponse对象。如果调用失败,可能会抛出rospy.ServiceException,因此你应该设置适当的try/except块。

06 功能包的编译

我们使用CMake作为构建系统,是的,即使是Python节点也必须使用它。这是为了确保创建消息和服务时自动生成Python代码。

$ cd ~/catkin_ws
$ catkin_make -DCATKIN_WHITELIST_PACKAGES="service_example"

07 测试service和client

7.1 运行Service

第一步,打开一个命令行终端:

$ roscore

第二步,打开第二个命令行终端:

# 用rosrun <package_name> <node_name>启动功能包中的发布节点。
$ source ~/catkin_ws/devel/setup.bash    # 激活catkin_ws工作空间(必须有,必不可少)
$ rosrun service_example server.py       # (python版本)

你将看到如下的输出信息:

Ready to add two ints.              # Server节点启动后的日志信息

7.2 运行Client

现在,运行Client并附带一些参数:

打开第三个命令行客户端:

$ source ~/catkin_ws/devel/setup.bash     # 激活catkin_ws工作空间(必须有,必不可少)
$ rosrun service_example client.py 1 3    # (Python)

你将会看到如下的输出信息:

# Client启动后发布服务请求,并成功接收到反馈结果
Requesting 1+3
1 + 3 = 4# Server接收到服务调用后完成加法求解,并将结果反馈给Client
Returning [1 + 3 = 4]

现在,你已经成功地运行了你的第一个Service和Client程序。

ROS入门笔记(十一):编写与测试简单的Service和Client (Python)相关推荐

  1. ROS入门笔记(十):编写与测试简单的消息发布器和订阅器(C++)

    ROS入门笔记(十):编写与测试简单的消息发布器和订阅器(C++) 文章目录 01 导读 02 功能包的创建 03 功能包的源代码编写 3.1 编写发布器节点(talker.cpp) 3.2 编写订阅 ...

  2. ROS入门笔记(九):编写ROS的第一个程序hello world(重点)

    ROS入门笔记(九):编写ROS的第一个程序hello world(重点) 文章目录 1 Catkin工作空间 1.1 创建catkin工作空间 1.2 编译工作空间 1.3 设置环境变量 1.4 检 ...

  3. ROS入门笔记(十二):动作编程 (C++)

    ROS入门笔记(十二):动作编程 (C++) 文章目录 01 导读 02 功能包的创建 03 在功能包中创建action(动作) 3.1 自定义action 3.2 在package.xml中添加功能 ...

  4. ROS入门笔记(七):详解ROS文件系统

    ROS入门笔记(七):详解ROS文件系统 文章目录 01 Catkin编译系统 1.1 Catkin特点 1.2 Catkin工作原理 1.3 使用`catkin_make`进行编译 02 Catki ...

  5. ROS入门笔记(六): ROS系统架构

    ROS入门笔记(六): ROS系统架构 文章目录 1 ROS系统架构 1.1 文件系统(重点) 1.2 计算图 1.3 开源社区 1 ROS系统架构 1.1 文件系统(重点) 文件系统:主要指在硬盘里 ...

  6. ROS入门笔记(十三):分布式通信

    ROS入门笔记(十三):分布式通信 文章目录 01 如何实现分布式多机通信 1.1 设置IP地址,确保底层链路的连通 1.2 在从机端设置ROS_MASTER_URI,让从机找到ROS Master ...

  7. ROS入门笔记(四):ROS实践(小海龟仿真)— ROS Topics

    ROS入门笔记(四):ROS实践(小海龟仿真)- ROS Topics 文章目录 1 基础知识 1.1 运行ROS Master所在主机的资源地址 1.2 ROS常用命令 1.2.1 查看所有以ros ...

  8. ROS入门笔记(三):二进制包与源代码包

    ROS入门笔记(三):二进制包与源代码包 文章目录 1 软件包分类 2 二进制包与源代码包的区别 3 ROS二进制包的安装 4 适配ROS的IDE 注意: 如果你是使用类似apt这样的软件管理器来安装 ...

  9. ROS入门笔记(二):ROS安装与环境配置及卸载(重点)

    ROS入门笔记(二):ROS安装与环境配置及卸载(重点) 文章目录 1 ROS安装步骤 1.1 ROS版本 1.2 确定Ubuntu版本号 1.3 安装ROS 1.3.1 Ubuntu初始环境配置 1 ...

最新文章

  1. 关于MATLAB FFT频谱泄露和加窗
  2. 前后端、多语言、跨云部署,全链路追踪到底有多难?
  3. 【PM模块】维护业务处理流程—内部维护(通知单)
  4. GPU Gems2 - 12 基于贴面的纹理映射(Tile-Based Texture Mapping)
  5. Jelastic Java云端平台
  6. 基于机器视觉的铁片轮廓检测
  7. linux 自动挂载usb设备,Raspberry Pi 自动挂载USB存储设备
  8. Android应用真机调试
  9. Qt的QDataStream
  10. window的pagefile.sys和hiberfil.sys文件
  11. sshsecureshell登录Ubuntu出错,server responded “algorithm negotiation failed”
  12. 亚太融媒+ | APEC数据+:“鲸确数集”环保熊猫“小保保”2022拜年 | APEC产业+
  13. 数据结构(本科学习)
  14. 百度云使用Docker镜像加速器
  15. 惠众和环宇计算机专业,计算机一级Office
  16. adb 打开 diag 端口用qpst备份恢复qcn
  17. CHAP6:通过可视化艺术共享数据
  18. TCL爱奇艺再次联姻 共同打造国际微电影节
  19. MySQL_帐号密码匹配规则与命名规范
  20. 四种静态路由配置方法

热门文章

  1. PAT乙级(1026 程序运行时间)
  2. connect mysql (4),mysql用法4
  3. 【连载】如何掌握openGauss数据库核心技术?秘诀三:拿捏存储技术(5)
  4. DBA自述:非科班出身,如何成为Oracle ACE
  5. 电商场景下,如何处理消费过程中的重复消息?
  6. 全链路数据血缘在满帮的实践
  7. Java编程中忽略这些细节,Bug肯定找上你
  8. 5招详解linux之openEuler /centos7防火墙基本使用指南
  9. 使用CloudIDE搭建简单java环境
  10. 计算机组成与设计英文版在线,计算机组成与设计(硬件软件接口英文版原书第5版RISC-V版)/经典原版书库...