ROS2 服务
ROS2 中的服务就类似于 RPC 调用,每个节点提供服务,其它节点可以调用服务并获取返回值
服务查看
查看节点提供的服务
1ros2 node info /turtlesim1 2 3 4 5 6 7 8 9 10 11 12 13 14 15Service Servers: /clear: std_srvs/srv/Empty /kill: turtlesim/srv/Kill /reset: std_srvs/srv/Empty /spawn: turtlesim/srv/Spawn /turtle1/set_pen: turtlesim/srv/SetPen /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute /turtle1/teleport_relative: turtlesim/srv/TeleportRelative /turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters /turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes /turtlesim/get_parameters: rcl_interfaces/srv/GetParameters /turtlesim/get_type_description: type_description_interfaces/srv/GetTypeDescription /turtlesim/list_parameters: rcl_interfaces/srv/ListParameters /turtlesim/set_parameters: rcl_interfaces/srv/SetParameters /turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically服务和话题一样,包括服务名和服务参数定义,可以查看服务的详细定义
1ros2 service info /spawn查看服务类型定义
1ros2 interface show turtlesim/srv/Spawn
这个定义表示输入参数为 x, y, theta, name ,其中 name 是可选的,返回值为 name
- ros2 命令行调用服务调用后的结果
1ros2 service call /spawn turtlesim/srv/Spawn "{x: 1.0, y: 1.0, theta: 0}"
定义服务描述文件
在
demo_interfaces下的srv目录自定义一个服务描述文件,名称叫AddInt.srvCMakeLists.txt 中添加编译
使用
colcon build编译
C++ 节点实现一个服务
创建一个功能包
1ros2 pkg create cpp_server_demo --destination-directory src --build-type ament_cmake --dependencies rclcpp demo_interfaces --license Apache-2.0写服务文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24#include "rclcpp/executors.hpp" #include "demo_interfaces/srv/add_int.hpp" void AddInt(demo_interfaces::srv::AddInt_Request::SharedPtr request, demo_interfaces::srv::AddInt_Response::SharedPtr response) { response->sum = request->a + request->b; RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %ld" " b: %ld", request->a, request->b); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%ld]", (long int)response->sum); } int main(int argc, char* argv[]) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("add_int_server"); auto service = node->create_service<demo_interfaces::srv::AddInt>("add_int", AddInt); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Ready to add ints."); rclcpp::spin(node); rclcpp::shutdown(); return 0; }编译完成后运行就可以看到对应服务了
C++ 实现一个节点调用服务
创建一个功能包
客户端代码
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 "rclcpp/executors.hpp" #include "demo_interfaces/srv/add_int.hpp" using namespace std::chrono_literals; int main(int argc, char* argv[]) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("add_client"); auto client = node->create_client<demo_interfaces::srv::AddInt>("add_int"); auto request = std::make_shared<demo_interfaces::srv::AddInt_Request>(); request->a = 100; request->b = 200; while (!client->wait_for_service(1s)) { if (!rclcpp::ok()) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting."); return 0; } RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again..."); } auto result = client->async_send_request(request); if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS) { RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sum: %ld", result.get()->sum); } else { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints"); } rclcpp::shutdown(); return 0; }