4、路径规划基础:全局路径与局部路径、路径点序列
做阿克曼底盘,绕不开路径规划。说白了,就是告诉车子“你要去哪”和“你怎么去”。
我刚开始接触这个领域时,也把全局和局部路径搞混过。后来在项目里摔了几次跟头,才真正理解这两者的区别。今天咱们就好好聊聊这个。
4.1 全局路径规划:大方向要准
全局路径,就是给车子画一条从起点到终点的“大路线”。它不考虑路上的小障碍,只关心能不能到。
常用的算法有 Dijkstra、A*、RRT 等。我个人习惯用 A*,因为它效率高,而且容易调参。
核心思路:全局路径规划是在已知地图上,找一条最优路径。最优的标准可以是距离最短、时间最少,或者转弯最少。
举个例子,你让车子从仓库A到仓库B。全局规划会给出这样一条路径:
起点 (0, 0) → (5, 0) → (10, 5) → (15, 10) → 终点 (20, 15)
这是一系列离散的点。每个点包含 (x, y) 坐标,有时还包含朝向角 yaw。
嗯,这里要注意:全局路径的密度不能太稀。太稀了,车子在点与点之间容易跑偏。我一般设置点间距为 0.5 米到 1 米。
4.2 局部路径规划:细节决定成败
全局路径画好了,但路上突然出现一个纸箱怎么办?这时候局部路径就派上用场了。
局部路径规划,是在车子周围一个小范围内,实时调整路径。它负责避障、平滑轨迹、保证车子不撞墙。
常用的方法有 DWA(动态窗口法)、TEB(时间弹性带)、MPC(模型预测控制)。
我在项目中遇到过一个问题:全局路径规划得好好的,但车子一遇到行人就卡住不动。后来发现是局部规划器的参数没调好。避障的权重设得太高,导致车子不敢动。
我的经验:局部路径的规划范围,一般设为车长 3-5 倍的距离。太短了来不及反应,太长了计算量太大。
4.3 路径点序列:车子的“导航指令”
不管是全局还是局部路径,最终都要转换成路径点序列。这个序列就是车子的导航指令。
一个典型的路径点长这样:
pose:
x: 1.234
y: 5.678
yaw: 0.785 # 弧度,约45度
curvature: 0.02 # 曲率,用于阿克曼转向
你想想看,阿克曼底盘转弯时,前轮要转一个角度。这个角度跟路径点的曲率直接相关。曲率越大,转弯越急。
我曾经踩过一个坑:路径点的朝向角 yaw 和曲率不匹配。结果车子在转弯时,前轮打到底了,但路径还没转过来。车子直接冲出路径。
避坑指南:路径点序列中,相邻点的 yaw 变化不能太大。我一般限制每两个点之间的 yaw 变化不超过 0.3 弧度。否则阿克曼底盘会“甩尾”。
4.4 全局与局部的配合
全局路径和局部路径不是孤立的。它们需要配合工作。
典型的流程是:
- 全局规划器生成一条粗路径
- 局部规划器沿着粗路径,实时生成精细路径
- 车子执行局部路径的点序列
- 如果遇到障碍,局部规划器临时绕开
- 绕开后,再回到全局路径上
说白了,全局路径是“战略”,局部路径是“战术”。战略不能天天变,战术可以随时调整。
下面这张图展示了它们的关系:
4.5 路径点序列的生成与优化
路径点序列不是随便生成的。它需要满足几个条件:
- 连续性:相邻点之间不能有突变
- 可达性:每个点的曲率必须在阿克曼底盘的转向范围内
- 平滑性:路径不能有尖锐的拐角
我常用的做法是,先用全局规划生成粗路径,然后用样条插值(比如三次样条)把路径变平滑。最后再采样成等间距的点序列。
关键参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 点间距 | 0.3 - 0.8 米 | 太密计算量大,太稀路径不平滑 |
| 最大曲率 | 0.15 - 0.25 1/m | 取决于阿克曼底盘的最小转弯半径 |
| yaw变化限制 | ≤ 0.3 rad/点 | 防止转向过猛 |
| 局部规划范围 | 3 - 5 倍车长 | 保证有足够反应时间 |
嗯,这里还要提一句:路径点序列的坐标系要统一。我见过有人把全局路径用经纬度,局部路径用车体坐标系,结果一转换就出问题。建议全部用地图坐标系(map frame)。
4.6 实战中的常见问题
最后分享几个我在项目中踩过的坑:
- 路径抖动:局部规划器频繁切换路径,导致车子左右摇摆。解决办法是增加路径切换的 hysteresis(迟滞)。
- 死锁:车子被障碍物包围,局部规划找不到出路。这时候需要重新触发全局规划。
- 曲率超限:路径点的曲率大于阿克曼底盘的最大转向角。车子会报错或原地打转。一定要在生成路径时做曲率检查。
我的小技巧:在调试时,把路径点序列可视化出来。用 RViz 或者 Matplotlib 都行。看到路径点,很多问题一眼就能发现。
路径规划是阿克曼底盘的核心。全局路径定方向,局部路径保安全,路径点序列做桥梁。这三者配合好了,车子才能跑得稳、跑得准。