在使用了话题通讯之后,服务通讯一直没怎么使用过,这里记录一下服务通讯的使用经历。
话题通讯有点儿像是广播数据,就像村口的大喇叭一样,一直以自己的频率去广播消息,把话题消息广播出去,只要在广场上的人都能听见。
而服务不一样,服务是基于请求的。跟网页服务是一样的机理,就是当我们点击网页中的按钮的时候,网站服务器相应一下,把相应的网页给我们客户端显示出来。这个属于一问一答的形式,问了才答,不问不答。
1.相关命令
rosservice list //打印服务列表
rosservice info 服务名称 //打印该服务相关信息
rosservice args 服务名称 //打印服务参数
rosservice type 服务名称 //打印消息类型
我们可以把小乌龟例程跑起来配合命令来做实验
1)打印服务列表
rosservice list //打印服务列表
打印效果如下:
2)打印该服务相关信息
rosservice info /spawn
效果如下:
3)打印服务参数
rosservice args /spawn
打印效果如下
4)打印消息类型
rosservice type /spawn
打印效果如下
2.自定义服务消息类型
服务端程序:
#include "ros/ros.h"
#include "hello/service.h"
bool doReq(hello::service::Request& req,
hello::service::Response& resp){
int num1 = req.num1;
int num2 = req.num2;
ROS_INFO("服务器接收到的请求数据为:num1 = %d, num2 = %d",num1, num2);
//逻辑处理
if (num1 < 0 || num2 < 0)
{
ROS_ERROR("提交的数据异常:数据不可以为负数");
return false;
}
//如果没有异常,那么相加并将结果赋值给 resp
resp.sum = num1 + num2;
return true;
}
int main(int argc,char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"AddInts_Server");
ros::NodeHandle nh;
ros::ServiceServer server = nh.advertiseService("AddInts",doReq);
ROS_INFO("服务已经启动....");
ros::spin();
return 0;
}
这里已经可以用命令行尝试发起请求了,如下图所示。
客户端程序:
#include "ros/ros.h"
#include "hello/service.h"
int main(int argc,char *argv[])
{
setlocale(LC_ALL,"");
if (argc != 3)
// if (argc != 5)//launch 传参(0-文件路径 1传入的参数 2传入的参数 3节点名称 4日志路径)
{
ROS_ERROR("请提交两个整数");
return 1;
}
ros::init(argc,argv,"AddInts_Client");
ros::NodeHandle nh;
ros::ServiceClient client = nh.serviceClient<hello::service>("AddInts");
ros::service::waitForService("AddInts");
hello::service ai;
ai.request.num1 = atoi(argv[1]);
ai.request.num2 = atoi(argv[2]);
bool flag = client.call(ai);
if (flag)
{
ROS_INFO("请求正常处理,响应结果:%d",ai.response.sum);
}
else
{
ROS_ERROR("请求处理失败....");
return 1;
}
return 0;
}
运行客户端: rosrun hello client 参数一 参数二