参数调优指南
本指南旨在帮助用户调优导航系统。配置指南 固然是 Nav2 全部参数的完整清单,但对于如何利用其中最重要的参数来调优系统,并未提供太多实操细节。本指南的目标是在首次设置(见环境配置指南)的基础上,就系统搭建提供更多建议。本指南不可能涵盖所有参数(请务必查阅你所关注软件包的配置指南),但会提供一些实用的提示和技巧。
本调优指南仍在持续完善中。如果你发现有遗漏的内容,欢迎提交工单(ticket)或拉取请求(pull request)来分享经验。这是由 Nav2 用户和维护者共同维护的开源项目,欢迎将你的知识传递下去。
膨胀势场(Inflation Potential Fields)
Section titled “膨胀势场(Inflation Potential Fields)”许多用户和维护者所使用的导航配置文件,其实都没有充分发挥膨胀层(inflation layer)的真正作用。诚然,你可以在墙壁周围简单地膨胀一个小半径来为关键碰撞设定权重,但膨胀层的真正价值在于在整个地图上构建一个均匀的势场(potential field)。
一些最流行的 ROS Navigation / Nav2 调优指南甚至专门指出了这一点——在施加内切代价(inscribed costs)之后,在整个地图宽度上创建一个平缓的势场会带来显著收益。然而,很少有用户在实践中这样做。
这种做法实际上会导致 NavFn、Theta* 和 Smac Planner 生成的路径不是最优的。这些规划器真正需要的不是一个宽阔的 0 代价空间,而是一个平滑的势场,这样才能使路径保持在空间的中间位置,并更好地应对附近的动态障碍物。在搜索算法触及引起膨胀的障碍物之前,势场就已经将搜索引导向自由空间(freespace),从而使规划器尽可能为障碍物留出足够的避让空间。
因此,维护者以及 ROS 中所有其他基于代价的搜索规划器都建议:增大膨胀层的代价缩放(cost scale)和半径,以便在整个地图上生成充分、平滑的势场。对于非常大的开阔空间,中间存在 0 代价区域是可以接受的,但对于走廊、通道等类似场景,请创建平滑的势场以获得最佳性能。
机器人足迹(Footprint)与半径
Section titled “机器人足迹(Footprint)与半径”Nav2 允许用户以两种方式指定机器人的形状:几何 footprint(足迹),或包络机器人的外接圆半径。在 ROS 1 中,使用机器人半径近似值通常是可以接受的,因为全局规划算法不使用它,而局部规划器和代价地图的设置中已内置了圆形假设。
然而,在 Nav2 中,我们有多个规划和控制算法会使用完整的 SE2 足迹。如果你的机器人不是圆形的,建议向规划器和控制器提供机器人实际的几何足迹,这样它们就能规划出进入更狭窄空间的轨迹。例如,对于一个细长的机器人,圆形假设会导致机器人无法规划进入仅比其宽度略宽的空间,因为按长度方向它放不进去。
运动学可行的规划器(例如 Smac Hybrid-A*、Smac State Lattice)在获得实际足迹后,将使用 SE2 足迹进行碰撞检查,以生成运动学可行的规划。截至 2021 年 12 月,所有控制器插件都支持完整的足迹碰撞检查,以确保路径跟踪的安全性。如果你提供了机器人足迹,它将被用于验证轨迹的有效性——建议你这样做,它可以避免许多本可轻松避免的「机器人卡死」情况。
如果你的机器人确实是圆形的,请继续使用 robot_radius 参数。非圆形机器人使用半径的三个合理场景:
- 机器人相对于环境非常小(例如仓库中的遥控车)
- 机器人算力非常有限,使用 SE2 足迹检查会增加过多计算负担(例如嵌入式微处理器)
- 如果你计划使用全向(holonomic)规划器(例如 Theta*、Smac 2D-A* 或 NavFn),可以继续使用圆形足迹,因为这些规划器不是运动学可行的,本身也不使用 SE2 足迹。
原地旋转行为(Rotate in Place)
Section titled “原地旋转行为(Rotate in Place)”使用旋转 Shim(Rotation Shim)控制器时,机器人在开始跟踪全向路径之前会先原地旋转到大致朝向。这使得开发者可以将控制器插件专注于路径跟踪优化,同时开箱即用地获得干净的旋转行为。
之所以添加此功能,是因为某些现有控制器存在局限:为某个任务调优控制器可能使其变得僵硬,或者算法在处理全向路径时根本不会原地旋转(即使这通常是期望的行为)。当机器人初始朝向与路径朝向差异较大时,结果往往是笨拙、磕磕绊绊或甩来甩去的旋转。为控制器提供一个更好的起始点来开始跟踪路径,使得控制器调优变得容易得多,也能带来更直观的视觉效果。
注意:如果使用非全向、运动学可行的规划器(例如 Smac Hybrid-A*、Smac State Lattice),则无需此行为优化。这类规划器会生成考虑机器人起始朝向的规划,不需要任何额外的旋转行为。
此行为最适用于:
- 可以原地旋转的机器人,例如差速(differential)和全向(omnidirectional)机器人。
- 当开始跟踪一条与机器人当前朝向差异显著的新路径时,需要原地旋转;或者当你为特定任务调优控制器而导致紧凑旋转变得困难时。
规划器插件选择
Section titled “规划器插件选择”Nav2 开箱即用地提供了许多规划插件。对于首次设置,请参阅选择算法(select_algorithm)一节,了解 Nav2 内算法风格的更详细分类;并参阅插件(Plugins)一节,了解当前可用插件的完整清单(该清单可能随时间更新)。
总体而言,下表可作为针对不同机器人底盘选择规划插件的参考:
| 插件名称 | 支持的机器人类型 |
|---|---|
| NavFn Planner | 圆形差速(Circular Differential)、圆形全向(Circular Omnidirectional) |
| Smac Planner 2D | 圆形差速(Circular Differential)、圆形全向(Circular Omnidirectional) |
| Theta Star Planner | 圆形差速(Circular Differential)、圆形全向(Circular Omnidirectional) |
| Smac Hybrid-A* Planner | 非圆形或圆形阿克曼(Ackermann)、非圆形或圆形腿式(Legged) |
| Smac Lattice Planner | 非圆形差速(Non-circular Differential)、非圆形全向(Non-circular Omnidirectional)、任意形状(Arbitrary) |
如果你使用的是算力非常有限的非圆形机器人,那么评估使用全向规划器的收益可能是值得的。维护者建议先尝试适合你平台的更高级算法之一,如有需要再降级到较简单的规划器。运动学可行的规划器运行时间通常与全向规划器相当(有时甚至更快),不要因为它们更先进就认为性能更差。
由于规划器的选择主要由机器人类型决定,上表准确地反映了维护者给用户的建议。在圆形机器人范畴内,规划算法的选择取决于应用和期望的行为。NavFn 通常会生成宽阔、大弧度的曲线;Theta* 偏好直线,并且支持任意角度的直线;而 Smac 2D 本质上是一种带代价感知惩罚的经典 A* 算法。
注意:这些只是社区提供的默认和可用插件。对于特定的应用/平台,你也可以选择不使用其中任何一个,而是创建自己的插件,这正是 Nav2 框架的意图。更多细节请参阅编写新的规划器插件教程。如果你愿意将这些工作回馈给社区,请提交工单或联系维护者,他们会很高兴收到你的反馈。
控制器插件选择
Section titled “控制器插件选择”Nav2 开箱即用地提供了许多控制器插件。对于首次设置,请参阅选择算法(select_algorithm)一节,了解 Nav2 内算法风格的更详细分类;并参阅插件(Plugins)一节,了解当前可用插件的完整清单(该清单可能随时间更新)。
总体而言,下表是对不同机器人底盘可用控制器插件的概览:
| 插件名称 | 支持的机器人类型 | 任务 |
|---|---|---|
| DWB controller | 差速(Differential)、全向(Omnidirectional) | 动态障碍物避让 |
| MPPI Controller | 差速(Differential)、全向(Omnidirectional)、阿克曼(Ackermann)、腿式(Legged) | 动态障碍物避让 |
| RPP controller | 差速(Differential)、阿克曼(Ackermann)、腿式(Legged) | 精确路径跟踪 |
| Rotation Shim | 差速(Differential)、全向(Omnidirectional) | 旋转至大致朝向 |
| VP controller | 差速(Differential)、阿克曼(Ackermann)、腿式(Legged) | 高速路径跟踪 |
上述所有控制器在配置上都能处理圆形和任意形状的机器人。
受控纯追踪(Regulated Pure Pursuit,RPP)擅长精确路径跟踪,通常与运动学可行的规划器之一(例如 State Lattice、Hybrid-A* 等)搭配使用,因为已知这些路径在严格的物理约束下是可行驶的。不过,它也可以应用于差速驱动机器人,这类机器人可以轻松原地转动以匹配任何全向路径。如果你只是想让机器人相当精确地跟随路径,而不做任何动态障碍物避让或偏离,这就是首选插件。它简单而几何化,并且在附近存在障碍物以及急转弯时会使机器人减速。
DWB 和 MPPI 都是会跟踪路径的选项,但如果存在动态障碍物,它们也会偏离路径(以避开障碍物)。DWB 通过在一组评价函数(critics)上对多条轨迹进行评分来实现这一点。这些轨迹也是通过可替换的插件生成的,但开箱即用地支持在有效速度和加速度限制内的全向(Omni)和差速(Diff)机器人类型。这些评价函数是可以运行时选择的插件,包含可根据需要调优的权重,以产生期望的行为,例如最小化路径距离、最小化到目标或目标朝向的距离,以及其他可以设计的动作惩罚。这确实需要针对特定平台、应用和期望行为进行一些调优,但将 DWB 调优到几乎能出色地完成任何单一任务是可以做到的。
另一方面,MPPI 实现了基于优化的方法,使用先前最优轨迹的随机扰动样本来最大化一组基于插件的目标函数。在这方面它与 DWB 类似,但 MPPI 是一种远比 DWB 更现代、更先进的技术,凭借基于优化的轨迹规划,它能够处理环境中的动态对象并产生智能行为,而不是像 DWB 那样采用恒定动作模型。不过 MPPI 确实有中等偏高的计算成本,但非常推荐使用它,并且由于其强大能力,它已获得了大量的开发资源和关注。它通常在开箱即用时就能工作得相当好,但要调优特定行为,你可能需要重新调优一些参数。该包的 README.md 文件包含如何有效调优它的详细信息。
旋转 Shim 插件(Rotation Shim Plugin)帮助 TEB 和 DWB(以及其他)等插件在开始跟踪路径之前,让机器人原地旋转到新路径的朝向。这允许你将局部轨迹规划器调优为以期望的行为运行,而不必担心在极小的欧几里得距离内,因显著的角度差而需要「急转弯」式旋转。某些控制器在针对精确路径跟踪进行重度调优后,其动作受到约束,无法干净地旋转到新朝向。其他控制器则有「螺旋向外」的行为,因为它们的采样需要一定的平移速度,从而阻止其原地旋转。旋转 Shim 有助于缓解该问题,使机器人能够非常平滑地原地旋转。
最后,矢量追踪(Vector Pursuit)是另一种很好的路径跟踪解决方案,与 RPP 一样,它与运动学可行的规划器搭配使用。它比 RPP 稍先进一些,因为它还考虑了路径朝向。Vector Pursuit 可以在高速下处理复杂路径,但它仍然是一个简单的几何控制器,因此计算资源需求低。
注意:这些只是社区提供的默认和可用插件。对于特定的机器人平台/公司,你也可以选择不使用其中任何一个,而是创建自己的插件。更多细节请参阅编写新的控制器插件教程。如果你愿意将这些工作回馈给社区,请提交工单或联系维护者,他们会很高兴收到你的反馈。
在 Smac 规划器中缓存障碍物启发式(Caching Obstacle Heuristic)
Section titled “在 Smac 规划器中缓存障碍物启发式(Caching Obstacle Heuristic)”Smac 的 Hybrid-A* 和 State Lattice 规划器提供了一个选项 cache_obstacle_heuristic。它可用于在朝向同一目标位姿的多次重规划之间缓存启发式信息,从而显著提高规划器速度(提升幅度取决于多种因素,通常为 40-300%)。障碍物启发式用于引导机器人进入空间中间、遵循代价,并驱动运动学可行的搜索沿着走廊走向有效解。可以把它理解为一个 2D 代价感知搜索,在完整的运动学可行搜索/SE2 碰撞检查需要更多计算之前,先为规划器「预热」方向,告诉它应该往哪里走。
这对于提高重规划速度以提升性能很有用。但需要注意的是,缓存该启发式后,它将不会使用代价地图中最新的信息来引导搜索。在规划过程中,规划器仍会使用最新的代价信息进行碰撞检查,因此这不会影响路径的安全性。然而,它可能会使搜索进入新被阻塞的走廊,或引导搜索走向可能含有新动态障碍物的区域,如果整个解空间被阻塞,速度可能会显著降低。
因此,维护者建议仅在基本静态的环境中(例如没有太多移动物体或变化、全局代价地图中不使用实时传感器更新等),跨大空间规划到单一目标时才启用此选项。在 Nav2 的目标切换之间,该启发式会使用最新信息进行更新,因此如果你非常频繁地更换目标,它的帮助就不大了。
Costmap2D 插件
Section titled “Costmap2D 插件”Costmap2D 提供了许多可用插件(你也可以创建自己的插件!)。
StaticLayer:用于设置来自 SLAM 的地图(预构建的或当前正在实时构建的),以确定环境尺寸,并设置墙壁、房间等关键特征,供全局规划使用。InflationLayer:使用指数函数膨胀致命代价,帮助引导导航算法远离墙壁并快速检测碰撞。ObstacleLayer:2D 代价地图层,用于 2D 平面激光雷达,或在低算力设备上无法对 3D 传感器使用 3D 层时使用。如果你的算力充足,请对 3D 数据使用VoxelLayer,它提供更准确的结果。VoxelLayer:3D 代价地图层,用于非平面 2D 激光雷达或基于光线投射(raycast)清除的深度相机处理。由于收集的数据稀疏,不适用于 3D 激光雷达。SpatioTemporalVoxelLayer:3D 代价地图层,用于 3D 激光雷达、非平面 2D 激光雷达或基于时间衰减的深度相机处理。适用于具有高传感器覆盖率的机器人,例如 3D 激光雷达或多深度相机,并且由于无需光线投射,计算开销更低。RangeLayer:对声呐、红外传感器或其他测距传感器建模,以纳入代价地图。DenoiseLayer:从最终代价地图中去除椒盐噪声(salt and pepper noise),以移除未过滤的噪声。还可以选择移除可配置大小的簇,以在没有时间衰减的情况下消除动态障碍物的影响。PluginContainerLayer:组合此插件内指定的代价地图层,生成一个内部代价地图,该地图是此层下指定的各代价地图层的组合结果。这允许在同一父代价地图内形成不同的隔离代价地图层组合,例如对静态层和障碍物层应用不同的膨胀层。
此外,还有代价地图过滤器(costmap filters):
KeepoutFilter:在代价地图中标记禁入区、更高加权或更低加权区域。SpeedFilter:根据位置降低或提高机器人速度。BinaryFilter:在特定区域内启用或禁用二进制话题。
注意:代价地图过滤器可以与 VectorObject 服务器搭配使用,从而使用矢量化区域,而非栅格化的地图区域。
对称偏航容差(Symmetric Yaw Tolerance)
Section titled “对称偏航容差(Symmetric Yaw Tolerance)”对于前进和后退行驶能力相当的机器人,你可以设置 symmetric_yaw_tolerance: true,让机器人无需不必要的 180° 旋转即可到达目标。这对于对称机器人(例如两端都装有传感器的差速驱动机器人)特别有用,因为你不关心它最终处于哪种朝向,交给控制器算法来决定即可。
如果你希望控制对称机器人的最终朝向,请查看 ROSCon 2023 上的Bidirectional navigation with Nav2(使用 Nav2 进行双向导航),了解如何使用 Nav2 设置和调优双向机器人。该演讲重点介绍了如何调优控制器、规划器及其他设置,在没有传统”前方”的平台上实现完全无方向偏好的导航。
SimpleGoalChecker:如果机器人处于目标朝向或目标朝向 + 180° 的容差范围内,则接受目标为已到达。GoalAngleCritic (MPPI Controller):根据到目标朝向或翻转朝向的最小角度距离对轨迹进行评分。
Nav2 启动选项
Section titled “Nav2 启动选项”Nav2 的启动文件(launch files)设计得非常灵活。对于正式应用,用户应以 nav2_bringup 作为导航启动系统的基础,但应将其迁移到自己的仓库中。一种典型做法是创建一个包含启动文件和参数文件的 <robot_name>_nav 配置包。
在 nav2_bringup 中,有一个主要的入口文件 tb3_simulation_launch.py。这是用于模拟机器人的主要文件,包含以下配置:
slam:是否使用 AMCL 或 SLAM Toolbox 进行定位和/或建图。默认为false,即使用 AMCL。map:用于导航的地图文件路径。默认为包中maps/目录下的map.yaml。world:模拟中使用的世界文件路径。默认为包中的worlds/目录。params_file:主要的导航配置文件。默认为包中params/目录下的nav2_params.yaml。autostart:是否自动启动导航系统的生命周期管理系统。默认为true,即创建时让 Nav2 栈向上转换到激活状态,随时可用。use_composition:是将每个 Nav2 服务器启动为独立进程,还是启动为单个组合节点(composed node),以利用 CPU 和内存的节省。默认为true,使用单进程 Nav2。use_intra_process_comms:是否使用 ROS 2 的进程内通信(intra-process communication)在节点之间传递消息。默认为false。use_respawn:是否允许崩溃的服务器自动重生(respawn)。当与生命周期管理器一起配置时,如果系统已经激活但因崩溃而关闭,管理器将把系统转换回启动状态。仅适用于非组合式启动(non-composed bringup),因为否则所有节点都位于同一进程/容器中。use_sim_time:是否将所有节点设置为使用仿真时间,模拟中需要。模拟默认为true。rviz_config_file:要使用的 rviz 配置文件路径。默认为rviz/目录下的文件。use_simulator:是否随 Nav2 栈一起启动 Gazebo 模拟器。默认为true,即启动 Gazebo。use_robot_state_pub:是否启动机器人状态发布器(robot state publisher),将机器人的 URDF 变换发布到 TF2。默认为true,即发布机器人的 TF2 变换。use_rviz:是否启动 rviz 进行可视化。默认为true,即显示 rviz。headless:是否在后台 Gazebo 仿真之外,额外启动 Gazebo 前端界面。默认为true,即显示 Gazebo 窗口。namespace:启动机器人所用的命名空间。robot_name:要启动的机器人的名称。robot_sdf:机器人的 gazebo 配置文件路径,包含用于模拟机器人系统的 Gazebo 插件和设置。x_pose、y_pose、z_pose、roll、pitch、yaw:用于设置机器人模拟初始位置的参数。
ROS 2 中的性能:RMW、节点组合、进程内通信与 QoS
Section titled “ROS 2 中的性能:RMW、节点组合、进程内通信与 QoS”在 Nav2 中,我们强烈建议将 use_composition 设置为 true,因为它能启用节点组合、减少进程开销并普遍提高系统效率。然而,是否启用进程内通信以及使用哪种 RMW 实现,取决于你的具体应用。
下表总结了在 TurtleBot4 模拟中(ros2 launch nav2_bringup tb4_simulation_launch.py)测量的不同 RMW 实现和进程内通信(IPC)设置的 CPU 使用率结果。基线测量对应于测试时(2025 年 12 月)最新的 rolling 提交。
| 中间件 | 配置 | CPU 使用率 (%) |
|---|---|---|
| Zenoh | 基线(Baseline) | 4.5% |
| Zenoh | 启用 IPC(SharedPtr) | 6.0% |
| Zenoh | IPC + ConstSharedPtr | 5.8% |
| CycloneDDS | 基线(Baseline) | 18.3% |
| CycloneDDS | 启用 IPC(SharedPtr) | 17.8% |
| CycloneDDS | IPC + ConstSharedPtr | 16.1% |
| FastDDS | 基线(Baseline) | 6.8% |
| FastDDS | 启用 IPC(SharedPtr) | 7.8% |
| FastDDS | IPC + ConstSharedPtr | 7.8% |
如表所示,启用进程内通信会导致 FastDDS 和 Zenoh 的 CPU 使用率增加,而 CycloneDDS 的 CPU 使用率则有所降低。
更多细节请参阅这篇文章。
关于 QoS,我们提供了 allow_parameter_qos_overrides 参数,允许你在需要时定制 QoS 设置。
如果你有额外的发现,欢迎随时提交 PR 分享,我们会很乐意将信息收录于此!
我们希望提供的其他页面
Section titled “我们希望提供的其他页面”如果你愿意贡献一份力量,这个议题 中有一些想法,但我们也欢迎任何你认为有见解的内容!