第一章 ROS空间创建、helloworld的实现、开启多个节点
第二章 话题通信
第三章 服务通信
现在大二,之前大一有幸参加了2021的国赛,很壮烈的拿了个江苏赛区的二等奖。但发现无人机这个题,真的是往堆钱上走了。不上ROS不行,现在来记录一下一个纯小白学习ROS的过程和遇到的问题。防止学弟、学妹们再走我走过的弯路。板子用的是学长给的Jetson Nano(4GB),版本是Ubuntu18.04(已配置好基础ROS所需配置)。
服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
一个节点需要向相机节点发送拍照请求,相机节点处理请求,并返回处理结果。与上述应用类似的,服务通信更适用于对时时性有要求、具有一定逻辑处理的应用场景。
srv=请求+响应
roscpp rospy std_msgs
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
<build_depend>message_generationbuild_depend>
<exec_depend>message_runtimeexec_depend>
CMakeLists.txt编辑 srv 相关配置:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
add_service_files(
FILES
AddInts.srv #你的文件名
)
generate_messages(
DEPENDENCIES
std_msgs
)
#注释放开
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES plumbing_server_client
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
需求:
编写服务通信,客户端提交两个整数至服务端,服务端求和并响应结果到客户端。
流程:
编写服务端实现;
编写客户端实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。
{
"python.autoComplete.extraPaths": [
"/opt/ros/noetic/lib/python3/dist-packages",
"/xxx/yyy工作空间/devel/lib/python3/dist-packages"
]
}
#! /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
catkin_install_python(PROGRAMS
scripts/demo01_server_p.py #自己的py文件
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
source ./devel/setup.bash
rosrun plumbing_server_client demo01_server_p.py
source ./devel/setup.bash
rosservice call AddInts "num1: 0
num2: 0"
#! /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文件具体字段值
catkin_install_python(PROGRAMS
scripts/demo01_server_p.py
scripts/demo02_client_p.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
source ./devel/setup.bash
rosrun plumbing_server_client demo01_server_p.py
以上就是今天要讲的内容,本文仅仅简单记录了ROS的服务通信,如果有问题请在博客下留言或者咨询邮箱:[email protected]。