详解ros::ServiceServer的使用方法
详解ros::ServiceServer的使用方法
ros::ServiceServer是ROS(Robot Operating System)中提供服务的关键组件。它允许节点向其他节点提供服务,使得其他节点可以请求并获取服务结果。在ROS中,服务是一种同步通信机制,允许节点之间进行请求-应答式的通信。
以下是使用ros::ServiceServer的详细步骤:
- 包含必要的头文件:
在C++代码中,需要包含服务的头文件和ros/ros.h。假设服务的类型为my_package::MyService,则需要包含以下头文件:1
2#include "ros/ros.h"
#include "my_package/MyService.h" - 编写服务处理函数:
编写一个函数,该函数用于处理服务请求并生成响应。函数的参数类型应该是服务请求的常量指针和服务响应的指针。例如:1
2
3
4
5
6
7
8
9bool myServiceCallback(my_package::MyService::Request &req,
my_package::MyService::Response &res)
{
// 处理服务请求,例如:
res.result = req.a + req.b;
// 返回值表示服务是否成功处理
return true;
} - 初始化ROS节点:
1
2
3
4
5
6int main(int argc, char **argv)
{
ros::init(argc, argv, "my_service_server");
ros::NodeHandle nh;
// ...
} - 创建ros::ServiceServer实例:
在main()函数中,使用NodeHandle的advertiseService()方法创建一个ros::ServiceServer实例。将服务处理函数作为回调传递给此方法。例如:在上述示例中,”my_service”是服务的名称,其他节点可以使用此名称请求服务。1
2
3// ...
ros::ServiceServer service = nh.advertiseService("my_service", myServiceCallback);
// ... - 进入ROS事件循环:
在main()函数中,调用ros::spin()函数,使程序进入ROS事件循环。当有节点请求服务时,服务处理函数将被调用:以上是使用ros::ServiceServer的详细步骤。请注意,使用ros::ServiceServer时,需要确保已经正确地生成和配置了服务消息。在实际应用中,ros::ServiceServer为节点间同步通信提供了方便、可靠的方法。1
2
3
4// ...
ros::spin();
return 0;
}
接下来,我们将通过一个简单的实例来演示如何使用ros::ServiceServer。在这个例子中,我们将创建一个名为“add_two_ints”的服务,该服务接收两个整数作为输入,并返回它们的和。
- 创建一个新的ROS包:
1
$ catkin_create_pkg add_two_ints_server rospy std_msgs
- 在add_two_ints_server包中的srv目录下,创建一个名为AddTwoInts.srv的文件,并添加以下内容:这定义了一个服务,该服务有两个输入参数(a和b)和一个输出参数(sum)。
1
2
3
4int64 a
int64 b
---
int64 sum - 在CMakeLists.txt中启用服务生成:
在find_package()函数中添加message_generation:在catkin_package()函数中添加CATKIN_DEPENDS message_runtime:1
2
3
4
5find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation
)添加服务文件和生成服务消息的指令:1
2
3
4catkin_package(
...
CATKIN_DEPENDS rospy std_msgs message_runtime
)1
2
3
4
5
6
7
8
9add_service_files(
FILES
AddTwoInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
) 在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;
}在CMakeLists.txt中添加可执行文件:
1
2
3add_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})使用catkin_make构建包并设置环境变量:
1
2$ catkin_make
$ source devel/setup.bash运行服务:
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”服务。
- 在刚才创建的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;
} - 在CMakeLists.txt中添加客户端可执行文件:
1
2
3add_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}) - 使用catkin_make构建包并设置环境变量:
1
2$ catkin_make
$ source devel/setup.bash - 在一个新的终端中,运行服务客户端节点:如果一切正常,客户端将输出求和结果:
1
$ rosrun add_two_ints_server add_two_ints_client_node 3 4
这个简单的示例演示了如何创建一个服务客户端来请求ros::ServiceServer提供的服务。在实际应用中,可以根据需要创建不同类型的服务客户端来与服务交互。服务客户端和服务服务器之间的通信是同步的,这使得它们非常适合那些需要请求-响应模式的任务。1
[ INFO] [1624515083.388228334]: Sum: 7
详解ros::ServiceServer的使用方法
https://qiangsun89.github.io/2023/04/19/详解ros-ServiceServer的使用方法/