:從里程計到目標檢測的機器人定位與感知)
SLAM 在移動機器人和具身智能里解決的是一個繞不開的問題機器人怎么知道自己在哪怎么知道周圍有什么。它不是一個單一算法而是一整套“定位 建圖 感知”的配合方式。這篇文章適合兩類人看一是準備做移動機器人、無人機、AGV 相關(guān)項目想系統(tǒng)理解 SLAM 定位與感知的入門者二是已經(jīng)跑過開源 SLAM但對里程計、目標檢測、剛體變換、射影變換、李群與李代數(shù)這些概念還停留在名詞層面的人。我會按“問題—幾何—感知—選型—實操—排坑”的順序展開少堆公式多給判斷標準和可復現(xiàn)步驟。1. SLAM 解決的不只是“建圖”而是“我在哪、周圍有什么”1.1 定位與建圖為什么是一對共生問題SLAM 全稱是 Simultaneous Localization and Mapping同時定位與建圖。它處理的核心矛盾是機器人要建立環(huán)境地圖就需要知道自己在地圖中的位置要知道自己的位置又需要一張可靠的地圖。這個互相依賴的關(guān)系是所有 SLAM 系統(tǒng)都要面對的“先有雞還是先有蛋”問題。工程上的通用做法是機器人一邊移動一邊用傳感器觀測環(huán)境先做一次帶誤差的位姿猜測然后用路標、回環(huán)等約束把位姿和地圖一起修正。整個過程不斷重復形成“預(yù)測—觀測—修正—再預(yù)測”的閉環(huán)。所以 SLAM 本質(zhì)上不是一個離線處理工具而是一個實時狀態(tài)估計過程。這里要先建立一個判斷SLAM 不是某個開源倉庫里的單文件而是多模塊組合。前端負責從傳感器數(shù)據(jù)里估計幀間運動后端負責對歷史位姿和路標做優(yōu)化回環(huán)檢測負責認出“我來過這里”建圖模塊負責把估計結(jié)果組織成可用的地圖。你讀開源項目時不要只盯著某一個文件先問自己這段代碼屬于前端、后端、回環(huán)還是建圖這個問題答不上來說明還沒建立起系統(tǒng)視圖。1.2 定位、感知、規(guī)劃在機器人里怎么分工具身智能強調(diào)機器人與環(huán)境實時交互機器人需要連續(xù)回答三件事我在哪周圍是什么下一步怎么動。目標檢測和分割解決“周圍是什么”里程計和全局定位解決“我在哪”路徑規(guī)劃和控制解決“怎么動”。這三種能力不能獨立成立。舉個例子你訓練了一個目標檢測模型輸出“障礙物 0.85”的框但如果檢測結(jié)果沒有從像素坐標系轉(zhuǎn)換到相機坐標系再轉(zhuǎn)換到世界坐標系機器人根本不知道障礙物離它多遠、在什么方向。很多入門項目表面上是“檢測 SLAM”實際大量時間花在坐標轉(zhuǎn)換、時間戳同步和消息類型對接上這不是浪費時間恰恰是必經(jīng)之路。所以我的建議是目標可以定位與感知一起學但切入順序先從定位下手。定位模塊的輸入輸出更明確有 ground truth 可以驗證結(jié)果好不好一眼能看出來目標檢測模型單獨跑通很簡單但要真正讓機器人用上反而要處理一堆定位側(cè)的問題。1.3 AGV、無人機和水下機器人場景不同底座相同從室內(nèi) AGV 到無人機再到水下機器人應(yīng)用場景差別很大但底座問題一致都是“無 GPS 或 GPS 不可靠環(huán)境下如何持續(xù)估計自身狀態(tài)并構(gòu)建環(huán)境表示”。室內(nèi)機器人常用 2D 激光雷達和輪式里程計地面可近似平面無人機有六個自由度運動快、視角變化劇烈更需要視覺慣性融合水下環(huán)境光線衰減嚴重視覺特征少聲納成為主要傳感器??吹健八履繕藱z測”“無人機目標檢測”這類需求時不要誤以為它們是完全不同的技術(shù)分支。它們的差異主要在傳感器、數(shù)據(jù)形態(tài)和約束條件上但感知模塊最終都要輸出“目標在哪里、是什么、屬于靜態(tài)還是動態(tài)”定位模塊都要輸出“機器人當前位姿”。先掌握共同底座再針對場景換傳感器和數(shù)據(jù)格式是更高效的學習方式。2. 從里程計到李群李代數(shù)先分清位姿、變換和優(yōu)化對象2.1 里程計的本質(zhì)與漂移來源里程計是 SLAM 前端里最直白的位姿估計方式。輪式機器人用編碼器數(shù)輪子轉(zhuǎn)了多少圈再根據(jù)輪距和轉(zhuǎn)向模型推算位姿變化視覺里程計通過相鄰兩幀圖像特征匹配估計相機相對運動激光里程計則用點云配準常見方法包括 ICP、NDT 等。它們的共同點是“增量式”只估計當前時刻相對于上一時刻的變化量然后不斷累加。增量式方案的優(yōu)點是實現(xiàn)簡單、速度快、不依賴外部全局信息缺點是誤差會累積。旋轉(zhuǎn)估計哪怕只有一點偏差走完一段長路徑后位置誤差可能擴大到幾米。所以里程計通常作為前端初始值或融合源之一不能單獨作為長期定位答案。如果你在 SLAM 代碼里看到 twist 這個詞它通常被翻譯為“速度旋量”或“空間速度”本質(zhì)是線速度與角速度的組合常出現(xiàn)在勻速模型、IMU 預(yù)積分和位姿插值代碼里。先把它理解成“一個帶方向的增量運動”就夠了不必在術(shù)語翻譯上卡住。2.2 剛體變換、仿射變換、射影變換怎么區(qū)分這三類變換是機器人視覺里最容易混淆的概念我建議按“保什么不變”來記。剛體變換對應(yīng)機器人或相機在真實三維空間中的運動保持物體形狀、長度、角度不變。它由一個旋轉(zhuǎn)矩陣加一個平移向量組成是 SE(3) 群里的元素。傳感器外參標定、機器人位姿表示、坐標框架轉(zhuǎn)換用的都是剛體變換。仿射變換允許平移、旋轉(zhuǎn)、縮放和錯切不再保角度和長度但仍然保持平行性。它在二維圖像處理中出現(xiàn)最多比如目標檢測數(shù)據(jù)增強里的隨機旋轉(zhuǎn)、縮放、錯切以及圖像配準里的仿射匹配。射影變換也叫單應(yīng)變換是針孔相機成像時發(fā)生的變換。一個三維平面上的點在圖像平面上的映射就是射影變換它連平行性都不保證。全景拼接、平面標記識別、視覺 SLAM 里的單應(yīng)矩陣分解都會用到它。區(qū)分它們的實際價值在于看到一段矩陣運算代碼先判斷它描述的是真實空間運動還是圖像坐標變化。如果是真實空間運動旋轉(zhuǎn)矩陣必須是正交矩陣逆矩陣等于轉(zhuǎn)置如果是圖像坐標變換自由度更高不能機械套用剛體變換的求逆方式。2.3 李群與李代數(shù)優(yōu)化位姿時為什么繞不開李群與李代數(shù)在 SLAM 里不是干巴巴的數(shù)學而是為了解決一件事位姿求導。視覺 SLAM 的核心優(yōu)化目標是讓重投影誤差最小優(yōu)化時要對旋轉(zhuǎn)矩陣或位姿求導。旋轉(zhuǎn)矩陣本身帶正交約束直接對矩陣元素求導很難保持約束歐拉角有萬向鎖問題四元數(shù)適合表示和插值但導數(shù)處理依然不直觀。李代數(shù)提供了一種旋轉(zhuǎn)和位姿的“局部向量表達”把帶約束的矩陣優(yōu)化問題轉(zhuǎn)化為無約束的向量優(yōu)化問題。具體來說SO(3) 是三維旋轉(zhuǎn)群對應(yīng)李代數(shù) so(3) 是三維向量SE(3) 是三維剛體運動群對應(yīng)李代數(shù) se(3) 是六維向量。二者通過指數(shù)映射和對數(shù)映射互相轉(zhuǎn)換。實際工程里你不需要手推李代數(shù)公式但必須掌握三點一是 Sophus、Eigen 這類庫里指數(shù)映射和對數(shù)映射怎么調(diào)用二是 g2o、Ceres 等優(yōu)化庫里位姿頂點和邊用的擾動模型是什么三是為什么代碼里常用Sophus::SE3d而不是直接用 4x4 矩陣去做優(yōu)化。剛接觸時不要一開始就卡在對數(shù)映射的公式推導上。先跑一個最小例程看看SO3、SE3、exp、log的輸入輸出長什么樣形成直覺之后再回頭補推導會高效很多。3. 目標檢測與分割不是獨立模塊要和定位共享坐標系3.1 2D 目標檢測的評價與落地局限目標檢測的任務(wù)是“框出來 認出來”。YOLO 系列、DETR 系列這類模型輸出目標類別、置信度和二維邊界框。在機器人場景里二維框本身不夠因為它缺少深度信息只能告訴你圖像上哪里有目標不能直接告訴你目標的世界坐標。想要拿到世界坐標需要把二維框和深度圖、點云、雙目視差或激光數(shù)據(jù)融合。訓練目標檢測模型時評價標準不能只看“準確率”。標準做法是先按類別計算 Precision 和 Recall再通過不同置信度閾值畫出 PR 曲線計算每個類別的 AP最后對所有類別取平均得到 mAP。還要注意 IoU 閾值mAP0.5 和 mAP0.75 代表不同嚴格程度不能隨便拿兩個模型在不同閾值下的結(jié)果對比。機器人任務(wù)里尤其要多看召回率漏檢一個障礙物比誤檢更危險。小目標檢測是個典型難點。無人機視角下的地面行人、遠處車輛、倉庫高貨架上的障礙物目標像素少、特征弱。YOLOv8 這類工具可以通過配置文件調(diào)整檢測頭或錨框尺寸但最終效果仍然取決于訓練數(shù)據(jù)中小目標的比例。先檢查數(shù)據(jù)分布再調(diào)網(wǎng)絡(luò)結(jié)構(gòu)才是正確順序。3.2 三維目標檢測與語義、實例分割三維目標檢測輸出的是三維包圍框中心坐標、長寬高、朝向角通常表達在相機坐標系或激光雷達坐標系下。它可以基于激光點云實現(xiàn)也可以基于圖像做單目或雙目三維檢測還可以做圖像和點云融合。三維框比二維框多一個朝向角而這個朝向角恰恰是機器人避障和路徑規(guī)劃最需要的信息。分割任務(wù)則更細語義分割給每個像素或每個點一個類別標簽實例分割還會區(qū)分同一類別里的不同個體。對 SLAM 來說分割最有價值的應(yīng)用是識別動態(tài)物體。如果場景里有人走動把落在人身上的特征點剔除就能避免把移動目標當成靜止路標減少定位漂移。這也是“動態(tài) SLAM”最常見的工程實現(xiàn)思路。3.3 動態(tài)目標過濾與語義地圖把檢測和分割接入 SLAM目前常見做法有幾類動態(tài)特征過濾檢測到動態(tài)目標后剔除目標框內(nèi)的特征點或用分割掩碼屏蔽對應(yīng)區(qū)域。語義地圖把檢測和分割結(jié)果與地圖點綁定建出來的地圖帶語義標簽機器人可以搜索“椅子在哪”而不只是面對一堆無標簽點。重定位輔助檢測門牌、二維碼、固定標志物用已知位置的目標幫助恢復全局位姿。感知驅(qū)動的建圖改進紋理缺失或小物體區(qū)域用深度學習方法補充約束。這些做法的共同前提是檢測模塊和定位模塊必須共享坐標系和時間戳。我見過很多項目模型精度不低最后卻失敗在檢測框沒有正確投影到相機坐標系或幀時間戳差了幾十毫秒。先把坐標轉(zhuǎn)換鏈路跑通再來調(diào)置信度閾值順序不能反。4. 視覺 SLAM 和激光 SLAM 怎么選關(guān)鍵看環(huán)境和成本4.1 視覺方案單目、雙目、RGB-D 各自邊界視覺 SLAM 是入門性價比最高的方向因為相機便宜、信息豐富。但不同相機形態(tài)的邊界完全不同。單目相機只有一個攝像頭成本最低但存在尺度不確定問題。單目 SLAM 可以估計軌跡和地圖的相對結(jié)構(gòu)無法直接得出“這個物體距離我 3 米”這樣的絕對尺度因此不能直接用于高精度導航。雙目相機通過左右視差估計深度能解決尺度問題代價是標定復雜、計算量增加。RGB-D 相機直接輸出像素對齊的深度圖室內(nèi)近距離效果好但室外強光下深度傳感器容易失效。特征點方案的代表是 ORB-SLAM 系列穩(wěn)健、文檔多適合入門直接法和半直接法適合紋理少但亮度穩(wěn)定的場景光照變化大時魯棒性較差。判斷視覺方案適不適合你的場景就看三個問題光照是否穩(wěn)定紋理是否足夠運動是否太快。三個條件都不滿足視覺 SLAM 會很難受。4.2 激光方案2D 建圖導航與 3D 激光里程計激光 SLAM 用激光雷達直接測距不依賴光照點云精度高。室內(nèi)移動機器人常用 2D 激光雷達配合 gmapping、Cartographer 做建圖這類方案在地面近似平面的場景里非常成熟掃地機器人、倉儲 AGV 大量采用。3D 激光雷達適合戶外復雜環(huán)境常用 LOAM 系列、LIO-SAM、FAST-LIO 等方案配合 IMU 提高快速運動下的穩(wěn)定性。激光方案的缺點是成本高2D 激光只能看到某一高度平面在坡道、分層貨架等場景會漏掉關(guān)鍵幾何信息3D 激光價格更貴點云處理也更重。如果預(yù)算有限又是在室內(nèi)光照穩(wěn)定環(huán)境視覺方案更容易起步如果要在夜間或強光照變化環(huán)境長期運行激光方案更可靠。4.3 標定與多源融合別讓時間戳和坐標系拖后腿無論選哪種方案傳感器標定都要提前做。相機內(nèi)參標定影響圖像去畸變和投影精度常用工具是 Kalibr 或 OpenCV 標定板相機與激光雷達、相機與 IMU 的外參標定決定多傳感器數(shù)據(jù)能否對齊到同一坐標系。Kalibr 是基于 ROS 的工具一般用 Aprilgrid 標定板錄制 rosbag再離線標定。很多項目定位效果差不是 SLAM 算法不行而是標定參數(shù)不對或時間戳沒對齊。IMU 和相機之間存在延遲快速運動時幾十毫秒偏差就會造成明顯漂移。建議先把傳感器時間同步和坐標系關(guān)系整理清晰再談算法調(diào)參。下面給一個選型參考維度視覺 SLAM激光 SLAM主要傳感器單目/雙目/RGB-D 相機2D/3D 激光雷達成本低中到高光照敏感度高低尺度問題單目有尺度不確定可直接測距典型地圖稀疏特征點地圖/稠密點云2D 柵格地圖/3D 點云適用場景室內(nèi)、光照穩(wěn)定、紋理豐富室內(nèi)外、光照變化大、幾何結(jié)構(gòu)清晰入門難度中數(shù)學要求稍高中重投影較直觀但工具鏈復雜5. 從開源庫到軌跡評估把一條 SLAM 流程完整跑通5.1 環(huán)境準備先確認依賴版本再編譯我一般建議在 Linux 環(huán)境里跑 SLAMUbuntu 20.04 或 22.04 都比較常見。使用 ROS 可以省去很多消息和時間同步的重復工作但如果不打算用 ROS也可以直接編譯 ORB-SLAM 這類純 C 項目。依賴通常包括Eigen3矩陣運算、OpenCV圖像處理、Sophus李代數(shù)、Pangolin可視化界面、g2o 或 Ceres圖優(yōu)化。目標檢測模型如果要在 SLAM 流程里實時運行大概率需要 GPU如果只是驗證思路純 CPU 也能跑但要降低輸入分辨率和 batch 大小。# 示意命令具體版本以你的系統(tǒng)為準 sudo apt update sudo apt install build-essential cmake git libeigen3-dev # 軌跡評估工具通常用 Python 安裝 pip install evo第一次跑 SLAM 項目最容易翻車的地方是依賴版本不匹配。OpenCV 3 和 OpenCV 4 的接口有差異Pangolin 對 OpenGL 版本有要求Sophus 有非模板版和模板版之分。先讀項目的 README 和 CMakeLists確認依賴版本范圍再逐項安裝。不要一上來就全量 apt install缺少哪個就補哪個報錯日志里通常已經(jīng)寫了線索。5.2 跑通 ORB-SLAM 的最小流程ORB-SLAM 系列是入門視覺 SLAM 最常見的開源項目。以單目為例最小流程是編譯項目下載 TUM 或 EuRoC 數(shù)據(jù)集運行單目示例。# 示意命令路徑和參數(shù)以你的環(huán)境為準 cd ORB_SLAM2 ./Examples/Monocular/mono_tum \ Vocabulary/ORBvoc.txt \ Examples/Monocular/TUM1.yaml \ /path/to/rgbd_dataset_freiburg1_desk這里最容易忽略的幾點路徑不能包含中文和空格否則加載詞典或數(shù)據(jù)集時會出錯。運行前確認數(shù)據(jù)集序列和時間戳文件存在ORB-SLAM 依賴關(guān)聯(lián)文件來找圖像。單目方案初始化需要緩慢平移攝像頭如果一開始對著白墻或純紋理區(qū)域初始化會失敗。跑通之后先別急著換數(shù)據(jù)集。打開可視化界面觀察相機視角、關(guān)鍵幀和地圖點的生成情況確認建圖不是一團亂麻之后再換更復雜的數(shù)據(jù)序列。5.3 用 evo 做軌跡評估指標怎么選跑通只是第一步評估精度才是證明方案可行的關(guān)鍵。evo 是 SLAM 軌跡評估最常用的開源工具支持 TUM、KITTI、EuRoC 等數(shù)據(jù)集格式核心指標有兩個絕對位姿誤差 APE 和相對位姿誤差 RPE。# 將估計軌跡與真值對比-a 表示先做坐標對齊 evo_ape tum groundtruth.txt keyframe_trajectory.txt -a # 相對誤差更適合評估里程計的局部漂移 evo_rpe tum groundtruth.txt keyframe_trajectory.txt -a看評估結(jié)果時不要只盯著 RMSE 一個數(shù)。還要看最大值、中位數(shù)和誤差曲線了解誤差集中出現(xiàn)在哪個時間段。如果誤差在某個轉(zhuǎn)彎處突然增大很可能是跟蹤丟失后重定位造成的和普通漂移是兩類問題。evo 也可以讀 rosbag 里的軌跡 topic方便實機測試時直接評估。5.4 把檢測模型接進來先離線、再同步、再實時如果你想把目標檢測和 SLAM 結(jié)合我的建議是分三步做。第一步離線驗證用數(shù)據(jù)集圖像跑檢測模型把檢測結(jié)果保存成文件不接入 SLAM。先確認模型本身的效果、類別的準確性、小目標召回的短板。第二步同步對接把檢測結(jié)果按時間戳與圖像幀對齊再把檢測框或分割掩碼投影到相機坐標系驗證坐標轉(zhuǎn)換正確。這一步通常在獨立的 Python 腳本里完成不要直接改 SLAM 主循環(huán)。第三步實時集成檢測線程和 SLAM 線程分別運行用隊列或消息緩存做同步。先在低分辨率、低幀率下驗證穩(wěn)定性再逐步提高輸入大小。不要一上來就開最大并發(fā)GPU 占用瞬間拉滿SLAM 線程反而被拖慢。我見過很多項目在這一步栽跟頭模型精度很高但每次接進 SLAM 后地圖就花。原因往往是檢測線程把 SLAM 線程的鎖搶了或檢測結(jié)果直接寫入了共享地圖點數(shù)組。先保證兩個線程的邊界清晰再談精度。6. 常見坑、邊界認識與一條現(xiàn)實的上手路線6.1 最容易踩的五個坑第一時間戳不對齊。多傳感器系統(tǒng)里不同傳感器觸發(fā)時間不同直接按消息到達順序處理會產(chǎn)生錯位。先用工具畫出時間戳分布再決定是否用插值或硬件同步。第二坐標系沒轉(zhuǎn)換。檢測框是從像素坐標系輸出的SLAM 優(yōu)化的是相機坐標系或世界坐標系中間隔著內(nèi)參、外參和畸變模型。少一個環(huán)節(jié)結(jié)果就偏了。第三標定參數(shù)不準。相機內(nèi)參、相機與 IMU 外參、激光與相機外參任何一項不準都會讓多傳感器融合效果大打折扣。大多數(shù)情況下先重新標定比換算法更有效。第四復制數(shù)據(jù)集參數(shù)到自己的環(huán)境。每個系統(tǒng)都有焦距、分辨率、失真系數(shù)、話題名差異不按自己的傳感器重新配置跑出來一片亂是正常現(xiàn)象。第五用評估工具時不做對齊就報誤差。evo 的軌跡評估默認可以先做 Sim(3) 或 SE(3) 對齊不對齊就統(tǒng)計誤差誤差里混合了坐標框架偏差和真實算法誤差結(jié)論沒有意義。6.2 SLAM、三維重建、檢測與分割的邊界很多初學者把 SLAM 和三維重建混為一談。SLAM 的核心目標是實時定位和一致性地構(gòu)建可用于導航的地圖地圖可以是稀疏特征點不一定要漂亮三維重建的目標是把場景還原成高精度的稠密模型和紋理計算量大實時性要求低。側(cè)重點完全不同。檢測和分割也一樣。目標檢測告訴你“這是什么、在哪里”但如果不結(jié)合深度和坐標轉(zhuǎn)換它只是圖像層的感知不是空間層的感知。支持某個功能不等于它在所有場景都穩(wěn)定。RGB-D 相機在室內(nèi)好用拿到陽光下可能直接丟深度YOLO 在公開數(shù)據(jù)集上精度高換到你的機器人視角和光照條件下可能需要重新采集數(shù)據(jù)微調(diào)。對工具能力保持邊界感是工程判斷力的一部分。6.3 一條現(xiàn)實的學習路線如果想系統(tǒng)入門 SLAM 與機器人感知我建議按下面順序走。第一步讀完《視覺SLAM十四講》的核心章節(jié)重點是三維空間剛體運動、李群與李代數(shù)、相機模型、狀態(tài)估計和非線性優(yōu)化。配合書中代碼在 Ubuntu 里親手編譯一遍熟悉 Eigen、Sophus、OpenCV 的用法。第二步跑通 ORB-SLAM 或同類開源項目先用公開數(shù)據(jù)集驗證再用自己的相機錄制數(shù)據(jù)。自己錄一次數(shù)據(jù)就會理解標定、時間戳、圖像質(zhì)量對結(jié)果的影響這些是公開數(shù)據(jù)集給不了的體驗。第三步在定位基礎(chǔ)上接入檢測或分割模塊做一個動態(tài)目標過濾的小實驗。哪怕只用最簡單的方式把移動目標區(qū)域的點剔除也能讓你真正理解感知和定位怎么協(xié)同。第四步建立評估閉環(huán)。用 evo 或 ROS 工具記錄并評估軌跡把每次實驗的配置、參數(shù)、結(jié)果和日志整理清楚。后續(xù)調(diào)優(yōu)時這套記錄就是你排查問題的最好依據(jù)。最后提醒一句學習 SLAM 最容易犯的錯誤是花大量時間追最新論文卻不關(guān)心數(shù)據(jù)、標定和評估是否可靠。先把一條小流程跑穩(wěn)再擴大場景比什么技術(shù)都重要。真正決定項目成敗的往往不是模型選得有多新而是前置環(huán)境和輸入材料有沒有處理干凈。