3. OMPL规划器详解

说到MoveIt的避障规划,OMPL是绕不开的核心。我刚开始接触MoveIt时,面对OMPL里那一堆算法名字——RRT、RRT*、PRM、EST、KPIECE……说实话,有点懵。每个算法都号称能规划路径,但到底该用哪个?参数怎么调?

这一章,我就带你把这些算法理清楚。咱们不搞学术那一套,就讲实际干活时怎么选、怎么配。

OMPL是什么?

OMPL的全称是Open Motion Planning Library,一个开源的运动规划库。MoveIt默认就用它来做路径规划。说白了,OMPL就是一群规划算法的集合,你给它一个起点、一个终点、一个环境地图,它帮你找出一条能走的路。

我个人的习惯是,把OMPL理解成一个工具箱。里面有不同的工具(算法),有的适合开阔空间,有的擅长狭窄通道,有的追求最优解,有的只求快速找到一条可行路径。

核心要点:OMPL不直接处理机器人的运动学模型,它只负责在配置空间(C-Space)中搜索路径。机器人具体的关节限制、碰撞检测,由MoveIt的其他模块处理。

OMPL算法家族概览

OMPL里的算法大致分两类:基于采样的和基于搜索的。实际工程中,我们主要用基于采样的算法,因为它们在高维空间里表现好。

下面这张图是我自己整理的OMPL算法家族关系,你看一眼就能明白大概。

OMPL 算法家族核心分类 OMPL 规划器 几何探索类 控制空间类 RRT / RRT* PRM / PRM* EST / KPIECE RRT (控制版) LQR-RRT* PDST 工程中最常用 RRT-Connect(快速) | RRT*(最优) | PRM(多查询)

嗯,这张图基本把OMPL的算法家族说清楚了。实际项目中,90%的场景用几何探索类就够了。控制空间类主要用在有动力学约束的机器人上,比如移动底盘、无人机。

RRT与RRT*:快速探索随机树

RRT(Rapidly-exploring Random Tree)是OMPL里最经典的算法。它的思路很简单:从起点开始,随机向空间里撒点,每次把新点连接到最近的树上,直到树长到终点附近。

你想想看,这就像在黑夜里用手电筒探路。你只能照亮眼前一小块,然后一步步往前走。RRT就是这种「走一步看一步」的策略。

RRT* 是RRT的升级版。它多做了两件事:

  • 重新选择父节点:每次加入新节点后,检查附近有没有更短的路径可以连过来
  • 重新布线:如果新节点能让附近节点的路径变短,就更新它们的连接关系

我在项目中遇到过这样一个场景:用RRT规划一条7轴机械臂的路径,每次都能找到路径,但路径弯弯绕绕,机器人走起来像喝醉了酒。换成RRT*后,路径平滑了很多,虽然规划时间多了30%,但执行效率反而更高了。

我的经验:如果对路径质量要求不高,只求快速找到一条可行路径,用RRT-Connect(双向RRT)。如果追求路径最优,用RRT*。RRT*的代价是规划时间更长,但路径更短、更平滑。

PRM:概率路线图

PRM(Probabilistic Roadmap)的思路和RRT完全不同。它先在整个空间里随机撒点,然后连接相邻的点,构建一张「路线图」。规划时,只需要把起点和终点连到这张图上,然后搜图就行了。

PRM适合什么场景?我举个例子。假设你要让机器人在一个固定的工作站里反复执行任务,环境基本不变。用PRM,你只需要建一次路线图,后面每次规划都是秒级完成。

PRM有两个阶段:

  1. 学习阶段:随机采样,构建路线图。这个阶段比较耗时
  2. 查询阶段:把起点终点连到图上,搜索路径。这个阶段非常快

我曾经在一个汽车焊装产线项目里用过PRM。工作站里有几十个夹具和焊枪,环境复杂但固定。用PRM建图花了大概5分钟,但后面每次规划只需要0.2秒。相比之下,RRT每次都要重新探索,平均要1.5秒。对于产线节拍来说,PRM的优势很明显。

注意:PRM不适合动态环境。如果障碍物经常移动,路线图需要频繁重建,反而比RRT更慢。另外,PRM在狭窄通道场景下表现不好,因为随机采样很难采到狭窄区域里。

配置OMPL规划器参数

好了,算法选好了,接下来就是调参数。OMPL的规划器参数主要在ompl_planning.yaml里配置。我直接给你看一个实际项目中的配置示例:

# ompl_planning.yaml 示例
planner_configs:
  RRTConnectkConfigDefault:
    type: geometric::RRTConnect
    range: 0.1          # 扩展步长,单位:弧度
    goal_bias: 0.05     # 向目标点偏置的概率
    border_fraction: 0.9 # 边界采样比例

  RRTstarkConfigDefault:
    type: geometric::RRTstar
    range: 0.15
    goal_bias: 0.05
    delay_collision_checking: 1  # 延迟碰撞检测,提高速度

  PRMkConfigDefault:
    type: geometric::PRM
    max_nearest_neighbors: 10    # 每个点的最大邻居数
    max_sampling_attempts: 100   # 最大采样尝试次数

# 为不同规划组分配规划器
arm_group:
  planner_configs:
    - RRTConnectkConfigDefault
    - RRTstarkConfigDefault
    - PRMkConfigDefault
  projection_evaluator: joints(shoulder_pan_joint, shoulder_lift_joint)
  longest_valid_segment_fraction: 0.01

参数调优,我个人的经验是抓住几个关键点:

参数名 作用 调优建议
range 每次扩展的最大步长 值越大,探索越快,但容易跳过狭窄通道。一般设0.05-0.2
goal_bias 向目标点采样的概率 值越大,规划越快,但容易陷入局部最优。一般设0.05-0.1
max_nearest_neighbors PRM中每个点的邻居数 值越大,路线图连通性越好,但建图越慢。一般设10-30
longest_valid_segment_fraction 路径离散化精度 值越小,碰撞检测越精确,但规划越慢。一般设0.01-0.05

我曾经踩过一个坑:把range设得太大,结果RRT每次扩展都跳过障碍物之间的缝隙,死活找不到路径。后来把range从0.5降到0.08,路径就出来了。所以,range这个参数,小了安全但慢,大了快但容易漏掉路径。

调参小技巧:先设一个较大的range(比如0.2)和较小的goal_bias(0.05),看能不能找到路径。如果找不到,逐步减小range。如果找到了但路径太绕,增大goal_bias或换用RRT*。

还有一个参数容易被忽略——projection_evaluator。这个参数告诉OMPL如何把高维关节空间投影到低维,用于计算距离和最近邻搜索。默认用前两个关节,但如果你的机器人有特殊构型,可以自定义投影方式。

嗯,关于OMPL规划器的核心内容就这些。记住一句话:没有最好的算法,只有最合适的算法。RRT-Connect适合快速找路,RRT*适合追求最优,PRM适合固定环境多查询。参数调优时,range和goal_bias是最先要调的。

可可精品资料库