第 5.5 节

terrain_analysis_ext(扩展远场地形与近远场结果合并)

作者:董佳辉

terrain_analysis_ext(扩展远场地形与近远场结果合并)

实车先看:坡道、落差与近远场衔接

这个节点给全局代价地图提供地形点。当前4 m内借用 terrain_analysis 的结果,4 m外才输出自己计算的结果。 因此,改本块的地面估计或高度筛选参数,不会同时改变近场;4 m是两种结果的交接距离,不是雷达最大量程。

实车上可能看到的现象先看哪些参数或条件怎样理解
上坡或下坡远处的地面消失lowerBoundZ、upperBoundZ、disRatioZ它们决定相对输入雷达位置,向上、向下能保留多大的高度范围;本节点的范围会随水平距离扩大
正常坡面、下坡被画成障碍useSorting、quantileZ,以及下游10 cm障碍门槛每一小片区域先选地面高度,再计算点离这个高度有多远;本节点远场对高低两侧都取绝对值,正常坡的较低侧也可能过门槛
同一障碍或坡面在4 m附近表现突然变化localTerrainMapRadius 与两个节点的规则差异近场与远场的地面格子、点密度、高度上限和负高度差处理不同;要检查交接处,不能只调一边
想排除顶棚、判断地面是否与车旁连得上checkTerrainConn 及其三个配套参数当前 False,专门的连接检查和顶棚筛选没有执行;ceilingFilteringThre=2.0 此时不起作用
人或障碍离开后,旧点没有在0.2秒消失decayTime 与两项 voxel…UpdateThre旧点只在缓存块更新时检查年龄;0.2秒不是准时删除的倒计时
以为 clearingDis=20.0 会自动清掉20 m外的点清图事件与 clearingDis它仅在外部触发时清除20 m内的自身缓存,平时不按这个半径清图

这些参数帮助系统看清地形,不能给出实车允许的坡度或台阶高度。车辆爬坡能力还取决于底盘、重心、附着力和实际测量;目前没有坡道或实物验证。

参数

ros__parameters(ROS节点参数)

参数表
terrain_analysis_ext:
  ros__parameters:
    scanVoxelSize: 0.1
    decayTime: 0.2
    noDecayDis: 0.0
    clearingDis: 20.0
    useSorting: true
    quantileZ: 0.2
    vehicleHeight: 1.0
    voxelPointUpdateThre: 100
    voxelTimeUpdateThre: 2.0
    lowerBoundZ: -1.5
    upperBoundZ: 0.5
    disRatioZ: 0.2
    checkTerrainConn: False
    terrainUnderVehicle: -0.75
    terrainConnThre: 0.5
    ceilingFilteringThre: 2.0
    localTerrainMapRadius: 4.0
参数名当前值单位实车处理建议作用调大效果调小效果生效条件/备注
scanVoxelSize0.1m,三维体素边长实物运行时重点观察,有问题再针对性调整合并小空间内的点,减少自身累计点云数量点通常更少,负担下降,细杆、小障碍的细节可能减少点通常更多,细节增加,负担上升应为正数;不改变写死的0.4 m地面格子;不对借入的近场点再次降采样
decayTime0.2s,输入点云时间实物运行时重点观察,有问题再针对性调整自身缓存更新时删除过期代表点历史保留更久,地面样本更多,旧障碍也可能残留更久历史更短,但远处点少时更容易缺数据仅缓存块更新时检查;受更新门槛与免衰减区影响;不检查借入近场点的年龄
noDecayDis0.0m,水平距离根据实际功能需求开启或设置指定自身缓存中不受年龄限制的区域免衰减区域扩大,近距离旧点保留更多区域缩小;0没有免衰减区条件为 d < noDecayDis;不能替代清图,不改变近场节点的历史规则
clearingDis20.0m,水平清图半径根据实际功能需求开启或设置清图事件发生时删除半径内的自身缓存点单次清图范围扩大单次清图范围缩小平时不执行;清的是半径内;cloud_clearing 消息会覆盖此变量;不清借入的近场结果
useSortingtrue不适用,布尔通常保持当前值,不作为优先调试项True 选排序分位高度作地面,False 选最低高度不适用不适用不是上坡开关;True 时使用 quantileZ;远场高差始终取绝对值
quantileZ0.2无量纲,分位比例实物运行时重点观察,有问题再针对性调整在排序后的高度中选地面样本地面估计通常升高,较高点的高差减小、较低点的高差可能增大地面估计通常降低,较高点的高差增大、较低点的高差可能减小仅 useSorting=True 时生效;宜在0~1内设置;不能保证调大就减少坡面障碍
vehicleHeight1.0m,相对估计地面的绝对高度差上实物前必须核对并正确配置保留自身远场中高度差小于1.0 m的点保留更多大高差点,也可能引入悬空结构更多大高差点被删,可能漏掉只在高处有回波的障碍不是整车模型高度或可爬台阶高度;不改变借入近场的0.5 m上限
voxelPointUpdateThre100点/缓存块,新入点计数通常保持当前值,不作为优先调试项新点达到门槛时更新该缓存块由点数触发的更新通常减少由点数触发的更新通常增加与时间门槛为“或”;不是地面最少样本数或发布频率
voxelTimeUpdateThre2.0s,输入点云时间通常保持当前值,不作为优先调试项距该缓存块上次更新足够久时触发更新低点密度块可能更久才清掉旧点低点密度块更新更及时,处理次数增加仍需新扫描驱动处理;点数达到门槛或清图可提前触发;不等于每2秒发布一次
lowerBoundZ-1.5m,相对输入位姿的 z 下界上实物前必须核对并正确配置限制向下保留的高度范围数值向上移,如-1.5改-1.0:更多低处地面、下坡点被删数值向下移,如-1.5改-2.0:保留更多低处点,也可能引入无关低层实际下界为 lowerBoundZ−disRatioZ×d;须核对雷达到地面高度及坐标方向
upperBoundZ0.5m,相对输入位姿的 z 上界上实物前必须核对并正确配置限制向上保留的高度范围保留更多高处坡面,也可能引入顶棚等结构更多高处点被删,上坡地面可能被截掉实际上界为 upperBoundZ+disRatioZ×d;不是障碍相对地面的高度上限
disRatioZ0.2无量纲,m/m实物运行时重点观察,有问题再针对性调整按水平距离同时放宽上下高度界远处允许更大上下落差,也会接纳更多无关高度点远处高度范围收窄,坡面可能缺失本节点从入缓存、地面估计到自身远场输出都使用扩展范围;与近场节点不同;不是最大安全坡度
checkTerrainConnFalse不适用,布尔根据实际功能需求开启或设置是否只保留与中心估计地面连接上的自身远场点不适用不适用当前关闭;开启会使用下面三项;不对借入近场结果重新检查
terrainUnderVehicle-0.75m,相对输入位姿的假定地面 z 偏置当前运行不使用这个参数,暂不调整开启连接检查且中心缺地面样本时,补一个起始地面高度启用后:假定地面更高、更接近输入原点启用后:假定地面更低当前 checkTerrainConn=False;有中心样本时也不用;若启用,须测量原点到地面的实际关系
terrainConnThre0.5m,两片估计地面的高度差当前运行不使用这个参数,暂不调整开启连接检查后,判断候选地面能否接上启用后:更容易连接,也可能跨过真实台阶或缺口启用后:更容易断开,正常坡面也可能被排除当前关闭;判断高度差严格小于门槛;0.5不表示车能爬50 cm台阶
ceilingFilteringThre2.0m,两片估计地面的绝对高度差当前运行不使用这个参数,暂不调整开启连接检查后,标记高度相差过大的候选区域启用后:较少候选被标记排除启用后:较多候选被标记排除,也可能误排低处地面当前关闭;用绝对差,较低地面也可能命中;不是车顶净空或距雷达2 m的顶棚线
localTerrainMapRadius4.0m,相对输入位置的水平距离实物运行时重点观察,有问题再针对性调整划分借入近场结果与自身远场结果更多范围使用近场结果,需要近场有足够覆盖更近处开始使用自身较粗的结果d≤4 m 借入、d>4 m 自算;近场缺点时不会用自身结果补洞;重点观察交接处
参数详解
输入、输出和高度基准
方向话题本节点怎样使用
订阅lidar_odometry取最近收到的位置作为距离与高度的基准;预期是 odom 中的雷达位姿
订阅registered_scan输入 odom 中的配准点云,用于累计、选地面和计算远场高差
订阅terrain_map保存近场节点最近一帧结果,取其中4 m内的点直接合入输出
订阅joy、cloud_clearing触发自身缓存清图;后者还提供清图半径
发布terrain_map_ext合并结果,参考系写死为 odom,时间标为当前输入扫描时间;自身远场的 intensity 是绝对高度差,单位 m

自身远场保留点的 x、y、z,不把点移到地面上;改写的是 intensity,它已经不是雷达反射强度。当前全局代价地图的 IntensityVoxelLayer 使用本输出,并以 min_obstacle_intensity=0.1、max_obstacle_intensity=2.0 筛选高度差。达到10 cm只是满足其中一项条件,还要通过坐标高度、距离等筛选才可能成为障碍。

下文的“高于/低于雷达”都指点的 odom z 减去输入位姿 z;距离指 odom 的水平距离。源码没有在这里查询雷达→底盘 TF,也没有按云台姿态重新定义竖直方向。上游 loam_interface 把输入当雷达位姿,而 Point-LIO 原始输出是内部 IMU 位姿;此前记录的 IMU→雷达转换缺口仍会影响本块的高度基准,不能靠扩大高度范围代替修正接口。

lowerBoundZ、upperBoundZ 与 disRatioZ:能不能看到远处上下坡

这三项先决定坡点有没有资格留下,再谈坡会不会被当成障碍。当前上下边界相对输入位姿,并随距离扩大:

点离输入位置的水平距离允许的相对高度范围,不含边界
0 m-1.5~+0.5 m
5 m-2.5~+1.5 m
10 m-3.5~+2.5 m

比如5 m外的下坡点比输入原点低2.0 m,能通过当前窗口;低3.0 m则会被删。5 m外的上坡点高1.0 m能通过,高2.0 m则会被删。这里只举高度筛选,仍需满足后面的输出条件。

所以:下坡地面缺失,检查下界;上坡地面缺失,检查上界;越远越缺,连同距离放宽比例一起检查。 下界的“调大”是数值变大,例如-1.5到-1.0,反而缩小向下保留范围。

与上一块不同,扩展节点在入缓存、缓存更新、选地面和自身远场输出时,都使用这个随距离扩大的窗口;没有在最终输出时退回固定上下界。disRatioZ=0.2 表示每增加1 m水平距离,上下各放宽0.2 m,不代表允许的坡度或坡面识别结果。

上实物前应先核对原点离地高度、odom 竖直方向和位姿转换。窗口过窄会丢坡面,过宽会引入顶棚或其他楼层;是否成为障碍还取决于局部地面估计及后续筛选。当前不据这些数值直接修改重力方向或安装外参。

useSorting 与 quantileZ:正常坡为什么也可能像障碍

扩展节点把水平地面分成写死的0.4 m格子,每格收集附近高度,选一个“这片区域的地面高度”。当前先排序,再取 floor(0.2×样本数) 处的高度;10个样本取从低到高第3个。False 则取最低高度。格子和邻域内有坡、障碍或离群点时,这个代表高度未必等于每个点下面的真实地面。

本节点自己的远场始终计算 abs(点高度−估计地面高度),没有 considerDrop 开关。 一个点比估计地面高15 cm,或低15 cm,都会输出0.15 m的高度差;满足其他条件时,两者都可能达到全局代价地图的10 cm障碍门槛。

这就是下坡尤其要看的地方:正常坡的较低侧,可能只是低于这一小片的代表地面,并不是真正的坑。反过来,真正坑洼只有被雷达看到且留下有效回波,才可能通过这个高度差表现出来;没有回波的断崖不因此自动得到可靠识别。扩展节点也没有近场那种 noDataObstacle 合成障碍功能,没有点的区域如何影响规划,还取决于下游的未知区域设置。

把 quantileZ 调大,通常会抬高代表地面:较高点的高差可能减小,较低点的高差却可能增大。因此不能照搬“调大就更容易上下坡”。应一起看正常坡面、小台阶和低障碍,确认地面估计是否偏高或偏低。这里没有正负高差相加抵消,也没有允许上坡/禁止下坡的专用开关。

vehicleHeight:哪些障碍点能进入远场输出

当前自身远场只保留绝对高差 h<1.0 m 的点,1.0 m边界不保留。这个值没有更改机器人尺寸,也不表示能跨越1 m台阶。

例如:障碍有离地20 cm的有效回波,可能进入输出;若它只有离地1.2 m处的回波,而“地面高度”选得正确,这些回波会被本项删掉。调小可能漏掉部分障碍,调大可能把悬空横梁等结构引入结果。应结合真实车辆需要避让的高度、雷达能看见的部位和地面估计核对,不能直接把名字当整车高度填入。

与下游10 cm门槛共同作用时,自身远场进入障碍筛选的高差范围为 0.1~不足1.0 m,仍需通过其他条件。4 m内借入的近场点沿用近场当前0.5 m上限,不受本项重新筛选。

localTerrainMapRadius:为什么4 m附近要单独看

当前以输入里程计位置为中心:d≤4 m 直接复制 terrain_map 点;d>4 m 使用扩展节点自算点。近场点不会再次套用本节点的 vehicleHeight、排序、高度窗口、衰减或连接检查。

两侧当前有这些区别:

处理方式4 m内借入的近场4 m外自身计算
自身点云降采样尺度0.05 m0.1 m
写死的地面格子边长0.2 m0.4 m
相对估计地面的正常输出范围非负、低于0.5 m绝对值、低于1.0 m
低于估计地面的点当前 considerDrop=False,被过滤取绝对值,可能进入输出
最终相对输入高度窗口固定上下界随距离放宽

因此,同一坡面或物体随着车辆接近,跨过4 m时可能改变高度差或可见点;这是需要观察的源码差异,目前没有确认发生实际交接故障。扩大半径会借用更多近场结果,缩小会更早使用较粗远场;它不改变代价地图大小、雷达量程或车辆半径。

还有两个接口前提:近场没有点,扩展节点不会用自己的4 m内计算补洞;近场停止更新,源码也不检查其年龄。 它会继续合入最近收到的近场结果,并把合并消息标成当前扫描时间。不能仅凭 terrain_map_ext 的时间戳新,就断定其中所有点都新。

checkTerrainConn 及三个配套参数:当前先知道没有生效

当前 checkTerrainConn=False,因此 terrainUnderVehicle、terrainConnThre、ceilingFilteringThre 都不影响输出。其他高度筛选仍在执行;这里只是专门的连接检查与顶棚筛选关闭。

若以后考虑启用,它从输入位置附近的地面出发,尝试把高度接近的地面区域连起来;自身远场只输出连上的区域。三项含义是:

  • terrainUnderVehicle=-0.75 m:仅当中心格没有地面样本时,假定地面在输入原点下方0.75 m,作为检查起点。若使用前提成立,应测量该原点到地面的关系;它不是底盘离地间隙,也不是直接读取的实车高度。
  • terrainConnThre=0.5 m:候选两片地面的高度差小于0.5 m才接上。过小可能断开正常坡,过大可能接上真实台阶或跨过缺口;不是允许爬50 cm台阶。
  • ceilingFilteringThre=2.0 m:连接检查中,高度相差超过2.0 m的候选可被标记排除。源码用绝对差,远低于当前地面的区域也可能命中;不是“高于雷达2 m就删”的顶棚线,也不是车顶净空。

源码一次能比较横纵各±10个地面格,即各±4 m,并非只检查紧贴的小格;中间是否连续有地面没有逐段证明。因此这个检查也不能直接当作车辆可通行性或可靠断崖判据。当前关闭,无需优先调整这三项;启用的适用性要另行验证。

scanVoxelSize、decayTime 与更新门槛:细障碍和旧点

scanVoxelSize=0.1 m 是自身累计点云的三维降采样尺度,不是地面格子大小,也不保证10 cm以上障碍都能看见。细杆、障碍边缘和远处稀疏回波应重点观察;调小能保留更多细节,但点数与计算量会上升。

历史缓存按写死的2 m水平分块管理。每块新入点达到100,或距上次更新达到2.0秒,或发生清图,才重新降采样并检查年龄;这些步骤仍由新扫描驱动。decayTime=0.2 s 是检查时使用的过期门槛,不能覆盖这个触发条件。

所以,近处点密集的块可能很快更新,远处点少的块可能等到时间门槛,旧点保留超过0.2秒。没有新扫描时也不会单靠计时继续处理。noDecayDis=0.0 没有免衰减区域;以后调大,只让指定范围的自身历史绕过年龄检查,不会自动恢复近场缺失的输出。

这两个更新门槛不是发布频率,源码100 Hz循环也不等于每秒输出100帧。先沿用门槛;若实物发现旧障碍残留、地面缺点或负担过大,再结合点密度、衰减时间一起判断。扩展节点没有近场那组 clearDyObs 动态筛选参数,不能把它当成同一套清理算法。

clearingDis:按事件清半径内,且只清自己

当前20 m表示收到清图事件后,删除水平距离小于20 m的自身缓存点。平时没有自动执行,也不是最大输出范围。

joy 第6个按钮可触发;cloud_clearing 的 Float32 消息还会用消息数值覆盖半径。近场节点对应话题是 map_clearing,二者不同。扩展节点清图后仍会借入 terrain_map 的近场结果,因此近场点可以继续出现在合并输出中;不能把清自身缓存理解为清掉整套地图。本轮没有发送清图事件。

启动来源与当前验证范围
启动方式来源要注意的区别
整套 reality launch默认 pb2025_nav_bringup/config/reality/nav2_params.yaml,可由 params_file 指定;经 navigation_launch.py 传入节点名设为 terrain_analysis_ext,匹配本表17项
整套 simulation launch默认 pb2025_nav_bringup/config/simulation/nav2_params.yaml,同样经导航 launch 传入当前这17项与实物 YAML 相同,不能因此认定实物效果相同
包内独立 terrain_analysis_ext.launchXML 内直接提供参数,不读取上面整套 YAML例如 decayTime=4.0、quantileZ=0.1、vehicleHeight=1.5、lowerBoundZ=-2.5,与本表不同
直接运行可执行文件且不传参数C++ 声明时的默认值例如 decayTime=10.0、useSorting=False、checkTerrainConn=True;不会自动套用本表

整套导航 launch 会同时安排两个地形分析节点,扩展节点本身始终是独立进程,不随导航组件开关变成组件。本轮在 ysu_ros_humble 中只查询环境与文件,确认包路径、安装后的独立 launch、导航 launch 和两份 YAML 与当前源码文件一致;没有启动节点或读取运行节点的有效参数。

17项都在启动时声明和读取,没有动态参数更新回调;运行时仅写同名参数不会更新算法中的成员变量。clearingDis 可由清图消息改变量,这与重新读取 ROS 参数是两回事。衰减计时使用输入点云时间戳,不是电脑墙钟;本块未列 use_sim_time,也不能据此证明全链路时钟或点内时间单位已经正确。

输入里程计与扫描没有时间配对或插值,也没有等待有效里程计的保护;近场点云同样没有同步与新鲜度检查。节点直接使用输入坐标,未校验参考系,最后却固定写 odom。这些前提对坡面高度和距离分区都有影响。

  • 源码能确认: 17项读取与当前门控、随距离扩大的高度窗口、远场绝对高差、4 m近远场合并、衰减与清图触发方式,以及三个未生效参数;上面的行为解释按当前源码复核。
  • 仿真已观察: 2026-10-08 的静止和约20 cm往返只覆盖独立 Point-LIO 输出,没有验证扩展地形、上下坡、坑洼、顶棚、4 m交接或全局代价地图。
  • 必须实物核实: 输入原点到地面的高度、内部 IMU→雷达→底盘关系、odom 竖直方向、坡面及低障碍的回波密度、下坡与真实落差是否被正确区分、交接处一致性和障碍离开后的残留。MID360 随实际 yaw、不随实际 pitch 转动的机械约定继续保留;本轮未作运行测试。

源码位置:src/pb2025_sentry_nav/terrain_analysis_ext/src/terrainAnalysisExt.cpp;启动来源:src/pb2025_sentry_nav/pb2025_nav_bringup/launch/navigation_launch.py 和两份 nav2_params.yaml;下游高度差筛选:src/pb2025_sentry_nav/pb_nav2_plugins/src/layers/intensity_voxel_layer.cpp。本块仅更新日志解释,工程源码、配置和参数值均保留。