在Jetson Nano上学习ROS的记录(版本Ubuntu18.04,课程来源赵虚左老师的《ROS理论与实践》)第三章 服务通信

系列文章目录

第一章 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 实现流程类似:
  1. 按照固定格式创建srv文件
  2. 编辑配置文件
  3. 编译生成中间文件

2.定义srv文件在工作空间的src目录下新建功能包

  • 选定 src 右击 —> create catkin package
  • 设置包名 添加依赖
  • 输入roscpp rospy std_msgs
  • 快捷键 ctrl + shift + B 调用编译
  • 在 功能包 下新建 srv 文件夹,在文件夹下新建srv文件
  • 服务通信中,数据分成两部分,请求与响应,在 srv 文件中请求和响应使用—分割,具体实现如下:
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum

3.编辑配置文件

  1. package.xml中添加编译依赖与执行依赖(51行)加两行:
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

CMakeLists.txt编辑 srv 相关配置:

  1. 第10行
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# 需要加入 message_generation,必须有 std_msgs
  1. 第58行
add_service_files(
  FILES
  AddInts.srv  #你的文件名
)
  1. 第71行
generate_messages(
  DEPENDENCIES
  std_msgs
)
#注释放开
  1. 第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文件添加可执行权限;
    编辑配置文件;
    编译并执行。

  1. 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"
    ]
}

  1. 服务端实现
    在功能包下创建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"
  1. 客户端实现
    在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。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值