详解ros::ServiceServer的使用方法

详解ros::ServiceServer的使用方法

ros::ServiceServer是ROS(Robot Operating System)中提供服务的关键组件。它允许节点向其他节点提供服务,使得其他节点可以请求并获取服务结果。在ROS中,服务是一种同步通信机制,允许节点之间进行请求-应答式的通信。

以下是使用ros::ServiceServer的详细步骤:

  1. 包含必要的头文件:
    在C++代码中,需要包含服务的头文件和ros/ros.h。假设服务的类型为my_package::MyService,则需要包含以下头文件:
    1
    2
    #include "ros/ros.h"
    #include "my_package/MyService.h"
  2. 编写服务处理函数:
    编写一个函数,该函数用于处理服务请求并生成响应。函数的参数类型应该是服务请求的常量指针和服务响应的指针。例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    bool myServiceCallback(my_package::MyService::Request &req,
    my_package::MyService::Response &res)
    {
    // 处理服务请求,例如:
    res.result = req.a + req.b;

    // 返回值表示服务是否成功处理
    return true;
    }
  3. 初始化ROS节点:
    1
    2
    3
    4
    5
    6
    int main(int argc, char **argv)
    {
    ros::init(argc, argv, "my_service_server");
    ros::NodeHandle nh;
    // ...
    }
  4. 创建ros::ServiceServer实例:
    在main()函数中,使用NodeHandle的advertiseService()方法创建一个ros::ServiceServer实例。将服务处理函数作为回调传递给此方法。例如:
    1
    2
    3
    // ...
    ros::ServiceServer service = nh.advertiseService("my_service", myServiceCallback);
    // ...
    在上述示例中,”my_service”是服务的名称,其他节点可以使用此名称请求服务。
  5. 进入ROS事件循环:
    在main()函数中,调用ros::spin()函数,使程序进入ROS事件循环。当有节点请求服务时,服务处理函数将被调用:
    1
    2
    3
    4
      // ...
    ros::spin();
    return 0;
    }
    以上是使用ros::ServiceServer的详细步骤。请注意,使用ros::ServiceServer时,需要确保已经正确地生成和配置了服务消息。在实际应用中,ros::ServiceServer为节点间同步通信提供了方便、可靠的方法。

接下来,我们将通过一个简单的实例来演示如何使用ros::ServiceServer。在这个例子中,我们将创建一个名为“add_two_ints”的服务,该服务接收两个整数作为输入,并返回它们的和。

  1. 创建一个新的ROS包:
    1
    $ catkin_create_pkg add_two_ints_server rospy std_msgs
  2. 在add_two_ints_server包中的srv目录下,创建一个名为AddTwoInts.srv的文件,并添加以下内容:
    1
    2
    3
    4
    int64 a
    int64 b
    ---
    int64 sum
    这定义了一个服务,该服务有两个输入参数(a和b)和一个输出参数(sum)。
  3. 在CMakeLists.txt中启用服务生成:
    在find_package()函数中添加message_generation:
    1
    2
    3
    4
    5
    find_package(catkin REQUIRED COMPONENTS
    rospy
    std_msgs
    message_generation
    )
    在catkin_package()函数中添加CATKIN_DEPENDS message_runtime:
    1
    2
    3
    4
    catkin_package(
    ...
    CATKIN_DEPENDS rospy std_msgs message_runtime
    )
    添加服务文件和生成服务消息的指令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    add_service_files(
    FILES
    AddTwoInts.srv
    )

    generate_messages(
    DEPENDENCIES
    std_msgs
    )
  4. 在src目录下创建一个名为add_two_ints_server.cpp的文件,添加以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include "ros/ros.h"
    #include "add_two_ints_server/AddTwoInts.h"

    bool add(add_two_ints_server::AddTwoInts::Request &req,
    add_two_ints_server::AddTwoInts::Response &res)
    {
    res.sum = req.a + req.b;
    ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
    ROS_INFO("sending back response: [%ld]", (long int)res.sum);
    return true;
    }

    int main(int argc, char **argv)
    {
    ros::init(argc, argv, "add_two_ints_server");
    ros::NodeHandle nh;

    ros::ServiceServer service = nh.advertiseService("add_two_ints", add);
    ROS_INFO("Ready to add two ints.");
    ros::spin();

    return 0;
    }
  5. 在CMakeLists.txt中添加可执行文件:

    1
    2
    3
    add_executable(add_two_ints_server_node src/add_two_ints_server.cpp)
    target_link_libraries(add_two_ints_server_node ${catkin_LIBRARIES})
    add_dependencies(add_two_ints_server_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
  6. 使用catkin_make构建包并设置环境变量:

    1
    2
    $ catkin_make
    $ source devel/setup.bash
  7. 运行服务:

    1
    $ rosrun add_two_ints_server add_two_ints_server_node

    现在,add_two_ints服务已经运行并准备好接收请求。要测试服务,请创建一个简单的服务客户端节点(ros::ServiceClient)来请求服务并检查响应。

本示例演示了如何创建一个简单的ros::ServiceServer,通过编写服务处理函数和配置CMakeLists.txt来生成和使用服务消息。在实际应用中,可以根据需求创建更复杂的服务来处理不同类型的任务,例如机器人控制、传感器数据处理或路径规划等。

接下来,我们将演示如何创建一个简单的服务客户端(ros::ServiceClient)来请求刚刚创建的“add_two_ints”服务。

  1. 在刚才创建的add_two_ints_server包的src目录下,创建一个名为add_two_ints_client.cpp的文件,并添加以下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include "ros/ros.h"
    #include "add_two_ints_server/AddTwoInts.h"
    #include <cstdlib>

    int main(int argc, char **argv)
    {
    ros::init(argc, argv, "add_two_ints_client");
    if (argc != 3)
    {
    ROS_INFO("usage: add_two_ints_client X Y");
    return 1;
    }

    ros::NodeHandle nh;
    ros::ServiceClient client = nh.serviceClient<add_two_ints_server::AddTwoInts>("add_two_ints");
    add_two_ints_server::AddTwoInts srv;
    srv.request.a = atoll(argv[1]);
    srv.request.b = atoll(argv[2]);

    if (client.call(srv))
    {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
    }
    else
    {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
    }

    return 0;
    }
  2. 在CMakeLists.txt中添加客户端可执行文件:
    1
    2
    3
    add_executable(add_two_ints_client_node src/add_two_ints_client.cpp)
    target_link_libraries(add_two_ints_client_node ${catkin_LIBRARIES})
    add_dependencies(add_two_ints_client_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
  3. 使用catkin_make构建包并设置环境变量:
    1
    2
    $ catkin_make
    $ source devel/setup.bash
  4. 在一个新的终端中,运行服务客户端节点:
    1
    $ rosrun add_two_ints_server add_two_ints_client_node 3 4
    如果一切正常,客户端将输出求和结果:
    1
    [ INFO] [1624515083.388228334]: Sum: 7
    这个简单的示例演示了如何创建一个服务客户端来请求ros::ServiceServer提供的服务。在实际应用中,可以根据需要创建不同类型的服务客户端来与服务交互。服务客户端和服务服务器之间的通信是同步的,这使得它们非常适合那些需要请求-响应模式的任务。

详解ros::ServiceServer的使用方法
https://qiangsun89.github.io/2023/04/19/详解ros-ServiceServer的使用方法/
作者
Qiang Sun
发布于
2023年4月19日
许可协议