Wiki
small_gicp_relocalization(先驗點雲地圖重定位)
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
1.small_gicp_relocalization(先驗點雲地圖重定位)
1.1.實車先看:地圖、起點和雲臺零位
這個節點在已有地圖導航模式 slam:=False 下,把當前配準點雲與先驗PCD地圖對齊,輸出 map → odom 的位置、朝向修正。它不直接控制車輪或雲臺,也不是重新建立地形障礙的節點;slam:=True 的整套啟動不執行它。
| 實車上遇到的問題 | 優先核對 | 用直白的話解釋 |
|---|---|---|
| 啟動後定位不對或找不到地圖 | prior_pcd_file、地圖來源與座標 |
要提供當前場地的三維PCD;Nav2二維地圖與PCD還必須使用對應的位置和朝向 |
| 車停在地圖中某個位置,卻一開始就對不上 | init_pose |
本引數直接給 map→odom 一個初始猜測,不是一律填寫“底盤在地圖中的位置” |
| RViz點了初始位置,朝向卻偏了一個雲臺角 | robot_base_frame |
當前訊息被當作 gimbal_yaw 的地圖位姿;箭頭應對應雲臺yaw層朝向,不能一律當底盤車頭 |
| 同一地圖,換個雲臺零位啟動後整體方向不同 | base_frame、lidar_frame 與PCD建圖時的參考 |
原始碼啟動時用當時的底盤←雷達變換處理整份地圖;雷達隨yaw轉,建圖和當前零位是否對應必須核實 |
| 定位跳到相似牆面、柱子或另一條走廊 | 初值、max_dist_sq 和現場可見結構 |
匹配距離放太寬可能接受錯誤對應,但初值、重複結構或座標錯誤也不能只靠收緊距離解決 |
| 定位計算慢、細節不足 | 兩個 leaf_size、num_neighbors、num_threads |
先確認點雲正確且足夠,再權衡細節和計算量;更密的點不保證更準確 |
當前沒有實物,也沒有本節點的有效重定位測試。下文分別說明“程式碼如何解釋這些值”和“實車是否適用”,不把原始碼流程當作已經驗證的定位效果。
1.2.引數
1.2.1.ros__parameters(ROS節點引數)
1.2.1.1.參數列
前12項對應當前實物 YAML;prior_pcd_file 雖被註釋,卻由 launch另行傳入;input_cloud_topic 沒寫在這份 YAML中,仍使用原始碼預設值。這兩項也列出,便於完整理解輸入來源。
small_gicp_relocalization:
ros__parameters:
use_sim_time: False
num_threads: 4
num_neighbors: 20
global_leaf_size: 0.1
registered_leaf_size: 0.05
max_dist_sq: 3.0
map_frame: "map"
odom_frame: "odom"
base_frame: "base_footprint"
robot_base_frame: "gimbal_yaw"
lidar_frame: "front_mid360"
init_pose: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # [x, y, z, roll, pitch, yaw]
# The prior_pcd_file does not need to be specified since it going to be set by defaults in launch.
# prior_pcd_file: ""
| 引數名 | 當前值 | 單位 | 實車處理建議 | 作用 | 調大效果 | 調小效果 | 生效條件/備註 |
|---|---|---|---|---|---|---|---|
use_sim_time |
False;模擬 True |
不適用,布林 | 上實物前必須核對並正確配置 | 控制節點與TF快取的ROS時鐘 | 不適用 | 不適用 | 地圖初始化查TF使用節點當前時間;匹配與釋出定時器用真即時間,True不會使其按模擬速率執行 |
num_threads |
4 |
執行緒數,計數 | 通常保持當前值,不作為優先除錯項 | 給鄰域估計、建樹與匹配計算設定並行執行緒 | CPU資源足夠時可能更快,也可能與Point-LIO等爭搶資源 | 並行度降低,計算可能更慢 | 應為正數;不是匹配頻率;降取樣呼叫未傳此值,當前庫預設4執行緒 |
num_neighbors |
20 |
鄰點數量,計數 | 實物執行時重點觀察,有問題再針對性調整 | 用每點附近的鄰點描述區域性牆面、地面等形狀 | 描述範圍通常更大,計算增加,可能混入牆角兩側等不同結構 | 描述更區域性、更快,但可能對稀疏點和噪聲更敏感 | 同時用於地圖和即時點雲;不是20幀或20個匹配候選;當前庫鄰點不足5時不能形成正常區域性估計 |
global_leaf_size |
0.1 |
m,三維體素邊長 | 實物執行時重點觀察,有問題再針對性調整 | 啟動時將先驗PCD降取樣後用於匹配 | 地圖點通常更少,負擔下降,細節減少 | 地圖點通常更多,啟動和匹配負擔增加 | 不修改PCD檔案或二維地圖解析度;應為正數;對目標地圖只在啟動時處理 |
registered_leaf_size |
0.05 |
m,三維體素邊長 | 實物執行時重點觀察,有問題再針對性調整 | 每輪匹配前將累計輸入點雲降取樣 | 輸入點通常更少,計算減少,細小結構可能減少 | 輸入點通常更多,負擔上升;噪聲、動態點也可能保留更多 | 不修改Point-LIO降取樣設定;應為正數;沒有另行剔除人、敵車等動態點 |
max_dist_sq |
3.0 |
m²,對應點距離的平方 | 實物執行時重點觀察,有問題再針對性調整 | 拒絕當前猜測下距離太遠的對應點對 | 允許更遠的點配對,也增加相似結構誤配可能 | 配對更嚴格,初值較差時可能剩餘點對不足 | 當前距離門檻約√3=1.73 m;不是3 m、定位精度或允許的總位置誤差 |
map_frame |
"map" |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 指定輸出TF的父系,約定為目標地圖參考系 | 不適用 | 不適用 | 改名稱不自動轉換PCD座標;需與二維地圖和全域性定位約定一致 |
odom_frame |
"odom" |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 指定輸出TF的子系,約定為輸入配準點雲參考系 | 不適用 | 不適用 | 當前輸入應為odom座標;節點不按該名稱轉換輸入點,也不校驗訊息frame_id與它一致 |
base_frame |
"base_footprint" |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 啟動時查詢它←雷達的變換,用於處理先驗PCD | 不適用 | 不適用 | 當前是底盤參考層;只取一次成功查詢,不隨隨後雲臺轉動重轉地圖;適用前提與PCD來源有關 |
robot_base_frame |
"gimbal_yaw" |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 指定initialpose訊息所代表的機器人部位,並參與換算 | 不適用 | 不適用 | 僅手動初始位姿回撥使用;不是每輪匹配的目標系,也不修改輸入點座標;此處是實際yaw層 |
lidar_frame |
"front_mid360" |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 與base_frame一起確定啟動時處理PCD的變換 | 不適用 | 不適用 | 僅地圖載入過程用它查TF;不能由此認定即時輸入是雷達自身系;MID360隨yaw、不隨pitch轉 |
init_pose |
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0] |
前3項m,後3項rad | 上實物前必須核對並正確配置 | 初始化匹配變換,即當前約定下map←odom的猜測 | 不適用,應按參考系逐項設定 | 不適用,應按參考系逐項設定 | 順序x/y/z/roll/pitch/yaw,旋轉按Rz×Ry×Rx;全零為單位變換,不保證機器人位於地圖原點 |
prior_pcd_file |
YAML未配置;由launch的 prior_pcd_file 提供 |
不適用,檔案路徑 | 上實物前必須核對並正確配置 | 載入當前場地的三維先驗地圖 | 不適用 | 不適用 | 整套啟動後面的引數字典傳入路徑;當前預設實物路徑不存在,模擬預設PCD存在;不能用空路徑代替 |
input_cloud_topic |
"registered_scan",原始碼預設;YAML未配置 |
不適用,話題名稱 | 上實物前必須核對並正確配置 | 接收用於匹配的配準點雲 | 不適用 | 不適用 | 當前應來自loam_interface、座標為odom;不是sensor_scan、terrain_map或原始雷達區域性點雲;型別PointCloud2 |
本塊沒有當前完全不使用的自定義引數:robot_base_frame 只在收到手動初始位姿時參與,init_pose 只在啟動時設初值,它們不是持續調節項。話題、座標系和路徑不能按數值大小調參。
1.2.1.2.引數詳解
1.2.1.2.1.輸入與輸出:匹配的是哪兩份點雲
| 方向 | 資料 | 程式碼實際用途 |
|---|---|---|
| 讀取檔案 | prior_pcd_file |
載入PCD,啟動時變換、降取樣,建立固定目標地圖 |
| 訂閱 | registered_scan,可由input_cloud_topic更名 |
複製XYZ座標並累加多幀,作為本輪匹配點雲;不用反射強度或點內時間 |
| 訂閱 | initialpose,PoseWithCovarianceStamped |
用人工給定的位姿重設匹配初值;話題名寫死為相對名 |
| 廣播 | map → odom |
釋出點雲匹配得到的參考系修正;不釋出獨立位姿或匹配點雲話題 |
即時點雲已經由Point-LIO與介面節點配準到 odom,本節點直接累加座標,不再逐幀轉雷達系,也不額外按雲臺yaw旋轉這些點。雲臺旋轉時,靜態環境應仍在共同的odom座標下對齊;這個結論依賴上游位姿、安裝外參和時間介面正確,目前沒有獨立yaw驗證。
回撥只儲存最近輸入的frame_id與時間戳,沒有檢查多幀是否同系,也沒有在frame_id變化時清空累計點。PCD沒有ROS訊息那樣的frame_id,本節點按自己的來源假設處理;檔名和座標系字串不能證明地圖已經對應。
每500 ms真即時間嘗試匹配一次,有點才處理;每輪降取樣、估計區域性形狀、搜尋地圖對應點,最多做10次最佳化迭代。匹配報告收斂才更新結果,未收斂則沿用舊結果,但本輪累計點仍會清空。收斂表示演算法停止條件滿足,不證明匹配到了場地中正確的位置;原始碼沒有再按匹配誤差、有效對應比例等檢查可信度。
1.2.1.2.2.prior_pcd_file:先確認用的是自己的場地地圖
整套啟動的預設路徑在安裝後的 pb2025_nav_bringup 共享目錄:
| 啟動方式 | 預設PCD路徑規則 | 當前預設檔案檢查 |
|---|---|---|
| 實物 | pcd/reality/<world>.pcd;world預設 rmul_2024 |
rmul_2024.pcd 不存在 |
| 模擬 | pcd/simulation/<world>.pcd;world預設 rmuc_2025 |
rmuc_2025.pcd 存在 |
相應實物預設二維地圖 map/reality/rmul_2024.yaml 也不存在;模擬預設二維地圖存在。這只是當前預設檔案檢查,沒有讀取執行節點引數,也不排除使用者另傳world、PCD或二維地圖路徑。上實物前需要準備當前場地的對應地圖,不能把模擬PCD存在當成實物地圖已準備。
localization_launch.py 在引數檔案之後,額外傳入 {"prior_pcd_file": prior_pcd_file},因此註釋掉這一行不表示節點不使用先驗PCD。它與Point-LIO是否啟用 prior_pcd_en 是不同功能:Point-LIO可不載入先驗,重定位節點仍需要先驗PCD。
檔案載入失敗只記錄錯誤並返回,建構函式仍繼續準備匹配目標,沒有明確阻止空目標進入後續匹配;不能把“節點起來了”視為地圖載入成功。原始碼不會在執行時重新讀取PCD,也不會替你核對它與Nav2二維地圖的位置、朝向、米制尺度或場地版本是否一致。
1.2.1.2.3.base_frame 與 lidar_frame:啟動時會轉動整份地圖
PCD讀入後,原始碼查詢 base_footprint ← front_mid360,再把這個矩陣左乘到整份地圖的每個點。它按節點當前時間查詢,失敗後每秒重試,成功一次就繼續;沒有查詢次數上限,也沒有在後續雲臺轉動時更新目標地圖。
這對應原始碼的一個來源假設:PCD基準是初始 lidar_odom,用初始底盤與雷達關係把地圖轉換到所需參考中。但當前Point-LIO實際儲存的是 camera_init 下的配準世界點,且其位姿原點涉及內部IMU;不是每一幀的雷達自身座標。把這類PCD當初始雷達系直接套機械變換,是否與實際建圖基準一致,必須複核,不能僅照README的命名認定轉換正確。
雷達在雲臺上,這一步特別依賴零位。 同一份PCD若建圖時與重新啟動時雲臺相對yaw不同,當前 base←lidar 會含不同角度;按原始碼計算,目標地圖可能被不同矩陣轉動,而獨立載入的二維地圖不會自動跟著調整。是否實際造成錯位,需要結合PCD生成時的起點、雲臺零位、底盤方向與地圖原點判斷,目前沒有測試結論。
該查詢與 loam_interface 的一次性基準轉換意圖相關,但兩節點分別查詢,不保證取到同一時刻的雲臺角。這裡的機械關係始終保留:MID360掛在 gimbal_yaw,只有實際yaw會帶動它,實際pitch位於後續層;兩個odom關節固定。重力參考、內部IMU→雷達關係或地圖來源錯誤,不能通過增大匹配距離掩蓋。
包內README還寫過“未設定時使用空變換”,當前實現沒有對應的單位變換旁路:若PCD能讀取但frame為空或TF缺失,會進入重試。應以當前原始碼為準,本輪不修改節點或地圖轉換。
1.2.1.2.4.init_pose 與 robot_base_frame:兩種初始位姿不是同一個物件
YAML的 init_pose 直接寫入匹配矩陣。 在當前輸入為odom、目標為map的約定下,它是 map←odom 初值,即“odom原點在map中的位置和方向”。
[0,0,0,0,0,0] 表示先猜兩系完全重合;這隻有在起始參考關係吻合時才合適,不表示演算法已知道機器人在地圖中的真實位置。位置單位m,角度rad;偏航90°應為約1.5708,而不是填90。旋轉按yaw、pitch、roll組成 Rz×Ry×Rx。
例如:若odom起點恰好與所描述的機器人原點重合且朝向一致,那麼機器人起始地圖位姿可能就是map←odom;若odom原點與雲臺存在高度或安裝偏移,或機器人已在odom內移動,就不能直接照抄機器人位置。當前底盤、雲臺、雷達原點不同,需按實際參考關係計算。
話題 initialpose 則被當作 robot_base_frame=gimbal_yaw 在地圖中的位姿。 回撥再查詢最新 gimbal_yaw←输入扫描系,當前掃描系應為odom,兩者相乘得到map←odom:
map←odom = 人工给定的 map←gimbal_yaw × TF中的 gimbal_yaw←odom
所以RViz箭頭若被你理解成底盤車頭,而當前雲臺相對底盤左轉90°,就可能少算一個雲臺角。位置也對應雲臺原點:若人工訊息給z=0,原始碼把它當作雲臺原點位於map的z=0,而不是“底盤地面高度為0”;高度應按這份地圖的基準核對。只改 robot_base_frame 的名字也需要重新核對整條關係,不能把“機器人”三個字自動等同於底盤。本引數僅該回呼叫,不在每次點雲匹配時扣機械角。
回撥沒有按訊息header.frame_id轉換位姿、沒有使用其協方差,也沒有按訊息時間查TF,而是取最新變換;收到首幀掃描前,掃描frame_id還為空,查詢可能失敗。手動設初值只改當前和下一輪匹配猜測,不會重轉PCD,也不清空已累計點。雲臺快速轉動時,人工位姿對應的朝向與最新TF是否同一時刻也要核對。
1.2.1.2.5.max_dist_sq:1.73 m是配對門檻,不是定位誤差指標
當前構建使用的small_gicp程式碼直接判斷“對應點距離平方是否大於 max_dist_sq”;超出就拒絕。源點先按當前猜測變換到地圖,再找最近地圖點,才檢查這項,因此在米制點雲中單位為m²:
max_dist_sq = 3.0 m² → 最大对应点距离约 sqrt(3) = 1.73 m
希望门槛为0.5 m → 平方值为0.25 m²
第二行僅解釋單位換算,不是建議修改當前值。它不限制機器人總移動距離,不表示允許定位偏差1.73 m,更不是掃描量程。錯誤初值下,源點仍可能碰巧靠近另一面牆並通過門檻。
實車中,放寬可留下更多點對,但重複柱子、相似走廊和動態物體也可能參與誤配;收緊會減少遠距離錯配,卻可能讓真實初值偏差稍大時無足夠點對。先確認地圖、初值和參考系,再結合正確匹配/誤匹配情況調整,不能單獨把“更小”理解成“更準”。
該單位按當前構建快取庫原始碼核實,庫提交為 fa0cfc983417c044b6036f71dfa448038bb9c820。CMake引用master,重新獲取依賴後應複核版本,不把當前快取行為當成所有版本的固定承諾。
1.2.1.2.6.兩個leaf_size、num_neighbors 與 num_threads(點雲精簡、鄰點數量與計算執行緒)
global_leaf_size=0.1 m 處理先驗地圖;registered_leaf_size=0.05 m 處理每輪累計即時點雲。兩者不要求相同,也不等於地形分析格子、Nav2地圖解析度或定位精度。地圖處理不會改原PCD,即時處理不會改變Point-LIO本身的輸出。
調小通常保留更多細節,代價是計算量增加;原始資料沒有的細節不會因調小而出現。遠處點稀疏、牆角或小柱子能否穩定描述,需看實際資料;人員、敵車等動態點在本節點沒有專門篩除,即時點更多也可能帶來更多幹擾。
num_neighbors=20 指每點用於描述區域性形狀的鄰點數,地圖與即時點都用它。它不是20個匹配候選或20幀累計。範圍太大可能混入牆角兩面、坡面與障礙等不同結構,太小又可能受噪聲影響;當前庫實際找到的鄰點不足5時,會設為無效區域性特徵的預設值,因此稀疏區域與降取樣尺度要一起看。
num_threads=4 控制鄰域估計、建樹及匹配的平行計算。降取樣呼叫沒有傳這個引數,當前庫該函式預設4執行緒;把引數改大,不等於所有步驟都跟著增加執行緒。它不是節點頻率,也不保證執行緒翻倍就快一倍,先沿用當前值。
1.2.1.2.7.map_frame、odom_frame、use_sim_time 與輸出邊界(地圖、里程計參考系與時間基準)
地圖匹配結果是“目標地圖←輸入累計點雲”的變換;輸出直接命名為 map→odom。要使這個名字正確,必須先保證目標PCD和輸入實際座標符合約定;本節點沒有另行變換到這兩個名稱指定的系。
輸出約20 Hz真即時間重複當前結果,點雲匹配則約2 Hz真即時間嘗試一次;20 Hz不表示每次都得到新定位。TF時間取最後收到的掃描時間加0.1秒,固定在原始碼中,不是本塊引數;也沒有“已成功匹配過”的輸出保護,啟動初值同樣可被髮布。這裡只記錄輸出介面,仍不展開此前擱置的導航走停或TF時效故障排查。
use_sim_time 應與輸入、機械TF和啟動模式一致。True影響節點當前時間與TF快取,不會讓兩個wall timer隨模擬倍速自動調整,也不會修復此前Point-LIO點時間單位或內部位姿轉換問題。
1.2.1.2.8.啟動來源與當前驗證範圍
| 啟動方式 | 引數與地圖來源 | 當前區別 |
|---|---|---|
| 整套reality導航,slam=False | 實物nav2_params.yaml,經localization_launch傳入;PCD由launch引數字典另傳 | 本表值;預設world對應的實物地圖檔案缺失,需準備當前場地地圖 |
| 整套simulation導航,slam=False | 模擬nav2_params.yaml,同樣另傳PCD | 除use_sim_time=True外,本塊12項相同;預設模擬地圖存在 |
| 整套slam=True | 進入slam_launch,不進入localization_launch | 本節點不執行,不能用建圖輸出說明本塊已驗證 |
| 包內獨立launch | 自己寫的引數字典,不讀取整套YAML | num_neighbors=10,兩種leaf_size均0.25,max_dist_sq=1.0,輸入cloud_registered,frame與PCD預設空;不能直接當整套入口 |
13項自定義引數均在構造時宣告和讀取,沒有動態引數更新回撥;init_pose 用於啟動,人工初值走 initialpose 訊息。13項之外的ROS標準 use_sim_time 由節點時鐘處理,不能混為演算法引數動態更新。
- 原始碼能確認: 引數讀取、地圖一次性轉換、累積配準點雲、平方距離門檻、啟動初值與人工初值的區別、匹配收斂後的更新規則和輸出介面。
- 模擬已觀察: 2026-10-08僅驗證獨立Point-LIO靜止和約20 cm往返;未驗證本節點、先驗地圖匹配、獨立雲臺yaw、人工初值或全域性定位。
- 必須實物測量/檔案來源核實: PCD與二維地圖的共同基準、建圖與啟動雲臺零位、雷達/內部IMU/底盤外參、地圖米制尺度及實際起點、可見結構與動態干擾、正確位置下的匹配穩定性。當前重力方向和點時間問題繼續保留待核實。
1.3.開發問題
1.3.1.關掉small_gicp
| 原模板 | 對應靜態版本 |
|---|---|
localization_launch.py |
localization_static_launch.py |
rm_navigation_reality_launch.py |
rm_navigation_reality_static_launch.py |
rm_navigation_simulation_launch.py |
rm_navigation_simulation_static_launch.py |
主要調整是關閉 small_gicp、增加靜態 map → odom;導航節點繼續複用原來的 navigation_launch.py
1.3.2.日誌某些報錯
| 日誌原文 | 含義 |
|---|---|
GICP did not converge. |
本次點雲配準沒有收斂 |
No accumulated points to process. |
沒收到可處理的即時點雲 |
TF lookup failed... |
初始化需要的 TF 查詢失敗 |
Couldn't read PCD file... |
先驗 PCD 讀取失敗 |
1.3.2.1.GICP did not converge.
點雲對不上,要自己跑一邊slam建出來PCD,然後再使用這個PCD進行匹配。
1.3.2.2.No accumulated points to process.
這條提示表示 small_gicp 的即時點雲快取為空,發生在匹配之前。現在先查資料有沒有送到,暫時不用調匹配引數或初始位姿。
它預設訂閱的是 /registered_scan,資料鏈是:
MID360 → Point-LIO → /cloud_registered
↓ loam_interface
/registered_scan → small_gicp