0 专栏介绍
本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。
🚀详情:《ROS2从入门到精通》
1 服务通信模型
服务是 ROS 图中节点之间的另一种通信方法。服务基于服务器-客户端模型,不同于话题的发布者-订阅者模型。话题允许节点订阅数据流并获取持续更新,而服务只在客户端特别调用时才提供数据。二者更详细的对比请参考第5节
2 服务模型实现(C++)
-
服务器
本实验中无需编程,为
turtlesim::Spawn
定义的/spwan
服务 -
客户端
void OnResultCallBack(rclcpp::Client<turtlesim::srv::Spawn>::SharedFuture result) { auto response = result.get(); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Request service successfully! [turtle id: %s]", response->name.c_str()); } void request() { auto spawn = std::make_shared<turtlesim::srv::Spawn::Request>(); spawn->name = "winter_turtle"; spawn->x = 1.0; spawn->y = 1.0; spawn->theta = 1.57; while (!client_->wait_for_service(std::chrono::seconds(1))) { if (!rclcpp::ok()) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting."); return; } RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again..."); } auto result = client_->async_send_request(spawn, std::bind(&ClientNode::OnResultCallBack, this, std::placeholders::_1)); }
服务通信的效果如下所示:
3 服务模型实现(Python)
-
服务器
本实验中无需编程,为
turtlesim::Spawn
定义的/spwan
服务 -
客户端
class ClientNode(Node): def __init__(self, name): super().__init__(name) self.client = self.create_client(Spawn, '/spawn') while not self.client.wait_for_service(timeout_sec=1.0): self.get_logger().info('service not available, waiting again...') self.request = Spawn.Request() def sendRequest(self): self.request.name = "winter_turtle" self.request.x = 1.0 self.request.y = 1.0 self.request.theta = 1.57 self.future = self.client.call_async(self.request)
服务通信的效果如下所示:
4 自定义服务
自定义服务的通用流程如下:
下面给出一个实例
添加如下自定义服务实现一个加法服务,并按上面步骤配置依赖
# client
int32 a
int32 b
---
# server
int32 sum
定义一个服务器、一个客户端,限于篇幅只贴出部分代码,完整代码见文末。
- 服务器
class ServerNode : public rclcpp::Node { public: ServerNode() : Node("lab_srv_server_own") { server_ = create_service<own_srv_lab::srv::Add>( "/add_service", std::bind(&ServerNode::OnAddSrvCallBack, this, std::placeholders::_1, std::placeholders::_2) ); } private: rclcpp::Service<own_srv_lab::srv::Add>::SharedPtr server_; void OnAddSrvCallBack( const std::shared_ptr<own_srv_lab::srv::Add::Request> request, std::shared_ptr<own_srv_lab::srv::Add::Response> response ) { response->sum = request->a + request->b; RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %d" " b: %d", request->a, request->b); RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%d]", response->sum); } };
- 客户端
ClientNode() : Node("lab_srv_client_own") { client_ = create_client<own_srv_lab::srv::Add>("/add_service"); } void request(int a, int b) { auto add_srv = std::make_shared<own_srv_lab::srv::Add::Request>(); add_srv->a = a; add_srv->b = b; while (!client_->wait_for_service(std::chrono::seconds(1))) { if (!rclcpp::ok()) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting."); return; } RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again..."); } auto result = client_->async_send_request(add_srv, std::bind(&ClientNode::OnResultCallBack, this, std::placeholders::_1)); }
服务通信效果如下所示:
5 话题、服务通信的异同
🔥 更多精彩专栏: