我的ROS学习之路——服务通信
本知识点将用一个实例(服务端处理客户端提交的两个数字求和,然后返回处理结果)来理解 服务通信的基本使用,大致分为三块:
1.自定义消息*.srv的编写()
2.服务端编写
3.客户端编写
一.首先创建一个工作空间和软件包
创建工作空间
mkdir -p ~/catkin_ws_srv_self/srccd catkin_ws_srv_selfcatkin_make
创建软件包
cd srccatkin_create_pkg server_client std_msg rospy roscpp
二.自定义消息*.srv的编写——srv编写其实与前面说的话题通信步骤一样,只不过改成了srv自己的东西。
(PS:这里可以完全参考ros wki上面的教程,消息创建部分,照搬就可以)
2.1编写srv文件
方式一:在终端中创建msg
cd ~/catkin_ws_srv_self/src/server_clientmkdir msggedit sum_ints.srv
在打开的文本,然后输入如下自己定义的信息(像结构体一样编写就行):
int32 num1
int32 num2
---
int32 sum
方式二:在vscode中创建srv
在终端中输入:
cd ~/catkin_ws_srv_selfcode .
这样就打开了vscode编辑器,在~/catkin_ws_srv_self/src/plumbing_server_client/目录下,创建一个srv文件夹,在srv文件下,创建一个sum_ints.srv文件,在输入自己定义的信息:
int32 num1
int32 num2
---
int32 sum
最终效果如下:
以上两种方式实现效果一样,但是显然vscode的交互界面舒服。
2.2编辑配置文件(简记:231——package.xml改动两项,CMakeLists.txt改动三项,放开注释一项)
2.2.1首先在package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
2.2.2然后在CMakeLists.txt编辑srv相关配置
# 不要直接复制这一大段,只需将message_generation加在括号闭合前即可
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation
)
#执行时依赖
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES demo02_talker_listenerCATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
#配置srv的源文件
add_service_files(FILESnum_sum.srv//这里放你自己定义的消息文件名
)
# 生成消息时依赖于 std_msgs
generate_messages(DEPENDENCIESstd_msgs
)
好了,至此已经自定义消息配置完了。但是还没完,编译完了之后,还需要继续配置环境。
2.3编译
编译之后,会产生一些中间文件(后续调用相关 msg 时,是从这些中间文件调用的),但我只关注头文件在创建的工作空间的开发空间下 include的文件夹里 即(~/catkin_ws_example/devel/inlcude下)。
因为这是自己定义的消息,所以现在需要做的是,把这个头文件包含进本工作空间的路径里面(在c_cpp_properties.json 里的 includepath属性引入,这样可以避免的是 在用vscode开发时,引入 自定义消息头文件,不会出现误报错误和代码无法补齐的情况)
PS:如何快速的得到这个头文件的路径呢?——这个路径可以鼠标放在include上,然后右击鼠标打开终端,输入pwd可得
引入的框架大致如下:
{"configurations": [{"browse": {"databaseFilename": "","limitSymbolsToIncludedHeaders": true},"includePath": ["/opt/ros/noetic/include/**","/usr/include/**","/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 ],"name": "ROS","intelliSenseMode": "gcc-x64","compilerPath": "/usr/bin/gcc","cStandard": "c11","cppStandard": "c++17"}],"version": 4
}
在本例中,引入图为:
最后面 ~/include/**的意思是,引入inlcude文件夹下的所有头文件。
至此,自定义消息部分,已经配置完成。
总结一下,做了哪些事?编写:
自定义消息
然后配置package.xml,CMakeLists.txt
引入头文件
三.服务端编写
3.1在~/catkin_ws_srv_self/src/server_client/src文件夹下创建一个*.cpp文件(本例为 server.cpp),然后放如下代码:
#include<ros/ros.h>
#include "plumbing_server_client/sum_ints.h"/*
服务端实现:解析客户端提交的数据,并运算在产生结果1.包含头文件2. 初始化ros节点3.创建句柄4.创建句柄对象(服务对象)5.处理请求并产生响应spin()
*///5.处理请求并产生响应
bool add(plumbing_server_client::sum_ints::Request &request,plumbing_server_client::sum_ints::Response &response)
{/*操作主要有两步*///1.处理请求int num1 = request.num1;/*问题:这里为什么用的是. 而不是->呢? ——因为函数形参列表不是以指针方式引用的,拿到的是引用,而不是指针,进一步的描述,这里的request和response不是指针,没有用ConstPtr来接收,而是对象。*/int num2 = request.num2;ROS_INFO("收到的请求数据:num2 = %d,num2 = %d",num1,num2);//ROS_INFO(" 收到的数据: num1= %d,num2=%d",request.num1,request.num2);//以上三条消息,可以融合成一条打印,只是多了中间变量接收一下而已//2.处理响应int sum = num1+num2;response.sum = sum;//response.sum = request.num1+request.num2;//以上两条信息,也可以融合成一条打印,只是多了一个中间变量接收而已ROS_INFO("求和结果:%d",sum);// ROS_INFO("求和结果:%d",response.sum);//说明返回response.sum和sum中间变量都可以return true;
}int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//日志输出,如果用中文的话,不要忘了这一句。// 2. 初始化ros节点ros::init(argc,argv,"server");//3.创建句柄ros::NodeHandle nh ;//4.创建句柄对象(服务对象)ros::ServiceServer server = nh.advertiseService("add_two_ints",add) ;/*第二个参数就是回调函数,处理请求的,只要是关于有回调函数的就不用写模板函数,他会自己推导然后填写的
回调函数返回的是 布尔类型的,因为这个处理结果请求,可能性有两个,成功或失败*/ROS_INFO("服务器端启动了!");ros::spin();return 0;
}
3.2配置CMakeLists.txt(需要修改三个地方,都是找到对应的地方,然后复制注释下来,修改需要改的部分即可)
第二句放的位置 有坑的说明,已经在发布的 话题通信之自定义消息 里已经说明了。
OK~发布方已经编写好了,接下来就可以编译测试了(这个模块写好了,先测试没有问题在写其他模块)。
3.3编译测试
3.3.1
方式一(终端编译方式):
cd ~/catkin_ws_srv_selfcatkin_make
方式二(vscode的快捷键编译方式):
在vscode中,shift+ctrl+B
3.3.2运行发布者节点(前提是已经运行了 roscore)
打开一个新的终端:
roscore
另开一个终端:
cd ~/catkin_ws_srv_selfsoure devel/setup.bashrosrun server_client server
到这一步之后,就运行成功了,服务端已经挂起了,但是在终端看不到什么反应,但是我们可以用内置指令,在终端上提交数字让服务端计算并把结果打印出来到终端来看结果,如:
另开一个终端:输入rosservice list 可以查看当前挂起的服务(发现/two_sum为我们所需的服务),然后输入rosservice -h可以查看rosservice有什么功能(指令忘记了,可以走这一步),然后输入rosservice call /two_sum "num1:[自己随便输入数字,如1] num2:[自己随便输入数字,如2]"
(这一串指令这么长,怎么记得住?——小技巧:可以输入到rosservice call /two_sum 然后多按几次tab键盘,就能自动补齐后面的东西,PS:后面可以自己输入的数字,其实就是自己写的服务端所做的事情。)
结果如图:
验证成功~
总结一下干了哪些事?
编写*.cpp文件
配置CMakeLists.txt
四.客户端编写
以固定方式(即程序运行前,数字已经固定死)提交:
4.1在~/catkin_ws_srv_self/src/server_client/src文件夹下创建一个*.cpp文件(本例为 client.cpp),然后放如下代码:
#include<ros/ros.h>
#include "server_client/num_sum.h"/*
客户端:提交两个整数,并处理响应的结果。1.包含头文件;2.初始化ros节点3.创建节点句柄4.创建一个客户端对象5.提交请求并处理响应
*/int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//2.初始化ros节点ros::init(argc,argv,"client");// 3.创建节点句柄ros::NodeHandle nh;//4.创建一个客户端对象ros::ServiceClient client = nh.serviceClient<server_client::num_sum>("two_sum");//serviceClient有三个重载,意思是可以 形参输入有三种样式,这里使用第二个重载,有范型的那一个,范型可以就是自己创建的那个服务消息srv(具体解释可看视频第67个4min10s)//5.提交请求并处理响应(主逻辑实现)server_client::num_sum srv;//5.1 组织请求srv.request.num1 = 1;srv.request.num2 = 2;//5.2 处理响应bool flag = client.call(srv); //返回值是一个布尔类型的,提交完之后,是有返回结果的,所以可以用一个bool值接收一下。如果是true就正常处理,false就是处理失败了。并且响应的结果(比如这里的sum),也封装进了这个srv对象(在这个srv对象中,有request还有response这两个属性)。if(flag){ROS_INFO("响应成功!");//获取结果ROS_INFO("处理结果 = %d" ,srv.response);}else{ROS_INFO("响应失败...");}ros::spin();return 0;
}
4. 2配置CMakeLists.txt(需要修改三个地方,都是找到对应的地方,然后复制注释下来,修改需要改的部分即可,改的方法与发布方一样,因此这里只放了最终效果图即可,用红笔标出改了哪些部分)
shift+ctrl+B编译(或者用终端方式的编译,上面3.3.1写过了)通过,好了。可以联合调试了。
总结一下干了哪些事?
编写*.cpp文件
配置CMakeLists.xtxt
五.联合调试
5.1 编译(不会编译的见3.1)
5.2运行roscore
5.3运行服务端节点
新开一个终端:
cd ~/catkin_ws_srv_selfsoure devel/setup.bashrosrun server_client server
5.4运行客户端节点
新开一个终端:
cd ~/catkin_ws_srv_selfsoure devel/setup.bashrosrun server_client client
最后效果如图所示:
OK~完成,结束~
--------------------------------------------------------分割线--------------------------------------------------------
这里值得一提的是(主要体会思想动态提交的思想,可以从终端输入数据,然后从mian函数入口进到程序里面):上面第四部分,写了一个以固定方式(即程序运行前,数字已经固定死)提交,这里优化客户端的编写,以动态的方式提交(就是灵活的填写两个数字,都可以实现求解):
可以在client.cpp文件中,放如下代码:
//优化客户端,实现参数的动态提交
//1.终端输入格式:rosrun xxxx(包名) xxxx(节点名) 1 2
//2.节点执行时,需要获取命令中的参数,然后数据放入requerst中
#include<ros/ros.h>
#include "server_client/num_sum.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//优化实现,获取命令中的参数/*此时argc 应该等于3(节点文件名,两个参数,所以是三个),*argv指针数组应该也是3,并且argv[0]为客户端文件名,argv[1]为终端传进来的第一个数,如1,,argv[2]为传进来的第二个数,如2*/if(argc != 3){ROS_INFO("输入个数不对...");return 1;}ros::init(argc,argv,"client");ros::NodeHandle nh;ros::ServiceClient client = nh.serviceClient<server_client::num_sum>("two_sum");server_client::num_sum srv;srv.request.num1 = atoi(argv[1]);srv.request.num2 = atoi(argv[2]);bool flag = client.call(srv);if(flag){ROS_INFO("求和结果为:%d",srv.response.sum);}else{ROS_INFO("响应失败...");return 1;}//return 0;ros::spin();//经过测试,程序运行到这里,会回调(因为终端就停在那了,并没有结束,继续给输入命令,需要按ctrl+c才能结束)。然后就不经过 return 0了。 ( return 0为正常停止,return 1为非正常停止的意思。)return 0;
}
然后就可以开始调试了。
1. 编译(不会编译的见3.1)
2。运行roscore
3运行服务端节点
新开一个终端:
cd ~/catkin_ws_srv_selfsoure devel/setup.bashrosrun server_client server
4。运行客户端节点
新开一个终端:
cd ~/catkin_ws_srv_selfsoure devel/setup.bashrosrun server_client client
最后效果如图所示(如图演示了 两组动态提交数据,分别是 1和2 ,5和10):
OK~完成,结束~
我的ROS学习之路——服务通信相关推荐
- ROS学习笔记-多机器人通信(1)-实现两台机器通信
ROS是一个分布式的计算环境.一个正在运行的ROS可以在多个机器人之间分布成几十甚至上百个节点.取决于系统的配置方式,任何节点可能需要随时与任何其他节点进行通信,为实现使用同一个master控制多台机 ...
- ROS学习小笔记(Topic通信 ,service通信,参数服务器)
(菜鸡整理的学习笔记,原文链接已经挂上,不小心过来的朋友建议去博主那边学习,谢谢) 原文链接:https://blog.csdn.net/LoongEmbedded/article/details/1 ...
- ros学习笔记_服务通讯
学习地址 0.话题通讯理论模型 前言: 话题通信基本操作(C++) 注:启动roscore的时候rosmaster已经启动了,因此ROS master 不需要实现,而连接的建立也已经被封装了(因此连接 ...
- ROS学习之路的整理
ROS是基于linux系统的一个次级操作系统,目前被看做是机器人界的一套标准平台,可以类比手机的安卓操作系统或者是电脑的windows操作系统.ROS最大的优点在于灵活.低耦合.分布式.开源以及功能强 ...
- 我的ROS学习之路——动起来的小海龟
a.让小海龟出现的两个步骤: 1.roscore2.rosrun turtlesim turtlesim_node b.让小海龟动起来的三个方法(当前学习): 1.键盘控制,命令行输入: rosrun ...
- 《ROS学习之路(1)》ROS Kinetic版本安装---ubuntu16.04(Xenial Xerus 好客的非洲地松鼠)
一.ubuntu16.04换国内软件源 https://blog.csdn.net/qq_40584960/article/details/104298468 二.按照官方教程来安装(ros源也用国内 ...
- ros和java通讯_ROS学习之路(二)——通信架构(上)
1. master&&node mater中文名又称为节点管理器,作为管家管理所需要的进程,其作用有两个: 每个node启动时都要向master注册. 管理node之间的通信. nod ...
- ROS学习:创建机器人的urdf
ROS学习之路08:创建机器人的urdf(xacro)模型并通过rviz可视化_Hi, Robotics-CSDN博客_urdf可视化 1 创建工作空间 mkdir -p ~/catkin_ws/sr ...
- 周末ROS学习沙龙第三期——launch文件、自定义服务通信、控制机器人移动、传感器数据处理
非博主原创,出于方便学习的目的,将周末ROS学习沙龙www.corvin.cn的课堂讲义PPT整理在这(老师讲得超棒!),无任何盈利目的,若有侵权则删除. Ros小课堂链接:https://space ...
- ROS学习笔记(八): ROS通信架构
ROS学习笔记(八): ROS通信架构 文章目录 01 Node & Master 1.1 Node 1.2 Master 1.3 启动master和node 1.4 rosrun和rosno ...
最新文章
- ## *将以下学生成绩数据,存放在Hdfs上,使用Spark读取完成下面分析**
- linux下防DDOS***软件及使用方法详解
- androidstudio表格中填充 宽跟长一样_Excel表格的基本操作教程,覆盖表格制作的10大知识!...
- 两个学习英语的好软件
- Easy Tech:什么是I帧、P帧和B帧?
- highcharts 怎么去掉鼠标悬停效果_练瑜伽减肥没效果什么原因?
- 摘抄自知乎的redis相关
- python学习随笔day3
- C/C++ OpenCV五种滤波器综合示例
- SQL Server -- 如何书写优雅、漂亮的SQL脚本?
- matlab 符号表,MATLAB——matlab特殊符号表【转载】
- 今天我们谈一下HTML标签中的map标签的用法和使用场景
- 在小公司待了3年后,我废了
- java计算机毕业设计论文评审系统源码+系统+mysql数据库+lw文档
- Hbase的过滤器分类
- 如何开通微信小程序在线客服系统?
- ad16 导入dwg_AD16怎样精确导入CAD文件
- Web2 大厂「谷歌」是如何进入 Web3 的?
- Mastering Selections in Photoshop CC Photoshop CC选区教程 Lynda课程中文字幕
- Jmeter导出性能测试报告