一 Buzz控制器
Buzz控制器
Buzz繼承實現了Argos中的控制器接口(如第一個案例中的buzz_controller_footbot控制器)。當啓動Argos模擬器時,會自動執行Buzz控制器的初始化方法,該方法主要獲取傳感器數據,讀取bytecode字節碼文件和debug調試文件,並將bytecode字節碼文件交給BVM模塊解析處理。Buzz控制器的ControlStep方法主要用於按步執行(執行頻率可以在.argos文件中配置),分爲四個過程:
1)processInMsg: 從sensors中讀取傳感器數據,更新鄰居節點信息,處理接收到的消息;
2)updateSensors: 更新傳感器數據,如位置、電量;
3)function_call: 調用用戶定義的step方法;
4)processOutMsgs: 通過actuator發送outmsg隊列中的消息,消息格式: robotid | 消息體長度 | 消息內容
二 BVM模塊
Buzz虛擬機主要用於在機器人平臺上執行通過Buzz語言生成的bytecode字節碼文件。BVM模塊會解析bytecode字節碼文件,存儲其中的相關指令和用戶定義的方法,以及內部模塊的一些方法(如neighbors/swarm/vstig/math/strings/obj等)。BVM還提供了方法調用堆棧、全局變量表、局部變量表、輸入輸出消息隊列等。
如上圖,BVM從"Sensor data"讀取接收到的消息,放入到inmsgs消息隊列,並根據消息類型分發給相應的功能模塊(swarm/neighbor/vstig),這些模塊會解析並處理消息,處理消息時會用到BVM中的堆棧、解釋器等,然後將要發送的消息放入到outmsgs消息隊列,通過"Actuator data"發送出去。
三 neighbor模塊
鄰居節點數據存儲:<robotid, [distance, azimuth, elevation]>
數據來源
節點每step都會向鄰居節點廣播一條消息,消息內容爲本節點的robotid,如果有outmsgs隊列中有要發送的數據,則合併發送。
鄰居節點收到該消息後,檢測與消息發送者的distance,並更新上面的數據存儲。
方法
1)listen(偵聽):BVM模塊將用戶定義的回調方法註冊到vm->listeners字段中,當每step中processInMsgsc處理接收到消息時,如果消息類型爲BROADCAST,則從vm->listeners中查詢對應的回調方法,並調用執行。
思考:vm->listeners爲字典結構<key, func>,是不是不能多個同一話題的偵聽?
2)broadcast(廣播):消息類型爲BROADCAST,消息放入到vm->outmsgs隊列中,每step都會將隊列中的消息發送出去。
3)ignore(取消):從vm->listeners回調函數列表中刪除回調函數。
4)map(座標變換):函數作爲參數,該函數用於對鄰居節點的數據進行轉換,並返回新的鄰居節點數據結構。
5)reduce(縮減):函數作爲參數,該函數用於對鄰居節點數據進行左摺疊/累積/縮小操作,函數最後計算出一個值。
四 swarm模塊
數據存儲:
vm->swarms字典:<swarmid, 0/1>,存儲本節點知道的羣列表;
vm->swarmmembers字典:<robotid, [age,swarmed_list]>,存儲本節點所有鄰居節點所屬的羣列表
方法
1)create(創建羣):本節點BVM將swarmid保存到vm->swarms字典中,數據結構爲<swarmid, 0/1>,後者表示本機器人是否屬於該羣。也可以從已有的羣中創建新羣:intersection(交集)/union(並集)/difference(差集)。
2)join(加羣):本節點BVM將vm->swarms字典中的標誌爲1,併發送消息<robotid, swarmid>,消息類型SWARM_JOIN。鄰居節點收到消息後,將節點與羣關係存儲到vm->swarmmembers字典中,數據結構爲<robotid, [age,swarmed_list]>。另外一種加羣方法爲select,不同的是:select 是有條件加羣,join 是無條件加羣。
3)leave(離羣):本節點BVM將vm->swarms字典中的標誌爲0,併發送消息<robotid, swarmid>,消息類型SWARM_LEAVE。鄰居節點收到消息後,更新vm->swarmmembers字典中的節點與羣關係。另外一種離羣方法爲unselect,不同的是:unselect 是有條件離羣,leave 是無條件離羣。
4)in(查詢):若判斷本節點是否屬於某個羣,則從本節點vm->swarms字典中的查詢標誌是否爲1;若判斷鄰居節點是否屬於某個羣,則從本節點的vm->swarmmembers字典中查詢。
5)exec(執行):屬於該羣的所有節點執行某個方法。
思考:如果一個節點屬於多個羣,那麼在exec執行任務時,如何處理?
BVM對羣的自動管理過程(如節點宕機時,如何主動判斷節點離羣?)
1)BVM每步都會調用一次update方法,該方法會檢查vm->swarmmembers字典中的鄰居節點的age是否超過限制(默認50),如果超齡,則從字典中刪除該節點的記錄。
2)BVM每10步發送一次SWARM_LIST消息,消息格式<robotid, swarmid_list>。鄰居節點收到該消息後,更新本節點BVM中的vm->swarmmembers字典,並將發送者的age置爲0。(age表示從上次更新到當前時間的經歷的步數)
五 vstig模塊
主要用於整個羣內的數據共享。
數據存儲 vm->vstigs :<vstigid, <key, [value,timestamp,robotid]>
方法
1)put (寫):當節點向共識寫新的數據時,本地BVM先更新本地共識數據,然後,將<vstigid,key,value,timestamp,robotid>消息放入vm->outmsgs隊列,消息類型爲VSTIG_PUT。鄰居節點收到該消息後,檢查消息的timestamp,如果timestamp比當前存儲的key的時間新,則數據有效並轉發;如果同樣的timestamp但不同的robotid說明出現了衝突,會調用用戶設置的onconglict方法(默認使用robotid大的數據有效),解決衝突後會調用用戶設置的onconflictlost方法。
2)get(讀):當節點從共識讀取數據時,如果本地有該key,則BVM會返回該key對應的數據;然後,BVM將<vstigid,key…>消息放入vm->outmsgs隊列,消息類型爲VSTIG_QUERY。鄰居節點收到該消息後,會查詢自己的共識數據,如果本地的數據較新,則會向發送者回復較新的數據,消息類型爲VSTIG_PUT;如果本地的數據較舊,BVM則會更新該條數據,並廣播給所有鄰居節點。該機制允許機器人斷開重連後自動更新數據。