前言
ros服务通信是一种请求响应的模式,有服务端和客户端。服务端接受客户端请求的数据后,响应数据到客户端。服务名在服务端和客户端需要配置一致才可建立通信。
本案例为实现简单的数据求和。客户端请求中有两个数据,服务端响应这两个数据的和。
一、配置srv文件
1、首先在功能包目录下创建一个名为“srv”的文件夹,之后在“srv”文件夹下创建一个.srv文件。我这里的文件名为AddInts.srv。目录结构如下:
2、在AddInts.srv中自定义数据类型,num1、num2为请求的2个数据,sum为响应的数据,输入:
int32 num1
int32 num2
---
int32 sum
注意:请求的数据和响应的数据之间需要用 --- 分割。
3、打开package.xml文件添加2行配置:
<!--如果编译时需要message文件就要导入message_generation-->
<build_depend>message_generation</build_depend>
<!--如果运行时需要message文件就要导入message_runtime-->
<exec_depend>message_runtime</exec_depend>
4、打开CmakeLists.txt,找到以下几条语句,增加以下配置:
#编译时依赖
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
#增加message_generation,编译时需要依赖message_generation
message_generation
)
#添加自定义的srv文件,意味着编译srv目录下的AddInts.srv文件
add_service_files(
FILES
AddInts.srv
)
#注释放开,不需要修改。意味着如果要编译AddInts.srv 要依赖于std_msgs
generate_messages(
DEPENDENCIES
std_msgs
)
#运行时依赖message_runtime(这儿不配置也能编译通过)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES pub_sub
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
5、编译,编译成功后查看devel/include/xxxx下是否生成了AddInts.h、AddIntsRequest.h、AddIntsResponse.h文件。如果成功生成了,那么你的配置是没有问题的。如果编译失败或没有生成.h文件,那么请检查前面的配置是否正确。
二、编写代码
1、编写代码之前,打开c_cpp_properties.json文件,添加AddInts.h所在的目录。我这里的目录是“"/home/sun/demo_pub_sub/devel/include”,建议后面直接写上/**
2、创建server.cpp(服务端)、client.cpp(客户端)两个文件,写入以下代码(注意包含AddInts.h头文件):
server.cpp(服务端)
#include "ros/ros.h"
#include "server_client/AddInts.h"
bool callBack(server_client::AddInts::Request& req,server_client::AddInts::Response& resp)
{
//请求数据req
int num1 = req.num1;
int num2 = req.num2;
ROS_INFO("server收到的请求数据为:num1 = %d,num2 = %d",num1,num2);
//返回的响应数据resp
resp.sum = num1 + num2;
return true;
}
int main(int argc, char *argv[])
{
//解决中文乱码输出
setlocale(LC_ALL,"");
//初始化ros节点(节点名唯一)
ros::init(argc,argv,"server");
//创建ros句柄
ros::NodeHandle nh;
//创建服务对象,callBack(自定义回调函数,参数名为...Request,...Response,返回值为bool类型)
ros::ServiceServer server = nh.advertiseService("AddInts",callBack);
ROS_INFO("服务启动....");
//回头处理回调函数
ros::spin();
return 0;
}
client.cpp(客户端)
#include "ros/ros.h"
#include "server_client/AddInts.h"
int main(int argc, char *argv[])
{
//解决中文输出乱码
setlocale(LC_ALL,"");
//初始化ros节点(节点名唯一)
ros::init(argc,argv,"client");
//创建ros句柄
ros::NodeHandle nh;
//创建客户端对象
ros::ServiceClient client = nh.serviceClient<server_client::AddInts>("AddInts");
//请求数据
server_client::AddInts ai;
ai.request.num1 = 100;
ai.request.num2 = 200;
//发送请求,返回值为bool类型
bool ret = client.call(ai);
if(ret)
{
ROS_INFO("请求成功,响应结果:%d",ai.response.sum);
}
else
{
ROS_ERROR("请求失败....");
return -1;
}
return 0;
}
编写CmakeLists.txt,加入以下几行:
add_executable(server src/server.cpp)
add_executable(client src/client.cpp)
add_dependencies(server ${PROJECT_NAME}_gencpp)
add_dependencies(client ${PROJECT_NAME}_gencpp)
target_link_libraries(server
${catkin_LIBRARIES}
)
target_link_libraries(client
${catkin_LIBRARIES}
)
4、vscode中 ctrl + shift + B 编译
三、运行
1、在工作空间目录下打开终端,依次运行以下三个程序:
- roscore
- rosrun server_client server
- rosrun server_client client
注意:这里有可能运行时报错 “package xxxx not found”的错误。只需要在每个终端窗口中都运行一遍source ./devel/setup.bash ,再次运行时就没有报错了。
2、查看终端(左侧为roscore,右上为server,右下client 。可以看出客户端请求了2个数据为100、200到服务端。服务端响应数据之和300。