Nav2 Inflation Layer 膨胀层公式、内切半径与 RViz 颜色理解
适合场景:ROS2 Nav2 局部规划 / DWB / MPPI 调参,尤其是想搞清楚
inflation_radius和cost_scaling_factor到底怎么影响避障行为。
1. Costmap 里的 254、253、0 分别是什么?
Nav2 costmap 内部使用 0 ~ 255 的 unsigned char 数值表示栅格代价:
| 内部 cost 值 | 名称 | 含义 |
|---|---|---|
0 |
FREE_SPACE |
完全自由空间 |
1 ~ 252 |
inflated cost |
膨胀层产生的渐变代价 |
253 |
INSCRIBED_INFLATED_OBSTACLE |
距离障碍物小于等于机器人内切半径的区域,极危险 |
254 |
LETHAL_OBSTACLE |
致命障碍物,也就是障碍物所在格子 |
255 |
NO_INFORMATION |
未知区域 |
可以简单理解为:
254:障碍物本体所在格子,不能碰
253:离障碍物非常近,机器人中心如果进入这个区域,footprint 很可能已经撞到或擦到障碍物
1~252:膨胀代价区,越靠近障碍物 cost 越高
0:自由空间
注意:253 不是一个独立插件,也不是传感器直接打出来的障碍物,而是 Inflation Layer 根据机器人 footprint / robot_radius 算出来的高危险区。
2. Inflation Layer 的核心公式
Nav2 Inflation Layer 的核心计算逻辑可以简化为:
if (distance == 0) {
cost = LETHAL_OBSTACLE; // 254
} else if (distance * resolution <= inscribed_radius) {
cost = INSCRIBED_INFLATED_OBSTACLE; // 253
} else {
cost = (INSCRIBED_INFLATED_OBSTACLE - 1)
* exp(-cost_scaling_factor * (distance * resolution - inscribed_radius));
}
换成数学公式就是:
如果 d = 0:
cost = 254
如果 0 < d <= r_inscribed:
cost = 253
如果 r_inscribed < d <= inflation_radius:
cost = 252 × exp(-k × (d - r_inscribed))
如果 d > inflation_radius:
cost = 0
其中:
| 符号 | 含义 |
|---|---|
d |
当前栅格到最近 lethal obstacle 栅格的距离,单位是米 |
distance |
源码里的距离,单位是 costmap cell,不是米 |
resolution |
costmap 分辨率,单位是 m/cell,例如 0.05 表示每格 5cm |
distance * resolution |
把 cell 距离转换成米 |
r_inscribed |
机器人内切半径,Nav2 根据 footprint 或 robot_radius 自动计算 |
k |
cost_scaling_factor,控制代价衰减速度 |
inflation_radius |
膨胀影响的最大半径 |
3. distance 到底是谁到谁的距离?
这是最容易误解的地方。
源码里的 distance 不是:
障碍物到 base_footprint 的距离
障碍物到机器人 footprint 边框的距离
雷达到障碍物的距离
它实际是:
当前 costmap 栅格中心
到
最近 lethal obstacle 栅格中心
之间的欧氏距离
并且源码里这个 distance 一开始是以 cell 为单位的。
例如 costmap 分辨率是:
resolution: 0.05 # 5cm/cell
如果某个栅格离障碍物格子 10 个 cell:
distance = 10
resolution = 0.05 m/cell
实际距离 d = distance × resolution = 10 × 0.05 = 0.5m
所以源码里才会写:
distance * resolution <= inscribed_radius
意思是:
当前栅格到障碍物格子的实际距离 <= 机器人内切半径
如果成立,就把这个格子标成 253。
4. inscribed_radius 内切半径从哪里来?
inscribed_radius 不是你直接在 Inflation Layer 里手动设置的。
Nav2 会根据 costmap 的机器人形状自动算:
footprint: "[[0.45, 0.35], [0.45, -0.35], [-0.45, -0.35], [-0.45, 0.35]]"
或者:
robot_radius: 0.35
如果你配置的是 footprint,Nav2 会计算:
inscribed_radius = base_footprint 原点到 footprint 边或顶点的最小距离
circumscribed_radius = base_footprint 原点到 footprint 边或顶点的最大距离
对一个中心在 base_footprint 的矩形车体:
footprint: "[[L/2, W/2], [L/2, -W/2], [-L/2, -W/2], [-L/2, W/2]]"
那么:
inscribed_radius = min(L/2, W/2)
circumscribed_radius = sqrt((L/2)^2 + (W/2)^2)
举例:
车长 L = 0.90m
车宽 W = 0.70m
inscribed_radius = min(0.45, 0.35) = 0.35m
circumscribed_radius = sqrt(0.45² + 0.35²) ≈ 0.57m
工程含义:
inscribed_radius 内的区域是非常危险区域;
如果机器人中心进入距离障碍物小于内切半径的位置,机器人 footprint 很可能已经碰到障碍物。
注意:如果你的 base_footprint 原点不在车体几何中心,或者 footprint 点写错,Nav2 算出来的内切/外接半径也会跟着错。
5. inflation_radius 和 cost_scaling_factor 分别控制什么?
这两个参数作用不同:
| 参数 | 控制什么 | 直观理解 |
|---|---|---|
inflation_radius |
膨胀影响范围最大到多远 | 影响范围 |
cost_scaling_factor |
这个范围内 cost 衰减多快 | 衰减速度 |
不要误解成:
inflation_radius = 1.0m,所以 1m 内都是高代价
正确理解是:
1m 内会产生指数衰减代价;
越靠近障碍物 cost 越高,越远 cost 越低;
cost_scaling_factor 越大,下降越快。
6. 例子:inflation_radius = 1.0m,inscribed_radius = 0.30m
假设:
inflation_radius: 1.0
inscribed_radius: 0.30
不同 cost_scaling_factor 下,距离障碍物不同位置的内部 cost 大概如下:
| 距离障碍物 | k=1 | k=2 | k=3 | k=5 | k=10 |
|---|---|---|---|---|---|
| 0.0m | 254 | 254 | 254 | 254 | 254 |
| 0.1m | 253 | 253 | 253 | 253 | 253 |
| 0.3m | 253 | 253 | 253 | 253 | 253 |
| 0.4m | 228 | 206 | 186 | 152 | 92 |
| 0.5m | 206 | 168 | 138 | 92 | 34 |
| 0.6m | 186 | 138 | 102 | 56 | 12 |
| 0.8m | 152 | 92 | 56 | 20 | 1 |
| 1.0m | 125 | 62 | 30 | 7 | 0 |
| 1.2m | 0 | 0 | 0 | 0 | 0 |
可以看到:
k 越小,代价下降越慢,远处也还有明显 cost,车更不容易贴障碍;
k 越大,代价下降越快,只有障碍旁边很小一圈有明显 cost。
所以如果你想让车更倾向走通道中间,一般不要把 cost_scaling_factor 设得太大。
7. 如何根据目标 cost 反推 cost_scaling_factor?
公式:
cost = 252 × exp(-k × (d - r_inscribed))
反推:
k = -ln(cost / 252) / (d - r_inscribed)
例如:
inscribed_radius = 0.30m
希望 d = 1.00m 时 cost 约为 80
那么:
k = -ln(80 / 252) / (1.00 - 0.30)
≈ 1.64
参考表:
| 希望 1.0m 处 cost 约为 | 对应 cost_scaling_factor,假设 inscribed_radius=0.30m |
|---|---|
| 150 | 0.74 |
| 100 | 1.32 |
| 80 | 1.64 |
| 50 | 2.31 |
| 20 | 3.62 |
8. RViz 里的颜色代表什么?
RViz 颜色显示的是 costmap 的可视化结果,不同显示模式/主题可能略有差异,但一般可以这样理解:
| RViz 颜色 | 大概含义 | 内部 cost |
|---|---|---|
| 黑色 / 透明 | free space | 0 |
| 蓝色 | 低代价膨胀区 | 较低的 1~252 |
| 红色 / 橙色 | 高代价膨胀区 | 较高的 1~252 |
| 青色 | inscribed inflated obstacle,内切半径危险区 | 253 |
| 紫色 / 粉紫色 | lethal obstacle,障碍物本体 | 254 |
| 灰蓝 / 灰绿 | unknown | 255 |
调参时不要只看颜色“好不好看”,重点看:
障碍物周围是不是有连续渐变?
通道中间的 cost 是否明显低于贴边位置?
膨胀区有没有把窄通道完全堵死?
253/254 区域是否只在真正危险区域附近?
如果想看原始代价值,可以看 raw costmap:
ros2 topic echo /local_costmap/costmap_raw
或者写一个小脚本订阅 /local_costmap/costmap_raw,取某个格子的 cost 值。
9. 针对园区巡检车的调参思路
如果你的车比较大,且目标是安全优先,可以先从下面的方向试:
local_costmap:
local_costmap:
ros__parameters:
footprint: "[[0.45, 0.35], [0.45, -0.35], [-0.45, -0.35], [-0.45, 0.35]]"
footprint_padding: 0.05
inflation_layer:
plugin: "nav2_costmap_2d::InflationLayer"
inflation_radius: 1.0
cost_scaling_factor: 2.0
调参顺序建议:
- 先写准
footprint。 - 确认 RViz 里 footprint 和真实车宽一致。
- 设置一个偏保守的
inflation_radius,比如0.8 ~ 1.2m。 - 把
cost_scaling_factor先设在1.5 ~ 3.0。 - 看车是否更愿意远离障碍物。
- 如果窄路过不去,减小
inflation_radius或增大cost_scaling_factor。 - 如果还贴障碍,增大
inflation_radius或减小cost_scaling_factor。
经验理解:
太贴障碍:inflation_radius 增大,或 cost_scaling_factor 减小
太保守、窄路过不去:inflation_radius 减小,或 cost_scaling_factor 增大
10. 一句话总结
inflation_radius 决定“影响多远”;
cost_scaling_factor 决定“掉得多快”;
inscribed_radius 由 footprint / robot_radius 自动计算;
distance 是 costmap 栅格到最近障碍物栅格的距离,不是机器人到障碍物的实时距离;
253 是内切半径危险区,254 是障碍物本体。
参考资料
- Nav2 Inflation Layer Parameters: https://docs.nav2.org/configuration/packages/costmap-plugins/inflation.html
- Nav2 Inflation Layer 源码:
computeCost():https://api.nav2.org/nav2-rolling/html/inflation__layer_8hpp_source.html - Nav2 Footprint 源码:
calculateMinAndMaxDistances():https://api.nav2.org/nav2-humble/html/footprint_8cpp_source.html - Nav2 Costmap 2D 配置文档:https://docs.nav2.org/configuration/packages/configuring-costmaps.html
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)