一、服务通信简介
服务通信是基于请求响应模式的,是一种应答机制。
一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
服务通信适用于实时性要求比较高的场景,例如设计一款自动搭讪机器人,每当摄像头检测到有搭讪目标出现,则摄像头这个节点就会向底盘发送请求,让机器人运动起来.
与话题通信的对比:
Ⅰ.话题通信适用于不断更新的数据传输的场景,而服务通信适用于即时应答,无需不断更新.
客户端请求被处理时,需要保证服务器已经启动
同时服务端在完成需求后,需要将结果返回给客户端
(类比实际生活中的客户-服务模型)
二、实现流程
功能需求:客户端发送5个-100~100之间的数给服务端,服务端完成排序后返回给客户端
- 首先要定义服务的请求和响应的数据结构(定义srv文件)
意思是:客户端与服务端需要相互发布消息,这个发布的消息是需要我们自己定义的
举个例子:
如果我们要让客户端发布两个整数,服务端实现这两个整数的和并返回回去,这时候就需要我们在srv文件中定义能够实现这个功能的消息类型(类似结构体)
//供客户端使用
int num1;
int num2;
//供服务端使用
int sum;
srv文件就是专门用来自定义消息的地方
具体流程:
功能包下新建 srv 目录,添加 xxx.srv 文件,内容:(不需要分号结尾!!)
必须用 “- - -” 隔开
# 客户端请求时发送的五个数字
int32 num1
int32 num2
int32 num3
int32 num4
int32 num5
---
# 服务器响应发送的数据
int32 num1
int32 num2
int32 num3
int32 num4
int32 num5
图片里有误 我发现如果用数组会报错 那就不用了
接着编辑配置文件(具体可参考Day03中自定义消息类型)
防止大家不会我们再操作一遍:
①修改package.xml文件
②修改cmakelist文件
虚拟机崩溃了n次
最后修改:
需要用 不要用vscode自带的编译器编译!!!
ros编译用的是catkin_make!!!
编译:在工作空间下的devel文件下的 include文件中会生成.h文件 这就是我们上述做的一系列最终的结果:
我们在定义srv文件的时候用- - - 隔开了两部分对吧 所以在这里就生成了两部分的消息,一个是request.h 另一个是response.h 这就是我们在服务过程中的消息应答载体.
最后的最后 把生成文件的路径包含进去,不然一会引用头文件会报错:
一定 一定要注意!! 这里添加的路径之前是没有逗号的 我们需要加一个逗号!!!
这里报错我找了好久
- 编写客户端发布五个数
#include "ros/ros.h"
#include "service_client/sort.h"
int main(int argc, char *argv[])
{
ros::init(argc, argv,"client");
ros::NodeHandle nh;
ros::ServiceClient client;
client = nh.serviceClient<service_client::sort>("sort");
ros::service::waitForService("sort");
service_client::sort num;
int numbers[5];
for(int i = 0; i < 5; i++)
{
int input;
ROS_INFO("please input number%d:",i);
std::cin >> input;
if(input > -100 && input < 100)
{
numbers[i] = input;
}
else
{
ROS_INFO("wrong number!");
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
--i; // 保持索引不变,以便重新输入
continue;
}
numbers[i] = input;
}
num.request.num1 = numbers[0];
num.request.num2 = numbers[1];
num.request.num3 = numbers[2];
num.request.num4 = numbers[3];
num.request.num5 = numbers[4];
bool flag;
flag = client.call(num);
if(flag)
{
ROS_INFO("sort successful");
ROS_INFO("results: %d %d %d %d %d",num.response.num1, num.response.num2, num.response.num3, num.response.num4, num.response.num5);
}
return 0;
}
服务端代码:
#include "ros/ros.h"
#include "service_client/sort.h"
bool do_sort(service_client::sort::Request& req,service_client::sort::Response& resp)
{
int num[5];
num[0] = req.num1;
num[1] = req.num2;
num[2] = req.num3;
num[3] = req.num4;
num[4] = req.num5;
int k;
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4-i; j++)
{
if(num[j] > num[j+1])
{
k = num[j];
num[j] = num[j+1];
num[j+1] = k;
}
}
}
resp.num1 = num[0];
resp.num2 = num[1];
resp.num3 = num[2];
resp.num4 = num[3];
resp.num5 = num[4];
return true;
}
int main(int argc, char *argv[])
{
ros::init(argc, argv, "server");
ros::NodeHandle nh;
ros::ServiceServer server = nh.advertiseService("sort",do_sort);
ros::spin();
return 0;
}
运行结果:
实现了检测是否不在-100 到 100 同时完成了排序
win
三、代码讲解
略
缺陷:
服务消息不知道怎么定义为数组,导致代码冗余
今天就到这里了,明天见.
标签:sort,int32,int,Day04,----,xxb,num,client,ros From: https://blog.csdn.net/chenmoxuexi/article/details/137549542