ROS-7.3.创建和运行服务服务器与客户端节点

2023-05-16

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
##这是进行catkin构建时所需的组件包。
##依赖包是message_generation、std_msgs和roscpp。如果这些包不存在,在构建过程中会发生错误。
find_package(catkin REQUIRED COMPONENTS message_generation std_msgs roscpp)

##服务声明:SrvTutorial.srv
add_service_files(FILESS rvTutorial.srv)

##这是一个设置依赖消息的选项。
##如果未安装std_msgs,则在构建过程中会发生错误。
generate_messages(DEPENDENCIESstd_msgs)
##这是catkin功能包选项,它描述了库、catkin构建依赖和依赖系统的功能包。
catkin_package(
	LIBRARIESros_tutorials_service
	CATKIN_DEPENDS std_msgs roscpp
)
##设置包含目录。
include_directories(${catkin_INCLUDE_DIRS})

##这是service_server节点的构建选项。
##设置可执行文件、目标链接库和附加依赖项。
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"                          // ROS Default Header File
#include "ros_tutorials_service/SrvTutorial.h"// SrvTutorial Service File Header (Automatically created after build)
#include <cstdlib>                            // Library for using the "atoll" function

#include <iostream>
using namespace std;
int main(int argc, char **argv)               // Node Main Function
{
  ros::init(argc, argv, "service_client");    // Initializes Node Name

  ros::NodeHandle nh;       // Node handle declaration for communication with ROS system

  // Declares service client 'ros_tutorials_service_client'
  // using the 'SrvTutorial' service file in the 'ros_tutorials_service' package.
  // The service name is 'ros_tutorial_srv'
  ros::ServiceClient ros_tutorials_service_client = nh.serviceClient<ros_tutorials_service::SrvTutorial>("ros_tutorial_srv");

  // Declares the 'srv' service that uses the 'SrvTutorial' service file
  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;
  // Request the service. If the request is accepted, display the response value
  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(使用前将#替换为@)

ROS-7.3.创建和运行服务服务器与客户端节点 的相关文章

随机推荐