文章目錄
- 1.服務通信的概念及應用場景
- 1.1概念
- 1.2 應用場景
- 2.準備工作
- 3.服務通信的實現
- 3.1 服務通信接口消息
- 3.2 服務端實現
- 3.3 客戶端實現
- 3.4 編譯及運行
- 3.4.1 修改CMakeLists
- 3.4.2 服務端運行結果
- 3.4.2 客戶端運行結果
1.服務通信的概念及應用場景
1.1概念
服務通信也是ROS中一種極其常用的通信模式,服務通信是基于請求響應模式的,是一種應答機制。也即:一個節點A向另一個節點B發送請求,B接收處理請求并產生響應結果返回給A。
服務端只能有一個,客戶端可以有多個:
1.2 應用場景
機器人巡邏過程中,控制系統分析傳感器數據發現可疑物體或人… 此時需要拍攝照片并留存。
也就是數據分析節點A需要向相機相關節點B發送圖片存儲請求,節點B處理請求,并返回處理結果。
2.準備工作
3.服務通信的實現
3.1 服務通信接口消息
定義服務接口消息與定義話題接口消息流程類似,主要步驟如下:
①創建并編輯 .srv文件;
②編輯配置文件;
③編譯;
④測試。
3.2 服務端實現
// 1.包含頭文件
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces_demo/srv/add_ints.hpp"
using base_interfaces_demo::srv::AddInts;
using std::placeholders::_1;
using std::placeholders::_2;// 3.定義節點類;
class MinimalService: public rclcpp::Node{ public: MinimalService():Node("minimal_service"){ // 3-1.創建服務端; server = this->create_service<AddInts>("add_ints", std::bind(&MinimalService::add, this, _1, _2));RCLCPP_INFO(this->get_logger(),"add_ints 服務端啟動完畢,等待請求提交..."); } private: rclcpp::Service<AddInts>::SharedPtr server; // 3-2.處理請求數據并響應結果。 void add(const AddInts::Request::SharedPtr req, const AddInts::Response::SharedPtr res){ res->sum = req->num1 + req->num2; RCLCPP_INFO(this->get_logger(),"請求數據:(%d,%d),響應結果:%d", req->num1, req->num2, res->sum); }
};int main(int argc, char const *argv[])
{ // 2.初始化 ROS2 客戶端; rclcpp::init(argc,argv); // 4.調用spin函數,并傳入節點對象指針; auto server = std::make_shared<MinimalService>(); rclcpp::spin(server); // 5.釋放資源。 rclcpp::shutdown(); return 0;
}
代碼分析:
3.3 客戶端實現
// 1.包含頭文件;
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces_demo/srv/add_ints.hpp"
using base_interfaces_demo::srv::AddInts;using namespace std::chrono_literals;
// 3.定義節點類;
class MinimalClient: public rclcpp::Node{
public:
MinimalClient():Node("minimal_client"){
// 3-1.創建客戶端;
client = this->create_client<AddInts>("add_ints");
RCLCPP_INFO(this->get_logger(),"客戶端創建, 等待連接服務端! ");
}
// 3-2.等待服務連接;
bool connect_server(){
while (!client->wait_for_service(1s))
{
if (!rclcpp::ok())
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"強制退出! ");
return false;
}
RCLCPP_INFO(this->get_logger(),"服務連接中, 請稍候...");
}
return true;
}
// 3-3.組織請求數據并發送;
rclcpp::Client<AddInts>::FutureAndRequestId send_request(int32_t num1, int32_t num2){
auto request = std::make_shared<AddInts::Request>();
request->num1 = num1;
request->num2 = num2;
return client->async_send_request(request);
}
private:
rclcpp::Client<AddInts>::SharedPtr client;
};
int main(int argc, char ** argv){
if (argc != 3){
RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"請提交兩個整型數據! ");
return 1;
}
// 2.初始化 ROS2 客戶端;
rclcpp::init(argc,argv);
// 4.創建對象指針并調用其功能;
auto client = std::make_shared<MinimalClient>();
bool flag = client->connect_server();
if (!flag)
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"服務連接失敗! ");
return 0;
}
auto response = client->send_request(atoi(argv[1]),atoi(argv[2]));
// 處理響應
if (rclcpp::spin_until_future_complete(client,response) ==
rclcpp::FutureReturnCode::SUCCESS)
{
RCLCPP_INFO(client->get_logger(),"請求正常處理");
RCLCPP_INFO(client->get_logger(),"響應結果:%d!", response.get()->sum);
}
else {
RCLCPP_INFO(client->get_logger(),"請求異常");
}
// 5.釋放資源。
rclcpp::shutdown();
return 0;
}
代碼分析:
3.4 編譯及運行
3.4.1 修改CMakeLists
別忘了修改CMakeLists文件
3.4.2 服務端運行結果
3.4.2 客戶端運行結果
提示:這里對文章進行總結: