Wiki
pointcloud_to_laserscan(三維地形點雲轉二維掃描)
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
1.pointcloud_to_laserscan(三維地形點雲轉二維掃描)
1.1.實車先看:哪些三維點會被畫進二維地圖
當前建圖鏈為:
terrain_map_ext(odom系地形点)
→ pointcloud_to_laserscan(转到底盘系,筛选并投影)
→ obstacle_scan(base_footprint系二维扫描)
→ slam_toolbox(二维建图)
這個節點在整套 slam:=True 啟動中使用。已有地圖導航 slam:=False 不走這個入口;當前區域性/全域性代價地圖直接使用地形點雲,並非依靠這份二維掃描更新障礙。
掃描以 base_footprint 原點為中心,方向按底盤系表達。 輸入雖來自MID360,卻不是原始雷達點雲,而是 terrain_map_ext;其中 intensity 已被改成相對估計地面的高差,單位m,不是雷達反射強度。
| 實車上看到的現象 | 先看哪些引數或條件 | 怎樣理解 |
|---|---|---|
| 正常坡面被畫成障礙 | 地形估計、min_intensity |
當前10 cm高差門檻可能接納被誤估成凸起/凹陷的坡點;降低門檻也會接納更多小障礙和噪聲 |
| 下坡較遠處的點消失 | min_height、target_frame方向 |
這裡重新要求底盤系z不低於-0.5 m;上游按距離放寬高度範圍,並不保證能通過這裡 |
| 高處橫梁、懸空結構被畫成牆 | max_height、max_intensity、上游地形篩選 |
通過篩選的點會壓到二維平面;目前z上限6 m很寬,是否妨礙車輛通行需按實車包絡判斷 |
| 車旁小障礙沒進入地圖 | range_min、min_intensity 和上游輸出 |
0.3 m內的點或高差不足10 cm的點會被刪;本節點也不能恢復上游丟掉的點 |
| 小杆或障礙邊緣漏掉 | angle_increment、點雲密度 |
當前約0.5°一個角度格,每格只留最近合格點;分格更細不能補出原本沒有的回波 |
| 以為掃描固定20 Hz,實際不是 | scan_time、輸入點雲週期 |
0.05 s只寫入訊息,釋出由點雲回撥驅動,沒有20 Hz釋出定時器 |
| 有點雲卻沒有掃描 | 下游訂閱、座標TF、欄位、tf2版本 | 沒人訂閱掃描時不接點雲;當前需要有效TF以及XYZ、intensity欄位;Humble的tf2/tf2_ros 0.25.23還可能因內部死鎖斷流,見點雲和TF正常但二維地圖不更新 |
1.2.引數
1.2.1.ros__parameters(ROS節點引數)
1.2.1.1.參數列
前13項對應當前實物 YAML;模擬僅 use_sim_time=True。另外列出原始碼預設的3項,明確TF等待與無回波編碼的條件。
pointcloud_to_laserscan:
ros__parameters:
use_sim_time: False
target_frame: base_footprint
min_height: -0.5
max_height: 6.0
min_intensity: 0.1
max_intensity: 2.0
angle_min: -3.1415926 # 约 -π,-180°
angle_max: 3.1415926 # 约 +π,+180°
angle_increment: 0.00872665 # 约 π/360,0.5°
scan_time: 0.05
range_min: 0.3
range_max: 10.0
use_inf: true
原配置把 angle_min/max 的註釋寫成 ±π/2,與數值不符;當前數值對應約±π,掃描角域約360°,不是180°。
| 引數名 | 當前值 | 單位 | 實車處理建議 | 作用 | 調大效果 | 調小效果 | 生效條件/備註 |
|---|---|---|---|---|---|---|---|
use_sim_time |
False;模擬 True |
不適用,布林 | 上實物前必須核對並正確配置 | 控制節點與TF快取的ROS時間 | 不適用 | 不適用 | 輸出沿用輸入點雲時間戳,不重新按當前時間打點;應與上游和機械TF使用相同時間域 |
target_frame |
base_footprint |
不適用,座標系名稱 | 上實物前必須核對並正確配置 | 先把點座標轉到此係,再按它的原點和軸投影 | 不適用 | 不適用 | 當前是底盤系虛擬掃描;不是隻改frame_id;TF不可用時無法正常轉換;空值保留輸入系 |
min_height |
-0.5 |
m,目標系z下界 | 上實物前必須核對並正確配置 | 刪除低於底盤原點下方0.5 m的點 | 下界上移,更多低處/下坡點被刪 | 下界下移,保留更多低處點,也可能引入無關低層 | 固定高度視窗,不隨距離擴大;不是相對區域性地面的高差 |
max_height |
6.0 |
m,目標系z上界 | 上實物前必須核對並正確配置 | 刪除高於底盤原點上方6 m的點 | 保留更多高處點,懸空結構也可能進入二維圖 | 更多高處點被刪,也可能丟掉障礙的可見部分 | 不是整車高度;點還必須通過高差門檻與上游規則,調大不保證出現更多點 |
min_intensity |
0.1 |
m,當前地形點的高差下界 | 實物執行時重點觀察,有問題再針對性調整 | 只接納相對估計地面高差至少10 cm的點 | 忽略更多小高差,可能減少坡面誤判,也會漏低障礙 | 接納更多低障礙,也更容易把地面噪聲/坡面當障礙 | 當前輸入不是反射強度;地形估計不準時不能只靠這項糾正 |
max_intensity |
2.0 |
m,當前地形點的高差上界 | 通常保持當前值,不作為優先除錯項 | 刪除高差超過2 m的點 | 允許更多大高差點 | 更多大高差點被刪 | 當前近場正常高差低於0.5 m、遠場低於1 m,2 m通常不再額外裁剪;條件仍被執行 |
angle_min |
-3.1415926 |
rad,目標系平面方位角 | 通常保持當前值,不作為優先除錯項 | 指定角域下界,當前約-180° | 下界提高,角域縮小 | 下界降低,角域擴大 | 與上界共同定義方位覆蓋;不是雷達垂直視場或雲臺機械角 |
angle_max |
3.1415926 |
rad,目標系平面方位角 | 通常保持當前值,不作為優先除錯項 | 指定角域上界,當前約+180° | 上界提高,角域擴大 | 上界降低,角域縮小 | 當前近似整圈;需與下界、增量及陣列邊界共同核對 |
angle_increment |
0.00872665 |
rad/角度格,約0.5° | 實物執行時重點觀察,有問題再針對性調整 | 把方位角劃分為離散格 | 格子更粗、項數減少,近鄰方向更易合併 | 格子更細、項數增加,稀疏輸入時空格更多 | 當前生成720項;不改變MID360取樣密度或點雲降取樣;應為正數 |
scan_time |
0.05 |
s,訊息中的掃描間隔 | 上實物前必須核對並正確配置 | 給LaserScan.scan_time欄位賦值 | 訊息宣告更長間隔,釋出週期不變 | 訊息宣告更短間隔,釋出週期不變 | 應與實際輸入/輸出掃描週期對應;不是固定20 Hz開關;time_increment另寫死為0 |
range_min |
0.3 |
m,目標系水平距離 | 上實物前必須核對並正確配置 | 刪除虛擬中心0.3 m內的點 | 近處點刪得更多,可能漏車旁障礙 | 保留更多近點,也可能帶入自車回波 | 距離為sqrt(x²+y²),以base_footprint為中心;不是雷達三維斜距或完整自車掩膜 |
range_max |
10.0 |
m,目標系水平距離 | 實物執行時重點觀察,有問題再針對性調整 | 刪除虛擬中心10 m外的點 | 接納更遠的已有點,也增加遠處稀疏/噪聲影響 | 截掉更多遠處輪廓 | 不提高硬體量程;還受地形輸出覆蓋和下游掃描範圍限制 |
use_inf |
true |
不適用,布林 | 根據實際功能需求開啟或設定 | 為沒有合格點的角度格選擇無回波表示 | 不適用 | 不適用 | True寫+∞;False寫range_max+inf_epsilon;沒有合格回波不等於確定空地 |
transform_tolerance |
0.01,原始碼預設;YAML未配置 |
s,變換查詢等待時間 | 通常保持當前值,不作為優先除錯項 | 點雲轉換時等待所需TF | 可等待更久,也可能延後處理 | 更快放棄缺失變換 | 當前傳給TF查詢的timeout;不是時間戳偏移或點雲同步誤差容差;空target_frame時不用 |
queue_size |
硬體併發執行緒數,原始碼預設;YAML未配置 | 訊息數,計數 | 通常保持當前值,不作為優先除錯項 | 設定點雲訂閱及TF訊息過濾佇列深度 | 可暫存更多訊息,可能增加積壓 | 快取更少,TF未就緒時更易丟訊息 | 預設隨機器而變;不是CPU工作執行緒數、釋出頻率或掃描點數 |
inf_epsilon |
1.0,原始碼預設;YAML未配置 |
m,超出量程的附加值 | 當前執行不使用這個引數,暫不調整 | use_inf=False時生成無回波哨兵值 | 啟用該分支後:哨兵值離range_max更遠 | 啟用該分支後:哨兵值更接近range_max | 當前use_inf=True,不參與結果;False時預設無回波為10+1=11 m;啟用時宜保持正附加值,避免落入有效量程 |
1.2.1.2.引數詳解
1.2.1.2.1.target_frame:掃描的中心和方向是底盤,不是雲臺或雷達
當前輸入 terrain_map_ext 的點座標在odom中;轉換使用輸入訊息時間戳對應的 base_footprint←odom,隨後以轉換後的x、y、z篩選。輸出 obstacle_scan.header.frame_id 為base_footprint,時間戳沿用輸入。
平面角度以該系+x為0,繞+z逆時針為正;距離以該系原點計算。它與 fake_vel_transform 最終按雲臺系表達的速度指令是兩條不同介面:這裡處理測距輪廓,沒有給底盤或雲臺下運動指令。
因此這是底盤原點上的虛擬二維掃描,不是MID360原點上的真實雷射束。MID360與底盤有安裝偏移,不能把range_min理解成“離雷達外殼0.3 m”。輸入是累積地形結果,含不同時間、不同高度的點;同一角度格只留最近的合格點,也不重新驗證從底盤虛擬中心到該點是否存在真實光路或遮擋。
正確的上游配準和機械TF應讓獨立雲臺yaw轉動後的靜態環境仍轉換到底盤方向;不能對這份點再手工重複加一個雲臺角。MID360掛在gimbal_yaw、隨yaw不隨pitch轉動,兩條odom關節固定的機械約定繼續適用。
base_footprint 這個名字不會自動把TF中的z、roll、pitch清零。當前sensor_scan_generation保留完整三維位姿,所以投影是該系的x-y平面;上坡時它是否真正與地面投影/預期水平面對應,需要核對參考系定義及上游姿態,不能僅憑名稱判斷。
若target_frame設空,原始碼不轉換點,直接在輸入系中計算。當前輸入為odom,這就變成以odom原點和方向作虛擬中心;機器人移動後,它不等價於仍以底盤為中心投影。
1.2.1.2.2.min_height、max_height 與兩項intensity:兩把不同的尺
高度視窗看 z_base_footprint,即點相對底盤原點、沿底盤z軸的座標;高差視窗看 intensity,即上游地形分析給出的“離估計地面多遠”。它們單位都是m,但基準不同。
假設上游已保留這些點,其他條件也滿足:
| 點在底盤系中的z | 上游給出的地形高差 | 本節點結果 |
|---|---|---|
| +0.2 m | 0.15 m | 兩個視窗都通過,參與二維投影 |
| +0.2 m | 0.06 m | 高差不足0.1 m,被刪 |
| -0.7 m | 0.2 m | 低於-0.5 m高度下界,被刪,即使高差足夠 |
所以遠處下坡點即使通過擴充套件地形節點隨距離放寬的視窗,仍可能在這裡被固定下界刪掉。上坡、下坡是否連續可見,要同時看target_frame的方向與高度視窗;disRatioZ 不會替本節點放寬範圍。
min_intensity=0.1 把10 cm作為進入二維障礙輪廓的高差下限,不是說車輛能跨10 cm臺階。降低它可能看見更低障礙,也可能把正常地面或坡面誤差畫進地圖;提高它會減少小高差輪廓,卻可能漏掉對實車危險的低障礙。遠場地形高差取絕對值,坡面較低一側也可能過門檻;近場目前忽略負高差,4 m交接處的差異仍會傳入掃描。
max_height=6.0 的視窗很寬。若高處橫梁等點通過上游和高差篩選,就會被壓到二維地圖中,即使車本來能從下面通過也可能形成障礙輪廓。應該根據底盤、雲臺活動包絡與懸空結構核對要保留的高度,不能把它當模型尺寸;同時也不能只調小上限而漏掉障礙唯一可見的部位。
當前正常地形輸出近場高差低於0.5 m、遠場低於1 m,因此max_intensity=2 m通常不額外刪點;這不表示引數沒被讀取。若換輸入、調整上游或出現其他標記點,效果會改變。高度與高差門檻使用“小於下界/大於上界則刪除”,邊界值可通過。
本地實現要求float型別的XYZ與intensity欄位;沒有intensity欄位的點雲不能直接套用。若接原始雷達點,intensity可能恢復為反射強度,這時0.1/2.0不再代表10 cm/2 m;不應僅換話題繼續沿用當前解釋。
1.2.1.2.3.angle_min、angle_max 與 angle_increment:整圈分成720格
當前角域約為-180°~+180°,增量約0.5°,原始碼生成720個距離項。角度是目標系中的 atan2(y,x),不是雷達垂直視場、安裝傾角或雲臺機械yaw範圍。
同一角度格內有多個合格點時,只保留水平距離最近的一個。例如,同方向2 m和5 m處各有點,掃描只留2 m;二維掃描不會同時表達它們的高度或多層結構。
0.5°在10 m處對應橫向約8.7 cm,在1 m處約8.7 mm;這裡只說明角度分格的幾何尺度,不是定位精度,也不保證這麼細的障礙都能看見。輸入點雲經過上游篩選與降取樣,調小角增量不會增加實際回波。
原始碼先以 ceil((angle_max-angle_min)/angle_increment) 建陣列,再計算下標。當前實現沒有檢查下標是否越界,而角度上界允許通過;當角域與增量恰好形成整數分格時,上界點存在越界路徑。當前近似整圈設定得到720項,不能據此證明其他角度組合的邊界安全;該缺口尚無執行觸發記錄。
1.2.1.2.4.range_min 與 range_max:底盤周圍的水平圓環
當前保留0.3~10.0 m水平距離的點,按 sqrt(x²+y²) 計算,不含z。相同x、y而高度不同的點,只要過高度/高差視窗,測距數值就一樣。
增大range_min可排掉更多近處回波,但也會漏掉車旁障礙;減小則可能帶入車體、雲臺或其他自車點。0.3 m圓形門檻不是完整車輛輪廓,距底盤原點更遠的自車回波仍可能留下,需要結合安裝位置與真實車體觀察。
增大range_max只允許更多已經存在的遠點,不能讓雷達看到更遠,也不能恢復上游刪點。當前slam_toolbox另配置min_laser_range=0.3、max_laser_range=10.0,兩級範圍應一起核對;下游引數用途另屬建圖引數塊。
1.2.1.2.5.scan_time:時間欄位,不是釋出頻率開關
LaserScan定義中scan_time表示掃描之間的時間間隔。這裡沒有測量實際間隔,只把引數0.05 s寫入訊息;輸出由輸入點雲驅動,實際週期取決於地形點雲、TF與計算過程。
time_increment 寫死為0,表示沒有逐束時間差;header.stamp 沿用輸入點雲時間。地形輸入含歷史點,不能把這個結果當成所有射線確實在同一時刻由物理二維雷達採集,也不能用scan_time代替運動補償或修復上游點時間單位。
實際釋出週期應按對應啟動模式測量後核對。修改scan_time只會改欄位,不會使10 Hz輸入變成20 Hz掃描,也不會給各個角度格補出真實取樣時間。
1.2.1.2.6.use_inf 與 inf_epsilon:無回波不等於確定空地
True先把每格距離設為+∞,再用最近合格點覆蓋;某格沒有合格點就保留∞。False則先設為range_max+inf_epsilon,當前預設組合是11 m,仍超出10 m有效量程。
“沒有合格點”可以來自真實無回波,也可以來自缺資料、遮擋、上游刪除、高度/高差過濾或角度格里沒有樣本;不能僅憑∞就判斷這條方向安全。下游怎樣處理無效/超量程值,應按對應掃描使用者的實現核對。
輸出只填ranges,不填LaserScan.intensities。這裡的兩項intensity引數用於挑選輸入點,並不把地形高差繼續作為掃描強度釋出。
1.2.1.2.7.預設TF引數與訂閱條件
transform_tolerance=0.01 s 在當前程式碼中作為轉換查詢的等待超時;它不是點雲和TF可以錯開0.01秒的補償量,也沒有把訊息時間戳前移/後移。TF訊息過濾器按輸入時間等待目標變換,queue_size控制其佇列以及點雲訂閱深度。TF轉換失敗的回撥直接返回,不用單位變換繼續生成掃描。
節點只有在scan輸出存在訂閱者時才訂閱cloud_in;最後一個掃描訂閱者消失後,會取消點雲訂閱。輸入和輸出均使用SensorDataQoS;相容的訂閱QoS與有效TF是收到掃描的前提。全是被過濾的點時,仍可釋出一幀全為無回波值的掃描,不能把“有掃描訊息”視為障礙輪廓正確。
預設queue_size取硬體併發執行緒數,適合先沿用;若訊息排隊或TF等待導致丟點,再按實際資料率和負載核對,不把佇列長度當成工作執行緒數。
1.2.1.2.8.啟動來源與驗證狀態
| 啟動方式 | 配置與輸入輸出來源 |
|---|---|
| 整套reality,slam=True | 實物nav2_params.yaml經slam_launch傳入;cloud_in重對映為terrain_map_ext,scan為obstacle_scan;target_frame=base_footprint |
| 整套simulation,slam=True | 模擬nav2_params.yaml,13項中僅use_sim_time=True不同;同樣的輸入輸出與目標系 |
| 整套slam=False | 進入已有地圖定位流程,不啟動這個轉換節點 |
| 包內sample_pointcloud_to_laserscan_launch.py | 示例點雲釋出器與靜態TF;目標系cloud、高度0~1 m、角域約±90°、scan_time=0.3333、距離0.45~4 m,未讀取整套YAML |
15項自定義引數在構造時讀取,沒有動態引數更新回撥;同名引數執行時改變不自動更新這些成員或重建TF過濾器。ROS標準use_sim_time由節點時鐘處理。當前use_inf=True使inf_epsilon不參與輸出,其他門檻仍按各自條件執行。
- 原始碼依據:
pointcloud_to_laserscan/src/pointcloud_to_laserscan_node.cpp;啟動接線見pb2025_nav_bringup/launch/slam_launch.py,LaserScan欄位定義見ROS2 sensor_msgs。 - 已有驗證範圍: 獨立Point-LIO靜止與短距離往返已有輸出記錄;該轉換節點的二維掃描、建圖輪廓、雲臺連續yaw和坡道投影尚未驗證。
- 實物待核實: 底盤原點與投影平面、IMU/雷達/底盤轉換、上下坡點是否被固定高度視窗截掉、低障礙與懸空結構的保留範圍、自車回波、角度覆蓋、實際掃描週期及無回波區域的下游處理。