[ROS Tutorial] Service Communication


1. Process

Service communication is also an extremely common communication mode in ROS. Service communication is based on the request response mode and is a response mechanism. That is: a node A sends a request to another node B, and B receives the processing request and generates a response result and returns it to A. In ROS, implementing service communication only requires the following steps:

  1. To determine the data type of the request sent by the client and the data type of the server response , you need to customize the .srv file, modify the CMakeLists.txt file and package.xml file and recompile
  2. Write the cpp files of the publisher and subscriber, modify the CMakeLists.txt file and recompile
  3. Start the publisher node and subscriber node respectively. You must start the server first and then the client.

2. Custom request and response data

2.1 std_msgs built-in type

  • Correspondence between built-in types and C++ and Python:
Primitive Type C++ Python
bool uint8_t bool
you8 int8_t int
uint8 uint8_t int
int16 int16_t int
uint16 uint16_t int
int32 uint32_t int
uint64 uint64_t long int
float32 float float
float64 double float
string std::string str bytes
time ros::Time rospy.Time
duration ros::Duration rospy.Duration
  • Correspondence between arrays of built-in types and C++ and Python:
Primitive Type C++ Python
variable-length std::vector tuple
fixed-length boost::array<T, length>或std::vector tuple

2.2 Write .srv file

Examples are as follows:

#文件名AddInt.srv
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
  • The three horizontal lines in the middle are used to distinguish request data and response data.

2.3 Modify the package.xml file

  • Check whether the following compilation dependencies exist
<build_depend>message_generation</build_depend>
  • Check whether the following execution dependencies exist
<exec_depend>message_generation</exec_depend>

2.4 Modify the CMakeLists.txt file

2.4.1 Modify the find_package command

# 需要加入 message_generation,必须有 std_msgs
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)

2.4.2 Add add_message_files command

## 配置 srv 源文件
add_service_files(
  FILES
  AddInt.srv
)

2.4.3 Add generate_messages command

generate_messages(
  DEPENDENCIES
  std_msgs
)

Among them, the add_service_files directive must be in front of the generate_messages directive , and then it can be compiled in the workspace directory.

2.5 View header files

After the above steps, ${workspace}/devel/include/${package}/the header file should appear in the directory, as shown in the figure:

Insert image description here

  • If it does not appear, the next steps cannot be performed. At this time, you only need to ${workspace}/delete all the build directory and devel directory in the directory, and then recompile.
rm -rf build/
rm -rf devel/
catkin_make

3.Write cpp file

3.1 Function package directory file tree

Insert image description here

3.2 Modify the CMakeLists.txt file

3.2.1 Add add_executable command

add_executable(server src/server.cpp)
add_executable(client src/client.cpp)

3.2.2 Add add_dependencies directive

add_dependencies(server ${
    
    PROJECT_NAME}_gencpp)
add_dependencies(client ${
    
    PROJECT_NAME}_gencpp)

3.2.3 Add target_link_libraries command

target_link_libraries(server
        ${
    
    catkin_LIBRARIES}
        )
target_link_libraries(client
        ${
    
    catkin_LIBRARIES}
        )

3.3 Server cpp

Examples are as follows:

/*
    需求:
        编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
        服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
        客户端再解析

    服务器实现:
        1.包含头文件
        2.初始化 ROS 节点
        3.创建 ROS 句柄
        4.创建 服务 对象
        5.回调函数处理请求并产生响应
        6.由于请求有多个,需要调用 ros::spin()

*/
// 1.包含头文件
#include "ros/ros.h"
#include "serve/AddInt.h"

// bool 返回值由于标志是否处理成功
bool reponse(serve::AddInt::Request& req,
           serve::AddInt::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,"");
    // 2.初始化 ROS 节点
    ros::init(argc,argv,"server");
    // 3.创建 ROS 句柄
    ros::NodeHandle nh;
    // 4.创建 服务 对象,回调函数的返回值必须是布尔类型
    ros::ServiceServer server = nh.advertiseService("AddInt",reponse);
    ROS_INFO("服务已经启动....");
    //     5.回调函数处理请求并产生响应
    //     6.由于请求有多个,需要调用 ros::spin()
    ros::spin();
    return 0;
}
  • The return value of the callback function when creating the service object must be of Boolean type

3.4 Client cpp

Examples are as follows:

/*
    需求:
        编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
        服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
        客户端再解析

    服务器实现:
        1.包含头文件
        2.初始化 ROS 节点
        3.创建 ROS 句柄
        4.创建 客户端 对象
        5.请求服务,接收响应

*/
// 1.包含头文件
#include "ros/ros.h"
#include "serve/AddInt.h"

int main(int argc, char *argv[])
{
    
    
    //设置编码
    setlocale(LC_ALL,"");

    // 调用时动态传值,如果通过 launch 的 args 传参,需要传递的参数个数 +3
    if (argc != 3)
        // if (argc != 5)//launch 传参(0-文件路径 1传入的参数 2传入的参数 3节点名称 4日志路径)
    {
    
    
        ROS_ERROR("请提交两个整数");
        return 1;
    }


    // 2.初始化 ROS 节点
    ros::init(argc,argv,"client");
    // 3.创建 ROS 句柄
    ros::NodeHandle nh;
    // 4.创建 客户端 对象
    ros::ServiceClient client = nh.serviceClient<serve::AddInt>("AddInt");
    //等待服务启动成功
    //方式1
    ros::service::waitForService("AddInt");
    //方式2
    // client.waitForExistence();
    // 5.组织请求数据
    serve::AddInt ai;
    ai.request.num1 = atoi(argv[1]);
    ai.request.num2 = atoi(argv[2]);
    // 6.发送请求,返回 bool 值,标记是否成功
    bool flag = client.call(ai);
    // 7.处理响应
    if (flag)
    {
    
    
        ROS_INFO("请求正常处理,响应结果:%d",ai.response.sum);
    }
    else
    {
    
    
        ROS_ERROR("请求处理失败....");
        return 1;
    }

    return 0;
}

4.Effect

Insert image description here

Insert image description here

Insert image description here

Insert image description here

Guess you like

Origin blog.csdn.net/qq_50791664/article/details/130022406