Description: 本教程介绍如何用C++编写服务和客户端节点。
                               Tutorial Level: BEGINNER 
                             1 编写服务节点 
                                这里,我们将创建简单的服务(Service)节点add_two_ints_server,该节点将接收两个整数,并返回它们的和。 
                              将当前目录切换到之前的教程中创建的beginner_tutorials包中: 
                             
                            
                               $ roscd beginner_tutorials 
  |   
 
                                请确保你已经按照之前教程中的指示创建了本教程中需要的服务AddTwoInts.srv。(确保在页面顶部选对了所使用的构建工具) 
                            1.1 代码 
                                在beginner_tutorials包中创建src/add_two_ints_server.cpp文件并粘贴以下内容进去: 
                             
                            
                                  1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 
   4 bool add(beginner_tutorials:: AddTwoInts::Request  &req,
   5          beginner_tutorials:: AddTwoInts::Response &res)
   6 {
   7   res.sum = req.a + req.b;
   8   ROS_INFO("request: x=%ld, y=%ld",  (long int)req.a, (long int)req.b);
   9   ROS_INFO("sending back response: [%ld] ", (long int)res.sum);
  10   return true;
  11 }
  12 
  13 int main(int argc, char **argv)
  14 {
  15   ros::init(argc, argv, "add_two_ints_server");
  16   ros::NodeHandle n;
  17 
  18   ros::ServiceServer service = n. advertiseService("add_two_ints", add);
  19   ROS_INFO("Ready to add two ints.");
  20   ros::spin();
  21 
  22   return 0;
  23 }
 
  |   
 
                                1.2  解释 
                                现在,让我们把代码分解。 
                             
                            
                                  1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 
 
  |   
 
                                beginner_tutorials/AddTwoInts.h是从我们之前创建的srv文件中生成的头文件。 
                             
                            
                                  4 bool add(beginner_tutorials:: AddTwoInts::Request  &req,
   5          beginner_tutorials:: AddTwoInts::Response &res)
 
  |   
 
                                这个函数提供了AddTwoInts服务,它接受srv文件中定义的请求(request)和响应(response)类型,并返回一个布尔值。 
                             
                            
                                  6 {
   7   res.sum = req.a + req.b;
   8   ROS_INFO("request: x=%ld, y=%ld",  (long int)req.a, (long int)req.b);
   9   ROS_INFO("sending back response: [%ld] ", (long int)res.sum);
  10   return true;
  11 }
  |   
 
                              
                                此处,两个整数被相加,和已经存储在了响应中。然后记录一些有关请求和响应的信息到日志中。完成后,服务返回true。 
                             
                            
                                 18   ros::ServiceServer service = n. advertiseService("add_two_ints", add);
 
  |   
 
                                在这里,服务被创建,并在ROS中宣告。 
                          2 编写客户端节点 
                                 2.1 代码 
                                在beginner_tutorials包中创建src/add_two_ints_client.cpp文件并粘贴以下内容进去: 
                             
                            
                                  1 #include "ros/ros.h"
   2 #include "beginner_tutorials/AddTwoInts.h"
   3 #include <cstdlib>
   4 
   5 int main(int argc, char **argv)
   6 {
   7   ros::init(argc, argv, "add_two_ints_client");
   8   if (argc != 3)
   9   {
  10     ROS_INFO("usage: add_two_ints_client X Y");
  11     return 1;
  12   }
  13 
  14   ros::NodeHandle n;
  15   ros::ServiceClient client = n.serviceClient <beginner_tutorials::AddTwoInts>("add_two_ints");
  16   beginner_tutorials::AddTwoInts srv;
  17   srv.request.a = atoll(argv[1]);
  18   srv.request.b = atoll(argv[2]);
  19   if (client.call(srv))
  20   {
  21  ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  22   }
  23   else
  24   {
  25  ROS_ERROR("Failed to call service add_two_ints");
  26     return 1;
  27   }
  28 
  29   return 0;
  30 }
  |   
 
                              
                                 2.2 解释 
                                现在,让我们把代码分解。 
                             
                            
                               
  15   ros::ServiceClient client = n.serviceClient <beginner_tutorials::AddTwoInts>("add_two_ints");
 
  |   
 
                              
                                这将为add_two_ints服务创建一个客户端。ros::ServiceClient对象的作用是在稍后调用服务。 
                             
                            
                                 16   beginner_tutorials::AddTwoInts srv;
  17   srv.request.a = atoll(argv[1]);
  18   srv.request.b = atoll(argv[2]);
 
  |   
 
                              
                                这里我们实例化一个自动生成的服务类,并为它的request成员赋值。一个服务类包括2个成员变量:request和response,以及2个类定义:Request和Response。 
                             
 
                              
                                此处实际上调用了服务。由于服务调用被阻塞,它将在调用完成后返回。如果服务调用成功,call()将返回true,并且srv.response中的值将是有效的。如果调用不成功,则call()将返回false且srv.response的值将不可用。 
                             3 构建节点 
                              
                                再来编辑一下beginner_tutorials里面的CMakeLists.txt文件,文件位于 ~/catkin_ws/src/beginner_tutorials/CMakeLists.txt,并将下面的代码添加在文件末尾: 
                              https://raw.github.com/ros/catkin_tutorials/master/ create_package_srvclient/catkin_ws/src/beginner _tutorials/CMakeLists.txt 
                             
                            
                                 27 add_executable(add_two_ints_server  src/add_two_ints_server.cpp)
  28 target_link_libraries (add_two_ints_server ${catkin_LIBRARIES})
  29 add_dependencies(add_two_ints_ server beginner_tutorials_gencpp)
  30 
  31 add_executable(add_two_ints_ client src/add_two_ints_client.cpp)
  32 target_link_libraries(add_two_ints_ client ${catkin_LIBRARIES})
  33 add_dependencies(add_two_ints_ client beginner_tutorials_gencpp)
 
  |   
 这将创建两个可执行文件add_two_ints_server和add_two_ints_client,默认情况下,它们将被放到软件包目录下的devel空间中,即~/catkin_ws/devel/lib/<package 
                                name>。你可以直接调用可执行文件,也可以使用rosrun来调用它们。它们没有被放在<prefix>/bin中,因为这样在将软件包安装到系统时会污染PATH环境变量。但如果你希望在安装时将可执行文件放在PATH中,可以配置安装目标,参见CMakeLists.txt。 
                              现在可以运行catkin_make: 
                            
                            
                               # 在你的catkin工作空间下
cd ~/catkin_ws
catkin_make 
  |   
                              
                              
                                如果你的构建过程因为某些原因而失败: 
                              确保已按照上一教程中的说明进行操作:创建AddTwoInts.srv。 
                              
                                现在你已经编写了一个简单的服务和客户端,开始检验简单的服务和客户端吧。 
                                                             |