您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何實現基于ROS服務通信模式”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“如何實現基于ROS服務通信模式”這篇文章吧。
ROS 服務通信模式
服務(services)是節點之間通訊的另一種方式。服務允許節點發送請求(request) 并獲得一個響應(response)
AddTwoInts.h文件是根據AddTwoInts.srv文件生成的
還會自動生成
AddTwoIntsRequest.h
AddTwoIntsResponse.h
AddTwoInts.h所在的目錄是
\catkin_ws\devel
AddTwoInts.srv
int64 a int64 b --- int64 sum
server.cpp
/** * AddTwoInts Server */ #include "ros/ros.h" #include "learning_communication/AddTwoInts.h" // service回調函數,輸入參數req,輸出參數res bool add(learning_communication::AddTwoInts::Request &req, learning_communication::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節點初始化 ros::init(argc, argv, "add_two_ints_server"); // 創建節點句柄 ros::NodeHandle n; // 創建一個名為add_two_ints的server,注冊回調函數add() ros::ServiceServer service = n.advertiseService("add_two_ints", add); // 循環等待回調函數 ROS_INFO("Ready to add two ints."); ros::spin(); return 0; }
client.cpp
/** * AddTwoInts Client */ #include <cstdlib> #include "ros/ros.h" #include "learning_communication/AddTwoInts.h" int main(int argc, char **argv) { // ROS節點初始化 ros::init(argc, argv, "add_two_ints_client"); // 從終端命令行獲取兩個加數 if (argc != 3) { ROS_INFO("usage: add_two_ints_client X Y"); return 1; } // 創建節點句柄 ros::NodeHandle n; // 創建一個client,請求add_two_int service // service消息類型是learning_communication::AddTwoInts ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts>("add_two_ints"); // 創建learning_communication::AddTwoInts類型的service消息 learning_communication::AddTwoInts srv; srv.request.a = atoll(argv[1]); srv.request.b = atoll(argv[2]); // 發布service請求,等待加法運算的應答結果 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
add_executable(server src/server.cpp) target_link_libraries(server ${catkin_LIBRARIES}) add_dependencies(server ${PROJECT_NAME}_gencpp) add_executable(client src/client.cpp) target_link_libraries(client ${catkin_LIBRARIES}) add_dependencies(client ${PROJECT_NAME}_gencpp)
package.xml
<?xml version="1.0"?> <package> <name>learning_communication</name> <version>0.0.0</version> <description>The learning_communication package</description> <maintainer email="hcx@todo.todo">hcx</maintainer> <license>TODO</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>geometry_msgs</build_depend> <build_depend>roscpp</build_depend> <build_depend>rospy</build_depend> <build_depend>std_msgs</build_depend> <run_depend>geometry_msgs</run_depend> <run_depend>roscpp</run_depend> <run_depend>rospy</run_depend> <run_depend>std_msgs</run_depend> <build_depend>message_generation</build_depend> <run_depend>message_runtime</run_depend> <!-- The export tag contains other, unspecified, tags --> <export> <!-- Other tools can request additional information be placed here --> </export> </package>
文件夾的主要功能
1)config:放置功能包中的配置文件,由用戶創建,文件名可以不同。 2)include:放置功能包中需要用到的頭文件。 3)scripts:放置可以直接運行的Python腳本。 4)src:放置需要編譯的C++代碼。 5)launch:放置功能包中的所有啟動文件。 6)msg:放置功能包自定義的消息類型。 7)srv:放置功能包自定義的服務類型。 8)action:放置功能包自定義的動作指令。 9)CMakeLists.txt:編譯器編譯功能包的規則。
如何自定義服務數據
與話題消息類似,ROS中的服務數據可以通過srv文件進行語言無關的接口定義,一般放置在功能包根目錄下的srv文件夾中。該文件包含請求與應答兩個數據域,數據域中的內容與話題消息的數據類型相同,只是在請求與應答的描述之間,需要使用“—”三個橫線進行分割。
針對加法運算例程中的服務需求,創建一個定義服務數據類型的srv文件learning_communication/srv/AddTwoInts.sint64 a
int64 b
int64 sumv文件的內容較為簡單,在服務請求的數據域中定義了兩個int64類型的變量a和b,用來存儲兩個加數; 又在服務應答的數據域中定義了一個int64類型的變量sum,用來存儲“a+b”的結果。
完成服務數據類型的描述后,與話題消息一樣,還需要在功能包的package.xml和CMakeLists.txt文件中配置依賴與編譯規則,在編譯過程中將該描述文件轉換成編程語言所能識別的代碼。
打開package.xml文件,添加以下依賴配置
message_generation message_runtime
打開CMakeLists.txt文件,添加如下配置
find_package(catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs message_generation ) add_service_files( FILES AddTwoInts.srv )
message_generation包不僅可以針對話題消息產生相應的代碼,還可以根據服務消息的類型描述文件產生相關的代碼。 功能包編譯成功后,在服務的Server節點和Client節點的代碼實現中就可以直接調用這些定義好的服務消息了。 接下來我們就編寫Server和Client節點的代碼,完成兩數相加求和的服務過程。
代碼解釋
Server節點實現過程
1. 頭文件
#include "learning-communication/AddTwoInts.h"
使用ROS中的服務,必須包含服務數據類型的頭文件,這里使用的頭文件是learning_communication/AddTwoInts.h,該頭文件根據我們之前創建的服務數據類型的描述文件AddTwoInts.srv自動生成。
2.主函ros::ServiceServer service = n.advertiseService(“add_two_ints”, add);部分相對簡單,先初始化節點,創建節點句柄,重點是要創建一個服務的Server,指定服務的名稱以及接收到服務數據后的回調函數。然后開始 循環等待服務請求;一旦有服務請求,Server就跳入回調函數進行處理。
3.回調函數部分
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
回調函數是真正實現服務功能的部分,也是設計的重點。add()函數用于完成兩個變量相加的功能,其傳入參數便是我們在服務數據類型描述文件中聲明的請求與應答的數據結構。
{ 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); ROS_INFO("sending back response: [%ld]", (long int)res.sum); return true; }
在完成加法運算后,求和結果會放到應答數據中,反饋到Client,回調函數返回true。
服務中的Server實現流程如下:
·初始化ROS節點。
·創建Server實例。
·循環等待服務請求,進入回調函數。
·在回調函數中完成服務功能的處理并反饋應答數據。
Client節點的實現過程。
1.創建Client
ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts> ("add_two_ints");
首先需要創建一個add_two_ints的Client實例,指定服務類型為learning_communication:AddTwoInts。
2.發布服務請求
learning_communication::AddTwoInts srv; srv.request.a = atoll(argv[1]); srv.request.b = atoll(argv[2]);
然后實例化一個服務數據類型的變量,該變量包含兩個成員:request和response。將節點運行時輸入的兩個參數作為需要相加的兩個整型數存儲到變量中。
if (client.call(srv))
接著進行服務調用。該調用過程會發生阻塞,調用成功后返回true,訪問srv.reponse即可獲取服務請求的結果。如果調用失敗會返回false,srv.reponse則不可使用。
服務中的Client實現流程如下:
·初始化ROS節點。
·創建一個Client實例。
·發布服務請求數據。
·等待Server處理之后的應答結果。
編譯功能包
編輯CMakeLists.txt文件,加入如下編譯規則:
add_executable(server src/server.cpp) target_link_libraries(server ${catkin_LIBRARIES}) add_dependencies(server ${PROJECT_NAME}_gencpp) add_executable(client src/client.cpp) target_link_libraries(client ${catkin_LIBRARIES}) add_dependencies(client ${PROJECT_NAME}_gencpp)
現在就可以使用catkin_make命令編譯功能包了。
運行Server和Client
運行編譯生成的Server和Client節點。
1.啟動roscore
在運行節點之前,首先需要確保ROS Master已經成功啟動:
roscore2.運行Server節點打開終端,使用如下命令運行Server節點:roscore
2.運行Server節點打開終端,使用如下命令運行
Server節點: rosrun learning_communication server
3.運行Client節點
打開一個新的終端,運行Client節點,同時需要輸入加法運算的兩個加數值:
$ rosrun learning_communication client 3 5
Client啟動后發布服務請求,并成功接收到反饋結果
Server接收到服務調用后完成加法求解,并將結果反饋給Client
wiki
rosservice list 輸出可用服務的信息 rosservice call 調用帶參數的服務 rosservice type 輸出服務類型 rosservice find 依據類型尋找服務find services by service type rosservice uri 輸出服務的ROSRPC uri
以上是“如何實現基于ROS服務通信模式”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。