不知道為什么會把這么嚴肅認真的一篇技術整理貼起這么一個故事會風格類似的名字,就這樣吧:^)shenmegui
園子里有人整理了actionlib的初學者教程,我來整理下actionlib的細節描述吧。初版偏向於逐字翻譯+少量個人理解。等我再長大一些感悟更多的時候再修改更新我的更多理解。我boss說開始學ROS相關就是會很亂的。我是一個喜歡划分割線的奇女子~\(≧▽≦)/~
一、服務端描述
1)goal是在ActionClient端啟動的(client會發送sendgoal嘛),一旦ActionServer接收到goal請求,它就會為這個goal創建一個狀態機來追蹤goal的狀態轉換,重復三遍,狀態機是跟蹤goal的不是跟蹤ActionServer的:
zou是這個狀態轉換圖,下面來細說這些個狀態:
2)服務端狀態
- 這些狀態的轉換大多是服務的實施者觸發的(這么生硬的翻譯,其實就是服務的程序下同),用小一串命令:
-
setAccepted - 檢查到有goal之后,決定開始處理它
-
setRejected - 檢察到goal后,決定不去處理它,因為它是個無效請求(溢出,資源不可用,無效等)
-
setSucceeded - 告知goal被正確執行
-
setAborted - 告知goal在處理時遇到了問題不得不被終止了
-
setCanceled - 告知因cancle請求,goal不再被執行了
-
CancelRequest: 客戶端通知action server它想要server停止處理這個goal服務端狀態
-
服務端狀態
中間狀態
(前面說了,simple的狀態有三個,就是等待執行掛起)
-
Pending - goal還沒有被ActionServer處理
-
Active - goal正在被AS處理
-
Recalling - goal沒有被處理並且從客戶端已發送取消它的命令,但AS還不確定goal已經被取消了(時差導致的?)
-
Preempting - goal正被處理呢,從AC端收到了取消請求,但AS還不確定goal已經被取消了
終點狀態
-
Rejected - AC沒有發cancle請求,goal被AS不處理直接拒絕了The goal was rejected by the action server without being processed and without a request from the action client to cancel
-
Succeeded - goal被AS成功實現 was achieved successfully by the action server
-
Aborted - goal被AS終止沒有AC的cancle請求
-
Recalled - 在AS開始執行之前這個goal被另一個goal或者cancle請求取消了
-
Preempted - 處理中的goal被另一個goal或者AC的取消請求給取消了
並發問題
setAccepted-CancelRequest vs CancelRequest-setAccepted:
直接的說就是AS能在收到CR之后仍然能把goal給SA。這是因為執行CR的異步競爭機制,那是,因為除了server之外的其他代碼觸發了狀態轉換,server不能確定現在到底是在[PENDING]還是 [RECALLING]狀態。
二、客戶端描述
1)客戶端狀態機
actionlib中,認為server的狀態機是主機,client的狀態機是從機/耦合機,它在追隨主機的狀態。
2)客戶端轉換
服務端觸發轉換
-
Reported [State]: 因為client在追隨主機狀態,很多狀態的轉換都是通知自己狀態轉換后觸發client的狀態轉換
-
Receive Result Message: 這種狀態,server給client發送result message。接收到result就意味着追蹤這個goal 結束了
客戶端觸發轉換
-
Cancel Goal: 請求server停止處理這個goal
"略過" 狀態
- 鑒於ROS是基於傳輸層協議,非常有可能client並不能收到所有server狀態的更新。因此,我們允許客戶端狀態機“略過”server的觸發狀態
-
Example: 客戶端在 [WAITING FOR GOAL ACK]狀態, 收到 [PREEMPTED]server的更新狀態, 客戶端狀態可以跳過 [ACTIVE]狀態,直接轉移到 [WAITING FOR RESULT]狀態
-
-
因為多AC可以連接單一AS,因此允許一個client取消另一個client的goal。因此當收到server的[RECALLING]狀態時允許client從 [PENDING] 轉移到 [RECALLING]狀態
三、Action接口和傳輸協議
Action客戶端和服務端通過預定義的action協議交流。這個action協議依賴ROS topics在一個ROS規定的命名空間中傳遞消息
- ROS Messages
-
goal - 用於給目標發送新的服務
-
cancel - 用來給服務發送取消命令
-
status - 用來通知當前狀態下系統中所有goal的狀態
-
feedback - 用來給客戶端定期定期發送輔助信息
- result - 用來在goal完成后給發送客戶端一次信息
-
1)數據組合和goal ID
goal ID是字符串類型字段
------明天寫*^_^*
四、協議
1)Simple Action Client
一般,高層的應用和可執行文件並不關心goal是否被處理或是否完整。他們才不關心中間狀態呢。Simple Action Client的原始客戶端狀態機只有三個狀態:Pending, Active, & Done
1.1)客戶端狀態模糊
單獨客戶端狀態是不夠確定SimpleClient狀態的,但這很容易通過觀察客戶端狀態轉移來解決.如果客戶端狀態轉移並未使SC狀態轉移.SC狀態就不更新.
栗子:如果客戶端從RECALLING轉移到WAITING FOR RESULT,SC的狀態仍然在PENDING.
1.2)多goal協議
Simple Action Client一次只追蹤一個goal。當用戶使用simple client發送一個goal時, 它會取消前一個goal的所有回調並使停止追蹤它的狀態,注意它並不是取消前一個goal!
1.3)線程模式(C++)
基於簡單的action客戶端結構,用戶決定是否要自旋另一個線程
-
不要額外線程 (推薦)
- 客戶端所有用戶都注冊到全局回調隊列
- 用戶的action回調是從ros::spin中回調的,因此,阻斷用戶的動作回調會組織全局回調隊列被服務端處理
-
自旋一個線程
- action client的所有訂閱者都會注冊到一個回調隊列。這個隊列與全局回調隊列分離,這個隊列服務於自旋線程
- 用戶的action回調隊列被稱為spun up線程,雖然堵在action回調不會阻止其他ROS消息被服務,但仍不推薦這樣用,因為這個action的status feedback和反饋都不能被服務
-
一個(可能是唯一一個)自旋一個額外線程的有點是用戶可以不用在app中調用ros::spin()
2)Simple Action Server
很多action server遵循同樣的模式,就是在同一時間只能有一個標簽是活躍的,並且新的goal可以搶占先前的goal。設計action server包裝的simple action server是為了強制這個簡單協議去處理goal
當從action client接收到一個新goal時,simple action server將這個goal移到等待槽。如果這個goal已經占據了等待槽,sipmle action server 將這個目標設置為cancle,並用線上到來的其他目標取代它。
好沒有動力繼續寫啊。。。。。。%>_<%