系列文章目录
第一章 ROS空间创建、helloworld的实现、开启多个节点
第二章 话题通信
第三章 服务通信
第四章 参数服务器
第五章 常用指令
第六章 通信机制实操
第七章 ROS通信机制进阶(常用API、Python模块的导入)
第八章 元功能包、节点运行管理launch文件(teleop_twist安装方法)
第九章 重名问题、分布式通信
第十章-第一节 TF坐标变换(内含PyKDL 和PyInit__tf2功能缺失等解决)
第十章-第二节 TF坐标变换实操
第十章-第三节 rosbag、rqt工具箱
第十一章-第一节 机器人系统仿真(URDF相关)
第十一章-第二节 机器人系统仿真(Gazebo相关)
第十二章 机器人导航(仿真)
文章目录
前言
现在大二,之前大一有幸参加了2021的国赛,很壮烈的拿了个江苏赛区的二等奖。但发现无人机这个题,真的是往堆钱上走了。不上ROS不行,现在来记录一下一个纯小白学习ROS的过程和遇到的问题。防止学弟、学妹们再走我走过的弯路。板子用的是学长给的Jetson Nano(4GB),版本是Ubuntu18.04(已配置好基础ROS所需配置)。
一、服务通信是什么?
服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
一个节点需要向相机节点发送拍照请求,相机节点处理请求,并返回处理结果。与上述应用类似的,服务通信更适用于对时时性有要求、具有一定逻辑处理的应用场景。
二、服务通信基本操作(Python)
1.srv定义
srv=请求+响应
- 流程
srv 文件内的可用数据类型与 msg 文件一致,且定义 srv 实现流程与自定义 msg 实现流程类似:
- 按照固定格式创建srv文件
- 编辑配置文件
- 编译生成中间文件
2.定义srv文件在工作空间的src目录下新建功能包
- 选定 src 右击 —> create catkin package
- 设置包名 添加依赖
- 输入
roscpp rospy std_msgs
- 快捷键 ctrl + shift + B 调用编译
- 在 功能包 下新建 srv 文件夹,在文件夹下新建srv文件
- 服务通信中,数据分成两部分,请求与响应,在 srv 文件中请求和响应使用—分割,具体实现如下:
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
3.编辑配置文件
- package.xml中添加编译依赖与执行依赖(51行)加两行:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
CMakeLists.txt编辑 srv 相关配置:
- 第10行
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
- 第58行
add_service_files(
FILES
AddInts.srv #你的文件名
)
- 第71行
generate_messages(
DEPENDENCIES
std_msgs
)
#注释放开
- 第108行
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES plumbing_server_client
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
- 快捷键 ctrl + shift + B 调用编译
4.服务通信自定义srv调用B(Python)
-
需求:
编写服务通信,客户端提交两个整数至服务端,服务端求和并响应结果到客户端。 -
流程:
编写服务端实现;
编写客户端实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。
- vscode配置
- 为了方便代码提示以及误抛异常,需要先配置 vscode,将前面生成的 python 文件路径配置进 settings.json
- 进入/home/lzl/myworld/devel/lib/python2.7 在命令行中打开
- 输入pwd
- 复制路径
- 打开/home/lzl/myworld/.vscode/settings.json
{
"python.autoComplete.extraPaths": [
"/opt/ros/noetic/lib/python3/dist-packages",
"/xxx/yyy工作空间/devel/lib/python3/dist-packages"
]
}
- 服务端实现
在功能包下创建scripts文件夹,在文件夹里创建.py文件
代码如下:
#! /usr/bin/env python3
"""
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
服务器端实现:
1.导包
2.初始化 ROS 节点
3.创建服务对象
4.回调函数处理请求并产生响应
5.spin 函数
"""
# 1.导包
import rospy
from plumbing_server_client.srv import AddInts,AddIntsResponse,AddIntsRequest
# 回调函数的参数是请求对象,返回值是响应对象
def doReq(req):
# 解析提交的数据
sum = req.num1 + req.num2
rospy.loginfo("提交的数据:num1 = %d, num2 = %d, sum = %d",req.num1, req.num2, sum)
#打印语句
# 创建响应对象,赋值并返回
resp = AddIntsResponse()
resp.sum = sum
# resp = AddIntsResponse(sum)
return resp
if __name__ == "__main__":
# 2.初始化 ROS 节点
rospy.init_node("addints_server_p")
# 3.创建服务对象
server = rospy.Service("AddInts",AddInts,doReq)
#参数1:当前服务通信使用的话题,参数2:服务类型(srv问价夹下的文件名),参数3:回调函数
# 4.回调函数处理请求并产生响应
# 5.spin 函数
rospy.spin()
- 添加可执行权限
chmod +x *.py
- 配置cmakelist
第162行:
catkin_install_python(PROGRAMS
scripts/demo01_server_p.py #自己的py文件
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
- 编译
- 启动rescore
- 新开一个命令行
source ./devel/setup.bash
rosrun plumbing_server_client demo01_server_p.py
- 新开一个命令行
source ./devel/setup.bash
rosservice call AddInts空格tab补齐:
rosservice call AddInts "num1: 0
num2: 0"
- 客户端实现
在scripts文件夹里创建.py文件
代码如下:
#! /usr/bin/env python3
"""
需求:
编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
客户端再解析
客户端实现:
1.导包
2.初始化 ROS 节点
3.创建请求对象
4.发送请求
5.接收并处理响应
优化:
加入数据的动态获取
优化实现:可以在执行节点时,动态传入参数
"""
#1.导包
import rospy
from plumbing_server_client.srv import AddInts,AddIntsResponse,AddIntsRequest
import sys
if __name__ == "__main__":
#判断参数长度(是否符合提交的标准)
if len(sys.argv) != 3: #sys.argv是一个数组可以存放名称、数据
rospy.logerr("错误的参数个数") #输出一个错误日志
sys.exit(1)
# 2.初始化 ROS 节点
rospy.init_node("AddInts_Client_p")
# 3.创建客户端对象
client = rospy.ServiceProxy("AddInts",AddInts)
#serviceproxy 此函数会产生并返回一个客户端对象.参数1:当前服务通信使用的话题,需要和客户端一致,参数2:消息类型(srv文件夹下的文件名)
# 4.组织请求数据,接收并处理响应
#解析传入的参数;argv这个数组【0】的位置是文件名,1是传入的第一个参数,2是第二个参数
#num1 = sys.argv[1] 现在是一个字符串
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
# 方式1
resp = client.call(num1,num2)
# 方式2
# resp = client(AddIntsRequest(1,5))
# 方式3
#req = AddIntsRequest()
# req.num1 = 100
# req.num2 = 200
#5处理响应
rospy.loginfo("响应结果:%d",resp.sum) #看srv文件具体字段值
- 添加可执行权限chmod +x *.py
- 配置cmakelist
162:
catkin_install_python(PROGRAMS
scripts/demo01_server_p.py
scripts/demo02_client_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
- 编译
- 启动rescore
- 新开一个命令行
source ./devel/setup.bash
rosrun plumbing_server_client demo01_server_p.py
总结
以上就是今天要讲的内容,本文仅仅简单记录了ROS的服务通信,如果有问题请在博客下留言或者咨询邮箱:layraliu@foxmail.com。