混合规划
MoveIt 的运动规划架构遵循”感知-规划-执行”(Sense-Plan-Act)模式。具体而言,先感知环境和机器人状态(“感知”),再由规划器计算机器人轨迹(“规划”),最后通过轨迹控制器一次性执行(“执行”)。
这种方法在已知的静态环境中进行全局运动规划时效果很好,但在许多现实场景中并不适用,尤其是当环境不稳定或动态变化时。例如,给桌上的人递一杯水,或在凹凸不平的黑板上写字——这类任务需要对不可预测的变化做出反应,超出了传统方法的能力。再比如,机器人的环境可能随时变化,或者任务本身存在固有的不确定性:用粉笔写字需要根据反馈动态调整施加在黑板上的压力,而粉笔也会随着使用不断变短。
解决这些挑战,需要一种能够根据实时条件调整所执行的运动、并在环境发生不可预见的变化时通过重新规划做出反应的方法。混合规划(Hybrid Planning)架构正是为此而设计——它将一对循环运行的全局规划器与局部规划器组合起来,协同完成任务。
什么是混合规划?
Section titled “什么是混合规划?”混合规划是一种组合异构运动规划器以产生更鲁棒、更具反应性的解决方案的运动规划方法。这种方法在导航(Navigation)社区中已非常成熟,并已在 navigation2 等热门项目中成功落地。
MoveIt 的混合规划架构将一对全局规划器与局部规划器组合起来,二者以不同的规划速度和问题范围并行、循环运行。
全局规划器(global planner)负责求解全局运动规划问题,其角色类似于”感知-规划-执行”模式中所用的规划器。所用的规划算法应当是完备(complete)的,因此计算时间相对较慢也在可接受范围内。此外,全局规划器不需要实时安全(real-time safe),即不保证在特定时限内找到解。根据实现的不同,全局规划器可以生成一个初始解,也可以在执行过程中迭代优化。
局部规划器(local planner)在执行过程中持续运行,生成用于跟随全局轨迹的迭代式机器人指令。从某种意义上说,局部规划器类似于控制器,但该架构允许它处理更复杂的问题和约束。其核心理念在于:规划器能够对世界进行推理并维护内部状态。这一特性使其非常通用,可用于解决各种局部规划问题,例如:
- 展开(unwinding)、融合(blending)或拼接(splicing)后续的全局参考轨迹
- 在跟随全局路径的同时动态避开近距离的碰撞
- 使全局轨迹适应局部约束(例如在不平整表面上施加期望的力/压力,或基于视觉反馈重新调整工具)
- 局部轨迹优化与时间参数化(在局部环境中优化轨迹,计算量更小、速度更快)
为了有效解决这些局部问题,局部规划器必须快速、能够对传感器反馈做出反应,并且在许多情况下满足实时安全要求。此外,它应当是确定性的,以避免抖动或不可预测的运动。
一般来说,局部规划器依赖全局规划器生成的参考轨迹来避免陷入局部极小值(local minimum)。不过,局部极小值有时仍无法完全排除,因此必要时需要触发全局规划器重新规划,以确保最终到达期望目标。这种行为需要一种特定的方式来传递规划器事件并进行相应处理。为此,混合规划架构支持实现基于事件的逻辑(event-based logic),可根据具体用例和规划器类型进行定制。
| 全局规划器 | 局部规划器 |
|---|---|
| 求解全局解轨迹 持续优化轨迹路径 | 跟随全局参考轨迹 求解局部问题约束 可处理传感器输入 局部优化解 计算控制器指令 |
| 完备(complete) 计算时间不受限 非实时安全 不一定是确定性的 | 可能陷入局部极小值 低计算时间 实时安全(取决于求解器) 确定性 |
| OMPL 规划器 STOMP TrajOpt 笛卡尔运动规划器 Pilz 工业运动规划器 MTC | IK 求解器、雅可比(Jacobian) 势场规划器 轨迹优化算法 模型预测控制(MPC) 基于传感器的最优控制 |
混合规划在许多场景中都很实用,大多数应用可以归为以下三类:
- 在线运动规划(Online motion planning):全局规划器创建初始全局解并持续优化。与此同时,局部规划器执行参考轨迹,并将更新后的轨迹段融合进去。
- 反应式运动(Reactive Motion):全局规划器用于修复失效的解(重新规划),而局部规划器在碰撞发生前减速或停止。
- 自适应运动(Adaptive Motion):局部规划器用于使全局解适应动态条件,例如在不平整表面上保持稳定的工具接触。
混合规划架构
Section titled “混合规划架构”下图描绘了构成混合规划架构的基本插件类型和 ROS 接口。

该架构由三个 ROS 组件节点构成:
-
混合规划管理器(Hybrid Planning Manager)
- 为混合规划请求提供 ROS action
- 运行规划逻辑并协调各规划器
-
全局规划器(Global Planner)
- 求解全局规划问题并发布解轨迹
-
局部规划器(Local Planner)
- 处理传入的全局轨迹更新
- 基于机器人状态、世界和参考轨迹求解局部规划问题
- 向机器人驱动发送位置/速度指令
各组件均被设计为通用且高度可定制。由于组件之间仅通过 ROS 2 消息接口交互,因此替换架构中任意组件或插件的实现都非常容易。插件接口被设计得尽可能精简,并与实际算法实现解耦。这让开发者能够完全专注于各自的逻辑或求解器,而无需自行实现任何基础设施;同一组件也可以在不同的设置或规划问题中复用。
混合规划管理器
Section titled “混合规划管理器”
该组件是架构的”大脑”。其主要职责是处理 HybridPlanner action 请求,并基于规划逻辑(planning logic)插件协调运动规划与执行过程。规划逻辑在 PlanningLogic 插件中实现,采用事件驱动设计。事件由字符串标识符定义,可以触发针对全局或局部规划器的 action 调用或取消。下图展示了一个简单规划逻辑的示例事件日志:

事件由混合规划 action 请求以及全局和局部规划器的 action 反馈消息触发。在此示例中,混合规划管理器收到混合规划请求后启动全局规划器。当全局轨迹到达时,局部规划器被启动;局部规划器完成后,混合规划管理器返回混合规划响应。
通过自定义 PlanningLogic 插件,可以将通用事件映射到架构提供的各种动作上,例如”启动全局规划”、“停止轨迹执行”或”切换到局部规划器约束 x”。由此,运动规划行为变得高度可定制和可适配。

全局规划器是架构中最简单的组件。它提供一个处理 GlobalPlanner 请求的 action 服务器。这些请求包含常见的 MotionPlanRequests,由全局规划器插件处理。默认情况下,这里使用的是 MoveIt 的规划流水线(planning pipeline),但从技术上讲,任何类型的规划器甚至 MTC 都可以在此使用。规划结果通过 action 反馈报告,解轨迹被发布给局部规划器作进一步处理。
局部规划器同样运行一个 action 服务器,用于处理来自混合规划管理器的请求。该 action 用于启动和停止执行,也可以配置约束或求解器类型等运行时参数。

局部规划器的实现基于两个插件:
- 轨迹算子(Trajectory Operator):该插件维护全局参考轨迹,处理来自全局规划器的轨迹更新,并监控当前机器人状态的进度。
- 局部约束求解器(Local Constraint Solver):该插件实现迭代求解器算法,基于参考轨迹和局部约束生成机器人指令。它可能包含额外的接口,用于动态处理传感器输入或事件更新。
下图展示了局部规划器在收到混合规划管理器的 action 请求后的一个示例循环周期:

每次迭代中,局部规划器都会请求当前的规划场景(planning scene),并在参考轨迹中匹配当前机器人状态。如果已到达目标,局部规划 action 便成功结束。否则,根据当前机器人状态识别当前的局部规划问题并求解。最后,将生成的控制指令发布给机器人控制器。
理解混合规划器运行时行为的最佳方式,是查看一张展示不同组件之间通信通道与事件的工作流图。
下图展示了成功执行轨迹时的运行时逻辑。

规划器由混合规划请求调用,这也是混合规划管理器响应的第一个事件。在此示例中,规划逻辑只是按顺序运行两个规划器。混合规划请求到达后,混合规划管理器调用全局规划器。全局规划器计算并发布轨迹,该轨迹同时被混合规划管理器和局部规划器接收。需要注意的是,局部规划器在收到混合规划管理器的调用之前,只是缓存新轨迹而不开始执行。一旦收到调用请求,局部规划器便开始展开参考轨迹,并在到达最终状态时成功返回 action 响应。之后,混合规划管理器返回成功的 HybridPlanningResponse。
接下来考虑一个更复杂的场景:混合规划器被设计为在执行过程中通过重新规划来避开障碍物。下面的动画展示了一个因碰撞物体变化而在运行时被修正的简单运动。

在此示例中,全局规划过程中存在的碰撞物体在全局轨迹计算完成后消失了。取而代之的是出现了两个新的碰撞物体,使得初始全局轨迹失效。局部规划器检测到即将发生的碰撞并暂停执行,直到全局规划器提供了更新后的无碰撞轨迹。
下面的工作流展示了上述行为。

启动过程与第一个示例相同,但在展开参考轨迹的过程中,局部规划器检测到了碰撞。此时,规划逻辑通过重新调用全局规划器来做出反应。在计算新的全局解期间,局部规划器必须确保机器人不与碰撞物体相撞,例如通过保持当前位姿。全局规划器完成计算后,新的全局解被发布给局部规划器,局部规划器的轨迹算子插件(Trajectory Operator Plugin)将其融合进参考轨迹。之后,局部规划器继续跟随参考轨迹,因为更新后的解使其能够绕开碰撞物体。
如果你想在自己的应用中使用混合规划,或者只是想试验一下,请查看 Hybrid Planning Example Tutorial。