寫在前面:
這是這個系列的第一篇
本系列主要從零開始深入探索ROS(機器人作業系統)的導航和規劃。
這個系列的目標,是讓大家瞭解:
1.ROS的導航是怎麼實現的
2.認識ROS裡各種已有的導航演算法,清楚的瞭解到每一個引數的作用,以及ROS的原始碼是怎麼設計的
3.和大家一起看看學術界和工業界在導航領域的相關發展。學會如何重寫ROS的原始碼,使用ROS的介面來實現一些導航演算法/論文
本篇目標:
1.瞭解什麼是導航(主要是室內導航)
2.遊戲世界中的導航是怎麼樣的
3.遊戲世界的導航在真實世界會遇到哪些問題
一、ROS導航
本篇作為系列的第一章,我希望大家能夠輕鬆的瞭解導航這個複雜而又簡單的系統。
本篇目標:大概明白ROS中的導航結構
1.1 什麼是ROS:
ROS是Robot Operating System(機器作業系統)的縮寫,但它並不是真正意義上的作業系統
它更像是跑在Linux系統上的一個專門給開發者提供的機器人演算法、工具的合集。
引用官方的描述:
The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications
ROS的特點有:開源, 便捷,支援多語言(主要為python和C++)
ROS在機器人行業的名聲特別大,因為它大大的簡化了機器人的開發流程和降低了機器人開發門檻。在我看來在ROS在機器人行業影響力就像在8年前安卓系統在手機行業的一樣,它不夠完善但潛力極強,因為其免費開源的性質最終將會被各大小廠商採用
這篇文章基於ROS - noetic版本,(在工作中,我使用的是melodic版本,其實這些臨近版本都大同小異,大多數程式碼和框架也是通用的)
如果大家對ROS還不太瞭解也沒關係,不會影響閱讀本篇文章
這裡有一些我收藏的瞭解ROS的途徑:
1.ROS wiki(官網):cn/ROS - ROS Wiki
2.B站搜尋ROS檢視學習視訊
1.2 什麼是導航
本系列主要聚焦於室內導航
我認為跟機器人學科接近的,是遊戲
大多數遊戲開發中需要使用導航,規劃,AI行為等,都與機器人學科高度相近。本系列中我們只聚焦於導航領域:
導航是遊戲引擎都會提供的重要元件(下面是unity和UE引擎提供的導航功能):
相信各位玩家,對以下這些場景可能不會陌生,這是遊戲中,開發者直觀地把導航路徑展示給玩家看:
簡單來說,導航是提供一個可達路線從一個位置到另一個位置的系統。下面我們會嘗試對這個系統進行解讀
二、遊戲中的導航
在本節中,一些關鍵術語會使用英文標記,希望給大家一個印象。因為它們對我們後續篇章進行原始碼分析和論文閱讀十分有幫助
2.1 我們來推測一下英雄聯盟的導航是怎麼做的:
如果你沒玩過英雄聯盟,那麼可以跳過這一節了,我肯定你是學霸。因為你沒時間玩遊戲
如果你玩過英雄聯盟,那你更厲害一定是學神,因為你除了逛部落格園和上班/上學,竟然還有時間玩遊戲
首先我們要:
1.開啟英雄聯盟,開始訓練模式,選取蒸汽機器人布里茨(或者其他英雄)進入遊戲
2.遊戲載入完成後,滑鼠右鍵點選小龍坑進行移動,此時留意右下角小地圖
這時候,小地圖上出現了一條白線(我們稱為路徑path),白線左端連線著機器人(稱為起點start),白線右端是我們滑鼠點選的位置小龍坑(稱為目標點goal)
-
- 隨著機器人的移動,白線(路徑)在變短,但是目標點小龍坑始終不變。
- 白線(路徑)在整個移動過程會有一定程度的改變,但始終會避開防禦塔,牆體,深林,山體等阻擋前進的東西(下面把這些東西統稱為障礙物obstacle)
2.2 我們大膽推測一下游戲的底層邏輯
如上圖我們把遊戲地圖看作一個二維座標系,橫向是x軸,縱向是y軸,地圖左下角是座標(0,0) 地圖右上角是座標(100,100)
- 玩家點選右鍵,遊戲的某一段程式碼受到激發(發生了callback),通知導航模組(navigation)的程式碼開始工作
- 遊戲的某一段程式碼捕獲到滑鼠指標在顯示器上的位置,作為目標點goal(80,30)
- 遊戲的某一段程式碼獲取到了當前機器人的位置作為起點start(1,1)
- 遊戲的某一段程式碼獲取到了地形圖(map),這個地形圖上分為會阻擋前進的障礙物(obstacle),還有暢通無阻的路面/河道(free space)
- 導航模組結合上面獲取的資訊,內部的規劃子模組(planner)通過某種演算法給規劃(plan)了一條能避開障礙物的白色路徑(path)並顯示在小地圖上
- (不重要)機器人根據自身的移動速度(velocity)延著這個路徑path開始移動,並伴隨著移動播放走路的動畫(機器人狀態機從停止切換到運動狀態)
- (不重要)在一定的條件下,比如靠近目標後,或者每隔一段時間,程式回到3開始再次執行,直到機器人當前座標(current location)和goal座標重合為止。每次重新跑到3,起點位置改變了,白線路徑就會變短,(由於演算法的原因新的白線與之前白線可能也會發生不同程度的偏差)
所以LOL裡邊導航模組大概是這樣子的:
(我們只需要關注有顏色的部分:藍色是導航模組需要的輸入資訊,綠色是導航模組輸出的路徑,紅色是導航模組本體)
好了,上面大概推導了一下英雄聯盟中的導航邏輯,從導航模組的最終目標是給出一個可行路徑(LOL小地圖裡的白色線),這個路徑能夠引導機器人避開障礙並向終點移動。
問題1:如下圖所示在,綠色,粉色,白色3個路徑中,為什麼導航系統給出的是白色的路徑而不是另外兩個?
回答:這個就是規劃模組要做的事情的了,通常來說,這個路徑會是起點start到終點goal的'最短'路徑
遊戲中比較常用的規劃方法是一系列基於網格(grid-based)的規劃方法,這些演算法從早期的djstra,A*等發展到現在擁有非常多的變體,它們都經歷了什麼,以及具體是怎麼實現的,我準備放到下一篇再和大家分享
(ps,以上對於英雄聯盟導航是依據我在機器人領域開發的經驗進行的推測,目的是更好引出後面ROS中的導航框架,實際遊戲設計中因為架構,網路,效率,bug修復等原因導航可能是一個非常複雜的模組)
2.2 遊戲導航在真實世界中遇到的問題
如果系統要給真實世界中機器人導航,會遇到哪些問題呢?
上面的遊戲導航框架其實已經和ROS中的導航十分接近了,甚至於在理想情況下直接把上面的導航模組搬到ROS上都能開始指導真實世界的機器人運動了
但是遊戲與我們的真實世界仍然存在一定的差異。這些差異包括但不限於:
2.21.動力學約束:在真實世界中,機器人受到了各種力的影響和限制,比如機器人的動力,重力,電機的阻力,輪子的摩擦力,慣性等等,一般我們會用線速度 角速度 線加速度,角加速度等來描述這些問題,
打個比方:
比如下圖1中在遊戲中為了迷惑對手而瘋狂點地板操作,機器人在真實世界不能執行如此高速度的轉頭(用數學來描述:遊戲中的機器人的角速度和角加速度趨近於無限大)
這個特性會導致某些(下圖2)在遊戲中輕鬆通過的急轉彎,在真實世界中,機器人受到了角速度和角加速度的限制無法完成這樣的操作
*真實世界的機器人好比在遊戲中使用亡靈勇士塞恩,塞恩開車的時候由於車速太快無法提供足夠角速度來進行轉彎(下圖3),這時的賽恩就受到了約束,(細心的玩家可能會注意到,塞恩開車的時候,小地圖是不會有白色導航路徑的)
2.22感測器的誤差和干擾:真實世界中,機器人通過一些射線感測器(比如鐳射雷達,超聲波,TOF相機等)來建立地圖(mapping)和獲取自己在地圖中的位置(localization), 通過慣性器件(比如陀螺儀和加速度計)來獲來獲取自身的方向角和傾斜度(orientation),通過碼盤,霍爾盤獲取輪子速度等等。不同精度的感測器能達到上萬倍的價格差異。但精度再高,干擾和誤差都無法完全消除。
比較常見的感測器問題有如下這些(展開檢視)
陀螺儀的零點偏移
相機畫面的畸變
鐳射雷達的白噪聲與延遲
超聲波的盲區以及非線性的發射角
所有光學感測器都會或多或少的受到光線影響
所有聲學感測器都會或多或少的受到聲音影響
這些小小誤差造成了真實世界和遊戲世界的巨大差異,每一種感測器都無法得到精確資訊。有經驗的工程師會在設計階段給機器人上配置不同的感測器來取長補短。在軟體上更是需要做感測器融合,這些融合大多很複雜,消耗大量算力的同時不一定能得到很好的效果。
2.23系統時延:真實世界中,機器人上具有算力的處理器遠遠不止一個CPU,通常還有大量的微控制器,它們負責收集和處理感測器資料,控制機器人機械運動等。不同晶片間的資訊交換,以及不同軟體系統的任務切換,都會導致接收資料的時機變得更加不穩定(加強了2.22的問題),控制輪子運動也得不到不及時執行,而且這些時延並不是固定有時也難以補償,會導致機器人無法完全按照白色路徑前進。這個感覺,類似於玩lol的時候有經常性發生網路卡頓和延遲,當網路反應過來的時候可能機器人已經走遠了。
現在我們看看ROS如何從程式碼設計上改善上面的問題:
三、ROS的導航是怎麼設計來解決這些問題的
3.1 ROS的導航框架
針對上面的問題2.21
相信大家都想到了解決方法,如果我們讓機器人走得很慢很慢,那麼再急的彎機器人不就能轉過來了嗎?但我們應該怎麼讓機器人在該快的時候快,該慢的時候慢呢?我們看看ROS怎麼在架構上做了什麼改動:
- 把上面的規劃器planner改名為全域性規劃器(global planner),其產生白色路徑我們稱為全域性路徑(global path)
- 由於現實中的機器人受到動力學約束,ROS增加了一個區域性規劃模組(local planner)來動態控制機器人,這個區域性規劃器拿到前面產生的全域性路徑,並根據動力學約束,讓機器人能夠提前進行加減速,來貼合路徑。
- *注:不同的區域性規劃演算法用不同的方法來讓機器人來貼合全域性路徑,甚至修改全域性路徑,但作為區域性規劃模組,它們的輸出必須是線速度和角速度
針對上面的問題2.22:
由於機器人上會放置的感測器太過於多樣化,ROS使用了代價地圖(costmap)這個概念,costmap可以把各種感測器資訊疊加再一起。
costmap的基本功能,是把經過簡單處理的多種感測器的資料,通過配置的方式,一個一個疊加到地圖中。
具體一點,costmap使用了子圖層(layer)的概念。使用過photoshop軟體或者做過視覺的同學就可能對圖層這個概念比較熟悉了:
- costmap能把地圖(map)的資訊複製下來,存放再某個圖層中
- 通過yaml配置檔案能新增更多圖層,只需要做簡單的修改,就能新增/刪除某個圖層
- ROS提供了不同的圖層來處理不同種類的感測器資料,如果你嫌這些圖層不夠豐富,甚至可以根據layer的介面編寫自己的圖層,使用更多的方法來融合多種感測器資料
- 所有圖層根據一定的規則進行疊加(疊加規則也可以配置),併產生一個主圖層(master layer),這個圖層上面的資訊,取代上圖中的地圖(map),給global planner和local planner使用
現在我們更新一下加入代價地圖以後的示意圖:
注意我們不再直接從地圖獲取地形資料了,而是從代價地圖獲取:
區域性規劃演算法自然也需要地圖資訊,大多數時候,是為了避開動態的障礙物(比如人),ROS也給區域性規劃器單獨配置了代價地圖。
現在我們已經大概瞭解ROS導航的構成了(還有一個恢復行為模組 recovery_behavior我們以後再做介紹),我們也瞭解了為什麼這樣子設計。(圖中紅色區域是ROS的導航模組,黃色的模組是必須的,紫色的模組是自行新增或刪除)
ROS也設計好了介面類,方便後各位大神對這些模組進行改寫。
*ROS導航框架中還有一個恢復策略模組(recovery behaivors),它能給使用者自定義一些遇到意外的自動恢復共嗯。非必須,這裡暫時進行省略。
3.2 ROS導航模擬配置
- ROS使用gazebo元件能給我們機器人在現實世界的模擬,我們會使用到gazebo元件來進行真實世界機器人模擬
- 我們還需要使用視覺化軟體(類似lol中的小地圖),rviz元件來進行場景的視覺化
- 我們還需要使用到AMCL模組進行導航的輔助定位
我們的主角機器人他有點殘疾,雙腳被替換成了輪子
在機器人動力分類上,他是一個二輪差動機器人(diff-drive)。沒有腳,用兩個輪子進行運動
*差動機器人的特點是兩個輪子可以單獨執行不同速度的運動。
- 如果兩個輪子速度相同且大於0,那麼機器人前進
- 如果其中一個輪子的速度比另一個輪子大,那麼機器人轉彎
- 如果兩個輪子速度相同但是方向相反,那麼機器人自轉
關於整個ROS工程,費了一點時間東拼西湊把機器人的基本框架搭起來了。
*要執行這個程式碼,是需要已經安裝好了ROS-noetic版本。由於ROS系統安裝過程本身比較繁瑣,在這短短的篇幅就不做介紹了。
我的git倉庫連結:https://github.com/DennLiang/ROS_navigation_denn.git
下載後需要把倉庫放在工作空間的src路徑下,如圖:
·關於地圖,我花了一點時間復刻了LOL的地圖, 總所周知,LOL是一個只有下路的遊戲,所以這裡也只復刻了下路野區部分:
相信我不說大家也能看出來,綠色是下路,黃色是城牆下方的小門,紅色區域是下路紅buff區,藍色區域是小龍坑。簡直和原圖一摸一樣。
·關於導航模組,這裡使用我認為比較合理的配置方式,如果是各位已經熟悉ros的大佬,可能會覺得跟官網還有其地方看到的配置不太一樣。這樣的做法看起來麻煩,但更靈活。跟我們上面說的導航框架一一對應。全域性規劃這裡使用A*演算法,區域性規劃使用了DWA演算法,這兩個演算法ROS都已經提供並且開放了原始碼。如果想深入瞭解它們的詳細內容,大家記得留意後續篇章的更新哦
·關於ROS原始碼:為了方便大家檢視和後續篇章的講解,我也把ROS的導航包navigation原始碼 和 tf座標變換原始碼 下載到工程中了:
四、大功告成,開始導航!
在工作空間中,使用catkin_make進行編譯:
新建終端1:
- 配置全域性變數: source ./devel/setup.bash
- 執行機器人模擬(機器人描述檔案):roslaunch urdf_gazebo_02 demo02_car.launch
新建終端2:
- 配置全域性變數: source ./devel/setup.bash
- 執行機器人導航(包括了定位AMCL 和 Move base兩部分):roslaunch nav_dev nav08_amcl_with_navigation.launch
點選開啟的rviz視窗中的2D Nav Goal按鈕來控制機器人:
還記得在第二節中機器人在基地向小龍坑移動的動圖嗎:
我們在真實世界中復刻一下機器人從基地走到龍坑的過程(見動圖):
機器人附近的彩色區域是區域性地圖(local costmap)的範圍,可以簡單的理解為戰爭迷霧(遊戲中英雄只看到自己附近的敵人,在黑影中的敵人看不到)
大家可以通過對比觀察到真實世界中和遊戲中的機器人運動的差異,
- 比如由於受到鐳射雷達的白噪聲影響,AMCL定位精度的影響,機器人附近地圖的牆壁會發生不同程度的抖動
- 比如由於DWA演算法的關係,機器人在某些狹窄的路口提前進行了減速。
好了,本篇到這裡結束了,下一篇中我們會通過閱讀論文和原始碼,一起來看看全域性規劃演算法在學術界上和工程領域都得到了一些怎麼樣的發展,也期待各位讀者繼續關注更新哦
今天是2022年第2天,祝大家在新年許的願望全部實現,拜拜了