一个服务被分成服务服务器和服务客户端,其中服务服务器只在有请求(request)的时候才响应(response),而服务客户端会在发送请求后接收响应。与话题不同,服务是一次性消息通信。ROS提供了叫做服务的消息同步方法,是一种一对一的机制。
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 }
代码解释
现在,让我们分解代码。
beginner_tutorials/AddTwoInts.h是之前创建的 srv 文件生成的头文件。srv:请求和相应的文件
此函数提供添加两个整数的服务,它接受 srv 文件中定义的请求和响应类型并返回布尔值。
在这里,两个整数被添加并存储在响应中。然后记录有关请求和响应的一些信息。最后,服务在完成时返回 true。%ld 表示按 long int 格式
该服务是通过 ROS 创建和发布的的。
写入客户端节点
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 }
代码解释
现在,让我们分解代码。
这将为add_two_ints的服务创建客户端。ros::ServiceClient对象用于稍后调用服务。
在这里,实例化一个自动生成的服务类,并将值分配给其请求成员。服务类包含两个成员,request和response。它还包含两个类定义,Request和Response.atoll:把字符串转换成长长整型数(64位)
这实际上调用了服务。由于服务调用正在阻塞,因此一旦调用完成,它将返回。如果服务调用成功,call() 将返回 true,并且srv.response中的值将有效。如果调用不成功,call() 将返回 false,并且 srv.response中的值将无效.
运行节点
运行节点需要启动 ROS 核心。打开一个新外壳,然后键入:
roscore
如果一切顺利,您应该会看到如下所示的输出:
... logging to /u/takayama/.ros/logs/83871c9c-934b-11de-a451-
001d927076eb/roslaunch-ads-31831.log
... loading XML file
[/wg/stor1a/rosbuild/shared_installation/ros/tools/roslaunch/roscore.xml]
Added core node of type [rosout/rosout] in namespace [/]
started roslaunch server http://ads:54367/
SUMMARY
======
NODES
changing ROS_MASTER_URI to [http://ads:11311/] for starting master locally
starting new master (master configured for auto start)
process[master]: started with pid [31874]
ROS_MASTER_URI=http://ads:11311/
setting /run_id to 83871c9c-934b-11de-a451-001d927076eb
+PARAM [/run_id] by /roslaunch
+PARAM [/roslaunch/uris/ads:54367] by /roslaunch
process[rosout-1]: started with pid [31889]
started core service [/rosout]
+SUB [/time] /rosout http://ads:33744/
+SERVICE [/rosout/get_loggers] /rosout http://ads:33744/
+SERVICE [/rosout/set_logger_level] /rosout http://ads:33744/
+PUB [/rosout_agg] /rosout http://ads:33744/
+SUB [/rosout] /rosout http://ads:33744/
现在一切都设置为运行服务器和客户端。
运行服务器
首先运行服务器。打开一个新外壳并键入:
rosrun beginner_tutorials add_two_ints_server
您应该看到类似于以下内容的内容:
Ready to add two ints.
运行客户端
现在让我们在另一个 shell 中运行具有必要参数的客户端:
$ rosrun beginner_tutorials add_two_ints_client 1 3
在客户端的 shell 中,您应该看到类似于以下内容的内容:
Sum: 4
相反,在服务器的 shell 中,您应该看到类似于以下内容的内容:
request: x=1, y=3
sending back response: [4]