建圖是定位的反面
上一篇我們問的是:給定一張地圖,我在哪裡?這就是定位。現在我們把問題反過來。假設你已經知道自己的位姿——也就是每一刻的精確位置和朝向。那麼,從感測器看到的東西裡,你能瞭解到關於這個世界的什麼呢?這個反過來的問題,就是機器人建圖,它正是定位的鏡像:定位是用已知的地圖找出位姿,建圖則是用已知的位姿來建構地圖。
想像一台機器人帶著旋轉雷射掃描儀在走廊裡行進。每次掃描都告訴它:這個方向最近的牆在 3.2 公尺外,那個方向的牆在 1.8 公尺外。只要機器人知道自己站在哪裡、朝著哪個方向,每一個讀數就都指向房間裡一個真實的位置。建圖的全部任務,就是把數以百萬計這樣被指向的位置收集起來,整理成機器人之後真正能用得上的東西。
把世界切成格子
儲存地圖最常用的方式,就是佔據柵格地圖。它的思路妙在簡單:在地面上鋪一張棋盤,把世界切成一個個小方格——邊長常常是 5 公分或 10 公分。每個格子只存一個數:那裡有實體物體的機率。接近 1 表示「幾乎肯定被佔據」,接近 0 表示「幾乎肯定是空的」,而 0.5 左右則表示「我真的拿不準」。
空閒、佔據、未知這三種狀態,正是機器人安全移動所需要的。空閒的格子是它可以行駛的地方;佔據的格子是要避開的牆壁、傢俱和人;未知的格子則是邊界——它還沒看過的地方,而那恰恰是探索者下一步該去的方向。注意,柵格地圖從不存「這是一把椅子」或「這是一道門」,它只存每個小方格有多滿。這種樸素正是它的長處。
格子大小裡悄悄藏著一個權衡。很小的格子能捕捉細節——細細的桌腳、窄窄的縫隙——但一個房間就需要數百萬個格子,既吃記憶體,又拖慢每一次查詢。大格子便宜又快,卻會把小障礙物糊成實心的一團。選擇格子大小,其實就是在選擇你願意為多少細節付出代價。
讓每一次掃描投票
單獨一次雷射或深度讀數,永遠不能全信。LiDAR 和深度相機都受感測器雜訊困擾:一束光可能擦到一粒塵埃、被玻璃反射,或者把距離多報了幾公分。所以,佔據柵格地圖不會讓某一次讀數把格子一錘定音,而是讓每一次讀數都投下一小票,格子相信的是群體,而不是任何單獨一位投票者。
讓一束光變得有資訊量的訣竅就在這裡。一次測距讀數同時告訴你兩件事。光束停下的那個點,很可能是被佔據的——有東西擋住了它。但光束一路穿過、才到達那裡的那整段空氣,一定是空的,否則它會更早停下。所以,一條射線把一個格子推向「佔據」,把它身後一連串格子推向「空閒」。這有時被稱為逆感測器建模:從感測器的報告反推世界的樣子。
- 取一次測距讀數,用機器人已知的位姿,算出這束光在柵格裡從哪裡出發、又在哪裡結束。
- 沿著從起點到終點的那一串格子走一遍,把每個格子都往「空閒」輕推一點——光束穿過了它們,所以它們是空的。
- 在光束停下的那個格子上,把它往「佔據」輕推——那裡有東西把光束反射了回來。
- 對掃描中的每一束光、以及機器人移動時的每一次掃描,都重複這個過程。有把握的格子會穩定在 0 或 1 附近;忽明忽暗、拿不準的格子,則在 0.5 附近徘徊。
正是這種投票的習慣,讓地圖能甩開雜訊。一次把某個格子誤畫成佔據的虛假反射,會在接下來光束十次乾乾淨淨地穿過時被票數壓倒。柵格地圖也悄悄應對著變化:當原本站在門口的人走開後,新湧入的「空閒」票會慢慢把他抹去。地圖隨著房間一起呼吸。
什麼時候柵格地圖是殺雞用牛刀
佔據柵格地圖是一種稠密的度量地圖:它鎖定真實世界的距離,把地面的每一個方格都填滿,無論那裡有沒有值得關注的東西。這讓它非常適合在椅子腿間穿梭的掃地機器人,但對於一台橫穿空曠大倉庫的機器人來說就太浪費了——那數百萬個格子,大多只是在說「空、空、空」。
一種更輕量的替代方案是路標地圖(特徵地圖)。它不記錄每一個格子,只記住一組稀疏的、有辨識度的點——這裡一根柱子、那裡一個牆角、裝卸口上方一塊醒目的標牌——以及它們的座標。它儲存起來便宜得多,匹配起來也快,但它對路標之間的空白一無所知,所以在繞開雜物方面就沒那麼直接好用。
更輕的還有拓撲地圖,它乾脆把精確距離全都丟掉,只保留一張「地點以及它們如何相連」的圖:「大堂連著 A 走廊,A 走廊連著實驗室。」這就像按比例繪製的平面圖與地鐵路線圖之間的區別。這兩種風格的對比——精確而稠密,對上稀疏而連通——正是度量地圖與拓撲地圖的核心,而在兩者間做選擇,是機器人開發者最早要拍板的設計決定之一。