7.3创建和运行服务服务器与客户端节点
- 介绍
- 创建功能包
- 修改功能包配置文件
- 修改构建配置文件
- 创建服务文件
- 创建服务服务器节点
- 创建服务客户端节点
- 构建节点
- 运行服务服务器
- 运行服务客户端
- rosservice call命令的用法
- GUI工具Service caller用法
- 代码链接
介绍
服务由服务服务器(service server)和服务客户端(service client)组成,其中服务服务器仅在收到请求(request)时才会响应(response),而服务客户端则会发送请求并接收响应。与话题不同,服务是一次性消息通信。因此,当服务的请求和响应完成时,两个节点的连接会被断开。
这种服务通常在让机器人执行特定任务时用到。或者用于需要在特定条件下做出反应的节点。
优点:由于是一次性的通信方式,因此对网络的负载很小,所以是一种非常有用的通信手段,例如被用作一种代替话题的通信手段
创建功能包
$cd ~/catkin_ws/src
$catkin_create_pkg ros_tutorials_service message_generation std_msgs roscpp
其中:
message_generation是用于创建新消息的功能包;
std_msgs是ROS的标准消息功能包;
roscpp是在ROS中使用C/C++的客户端程序库。
这些依赖包必须在提前安装好;可以选择在创建功能包是指定依赖关系,也可以在创建功能包之后在package.xml中进行修改。
修改功能包配置文件
在创建功能包的时候,会在“~/catkin_ws/src”目录中生成ros_tutorials_service功 能 包 目 录 , 在 这 个 功 能 包 目 录 中 会 生 成 RO S 功 能 包 所 要 配 备 的 默 认 目 录 , 以 及CMakeLists.txt和package.xml文件。下面使用ls命令检查内容。
$cd ros_tutorials_service
$ls
include →头文件目录
CMakeLists.txt →构建配置文件
src →源代码目录
package.xml →功能包配置文件
修改构建配置文件
ROS所必需的配置文件之一package.xml是一个包含功能包信息的XML文件,它描述了功能包名称、作者、许可证和依赖包。使用以下命令使用编辑器(gedit、vim、emacs等)打开文件,并修改它,以匹配当前节点。推荐使用subl,嘿嘿。
ROS的构建系统catkin以CMake为基础,它在功能包目录中的CMakeLists.txt文件里描述了构建环境。该文件设置可执行文件的创建、依赖包优先构建、链接生成等。与上述ros_tutorials_topic不同,如果添加了发布者节点、订阅者节点和msg文件,则ros_tutorials_service功能包将添加新的服务服务器节点、服务客户端节点和服务文件(*.srv)。
$ subl CMakeLists.txt
find_package(catkin REQUIRED COMPONENTS message_generation std_msgs roscpp)
add_service_files(FILESS rvTutorial.srv)
generate_messages(DEPENDENCIESstd_msgs)
catkin_package(
LIBRARIESros_tutorials_service
CATKIN_DEPENDS std_msgs roscpp
)
include_directories(${catkin_INCLUDE_DIRS})
add_executable(service_server src/service_server.cpp)
add_dependencies(service_server${${PROJECT_NAME}_EXPORTED_TARGETS}${catkin_EXPORTED_TARGETS})
target_link_libraries(service_server${catkin_LIBRARIES})
add_executable(service_client src/service_client.cpp)
add_dependencies(service_client${${PROJECT_NAME}_EXPORTED_TARGETS}${catkin_EXPORTED_TARGETS})
target_link_libraries(service_client${catkin_LIBRARIES})
创建服务文件
这是在构建本次的节点中使用的SrvTutorial.srv时所包含的内容。现在您还没有创建SrvTutorial.srv,请按以下顺序创建它。
$roscd ros_tutorials_service →移动到功能包目录
$cd srv →转到创建的srv目录
$mkdir srv →在功能包中创建一个名为srv的新服务目录
$gedit SrvTutorial.srv →新建和修改SrvTutorial.srv文件
在这里我们设计一个加减乘除服务请求,服务器负责计算,客户端负责将要计算的数据上传。
数据为a b 操作为operation 结果为result
如下所示。“—”是分隔符,用于分隔请求和响应。除了请求和响应之间有一个分隔符之外,它与上述话题的消息相同。
int64 a
int64 b
int64 operation
---
int64 result
创建服务服务器节点
$roscd ros_tutorials_service/src →移动到功能包的源代码目录
$gedit service_server.cpp →创建和修改源文件
#include "ros/ros.h"
#include "ros_tutorials_service/SrvTutorial.h"
#define PLUS 1
#define MINUS 2
#define MULTIPLICATION 3
#define DIVSION 4
bool calculation(ros_tutorials_service::SrvTutorial::Request &req,
ros_tutorials_service::SrvTutorial::Response &res)
{
switch(req.operation)
{
case PLUS:
res.result = req.a + req.b;break;
case MINUS:
res.result = req.a - req.b;break;
case MULTIPLICATION:
res.result = req.a * req.b;break;
case DIVSION:
if (req.b == 0)
{
res.result = 0; break;
}
else
{
res.result = req.a / req.b;break;
}
default:
res.result = req.a + req.b;break;
}
ROS_INFO("Request:x = %ld, y = %ld", (long int) req.a, (long int) req.b);
ROS_INFO("req.operation = %ld", req.operation);
ROS_INFO("sending back response:%ld", (long int) res.result);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "service_server");
ros::NodeHandle nh;
ros::ServiceServer ros_tutorials_service_server = nh.advertiseService("ros_tutorial_srv",calculation);
ROS_INFO("read srv serer!");
ros::Rate r(10);
while(1)
{
ros::spinOnce();
r.sleep();
}
return 0;
}
创建服务客户端节点
$roscd ros_tutorials_service/src →移动到功能包的源代码目录
$gedit service_client.cpp →创建和修改源文件
#include "ros/ros.h"
#include "ros_tutorials_service/SrvTutorial.h"
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "service_client");
ros::NodeHandle nh;
ros::ServiceClient ros_tutorials_service_client = nh.serviceClient<ros_tutorials_service::SrvTutorial>("ros_tutorial_srv");
ros_tutorials_service::SrvTutorial srv;
int num1, num2, operation;
cout << "a: b: operation:"<<endl;
cin >> num1 >> num2 >> operation;
srv.request.a = (num1);
srv.request.b = (num2);
srv.request.operation = operation;
if (ros_tutorials_service_client.call(srv))
{
ROS_INFO("send srv, srv.Request.a and b: %ld, %ld, operation: %ld", (long int)srv.request.a, (long int)srv.request.b, (long int)srv.request.operation);
ROS_INFO("receive srv, srv.Response.result: %ld", (long int)srv.response.result);
}
else
{
ROS_ERROR("Failed to call service ros_tutorial_srv");
return 1;
}
return 0;
}
构建节点
使用以下命令构建ros_tutorials_service功能包的服务文件、服务服务器节点和客户端节点。ros_tutorials_service功能包的源文件位于“/catkin_ws/src/ros_tutorials_service/src”目录中,服务文件位于“/catkin_ws/src/ros_tutorials_service/srv”目录中。
$cd ~/ catkin_ws&&catkin_make → 转到 catkin 目录并运行 catkin 构建
生成的文件位于“/catkin_ws/build”目录和“/catkin_ws/devel”目录。目录“/catkin_ws/build”包含catkin构建中使用的配置,“/catkin_ws/devel/lib/ros_tutorials_service”包含可执行文件,“~/catkin_ws/devel/include/ros_tutorials_service” 保存从消息文件自动生成的服务头文件。如果您想知道这些文件,请进入各自的目录查看。
运行服务服务器
运行主节点master
$roscore
运行服务服务器节点
$rosrun ros_tutorials_service service_server
显示结果
运行服务客户端
运行服务客户端节点
$rosrun ros_tutorials_service service_client
显示结果
rosservice call命令的用法
GUI工具Service caller用法
最后,介绍使用rqt的ServiceCaller的方法,它使用一个GUI形式的界面。首先,运行ROS的GUI工具rqt。
$rqt
然后从rqt程序的菜单中选择[插件[Plugins]→[Service]→[Service Caller],然后出
现如下屏幕。
代码链接
代码链接 https://github.com/DoubleYuanL/7.3.-Creating-and-Running-Service-Servers-and-Client-Nodes.git
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)