4. ST图基础:ST图的构建方法、障碍物在ST图中的投影
各位同学,欢迎来到速度规划的核心基础——ST图。说实话,我刚开始接触自动驾驶规划时,觉得ST图就是个二维坐标系,没什么特别的。直到我在实际项目中,因为对ST图理解不够深,导致车辆在高速上跟车时频繁急刹,被测试同事吐槽“像新手司机”。从那以后,我才真正沉下心来研究ST图的每一处细节。
ST图,说白了就是“时间-路径坐标系”。S代表沿参考线的纵向位移,T代表时间。你想想看,速度规划要解决的核心问题是什么?就是在什么时间,车辆应该到达路径上的哪个位置。ST图正好把这个关系直观地表达出来了。
4.1 ST图的坐标系与构建方法
先说说ST图的坐标系。横轴是时间t,单位秒;纵轴是纵向位移s,单位米。这个s不是大地坐标系的x或y,而是沿着参考线累积的弧长。
关键理解:ST图里的s,是从路径起点开始,沿着参考线走过的距离。不是直线距离,是曲线距离。我见过不少新手把s当成欧氏距离,结果规划出来的轨迹直接穿墙。
构建ST图,我习惯分三步走:
- 确定时间范围:通常取当前时刻到未来8-10秒。太短了来不及避障,太长了预测不准。
- 确定位移范围:根据当前车速和最大加速度,估算车辆在时间范围内能到达的最远位置。一般取0到200米左右。
- 离散化网格:把连续的时间-空间离散成网格。时间步长dt通常取0.1秒或0.2秒,位移步长ds取0.5米或1米。网格越细,精度越高,但计算量也越大。
这里有个小技巧——网格分辨率不是固定的。我在项目中遇到过这种情况:高速场景下,车辆移动快,网格可以粗一些;低速泊车场景下,车辆移动慢,网格必须细。所以我一般会根据车速动态调整网格密度。
// ST图网格构建伪代码
struct STGrid {
double t_min, t_max; // 时间范围
double s_min, s_max; // 位移范围
double dt; // 时间步长
double ds; // 位移步长
vector<vector<double>> cost; // 代价矩阵
};
STGrid BuildSTGrid(double current_speed) {
STGrid grid;
grid.t_min = 0.0;
grid.t_max = 10.0; // 10秒规划时域
grid.s_min = 0.0;
// 根据车速估算最远距离
grid.s_max = current_speed * 10.0 + 0.5 * 3.0 * 100.0;
grid.dt = 0.1; // 100ms分辨率
grid.ds = 0.5; // 0.5m分辨率
return grid;
}
4.2 障碍物在ST图中的投影
有了ST图这个“画布”,接下来就要把障碍物“画”上去。障碍物投影,就是把三维世界中的障碍物运动,映射到二维的ST平面上。
怎么投影?核心思想是:对于每个时刻t,计算障碍物在参考线上的纵向覆盖范围[s_min, s_max]。
具体步骤是这样的:
- 第一步:获取障碍物的预测轨迹。对于动态障碍物,预测模块会给出未来若干时刻的位置序列。
- 第二步:把每个时刻的障碍物位置,投影到参考线上。投影方式通常是找参考线上最近的点,取该点的s值。
- 第三步:考虑障碍物的几何尺寸。不能只投影一个点,要投影成一个矩形区域。障碍物有长有宽,投影到ST图上就变成了一个“块”。
我的经验:投影时别忘了加上安全裕量。我一般会在障碍物前后各加0.5米,左右各加0.3米。这个裕量不是拍脑袋定的,是根据车辆控制精度和定位误差算出来的。你想想看,如果投影刚好贴着障碍物边缘,控制稍有偏差就蹭上了。
4.3 静态障碍物与动态障碍物的ST表示
静态障碍物和动态障碍物,在ST图上的表现完全不同。我刚开始做的时候,把两者混为一谈,结果规划出来的轨迹要么太保守,要么太激进。
| 特性 | 静态障碍物 | 动态障碍物 |
|---|---|---|
| ST图形状 | 竖直条带 | 倾斜平行四边形 |
| 时间维度 | 贯穿整个时间轴 | 只在特定时间段出现 |
| 位移范围 | 固定不变 | 随时间变化 |
| 投影复杂度 | 低,一次投影即可 | 高,需要预测轨迹 |
| 典型示例 | 路边的锥桶、停着的车 | 同向行驶的车辆、横穿的行人 |
静态障碍物:它在ST图上是一条竖直的带状区域。为什么?因为静态障碍物的位置不随时间变化,所以它在每个时刻的s范围都一样。比如路边停着一辆车,占据s=50到s=55这段区域,那么在整个时间轴上,这段区域都是不可通行的。
动态障碍物:它在ST图上是一个倾斜的平行四边形。前车在向前移动,它的s值随时间增大,所以投影区域是斜向右上的。对向来车呢?它的s值随时间减小,投影区域是斜向右下的。
这里有个坑——动态障碍物的速度变化。我曾经假设障碍物匀速运动,结果前车突然刹车,我的规划轨迹直接怼上去了。后来我改用分段匀速模型,每段1秒,速度可以变化。虽然计算量大了点,但安全性提升了一大截。
注意:动态障碍物的预测轨迹是有不确定性的。预测时间越长,不确定性越大。我一般对3秒内的预测比较信任,3-5秒的预测打8折置信度,5秒以上的预测只做参考。这个经验值来自我多次实车测试的教训。
4.4 ST图的可通行区域构建
把所有障碍物投影到ST图上之后,剩下的空白区域就是可通行区域。速度规划的任务,就是在可通行区域内找一条从起点到终点的最优路径。
构建可通行区域,我通常这样做:
- 初始化:整个ST图都是可通行的。
- 标记障碍物:把所有障碍物投影区域标记为不可通行。
- 膨胀处理:对障碍物区域进行膨胀,留出安全距离。
- 连通性检查:检查起点到终点是否存在连续的可通行路径。
如果可通行区域被障碍物完全切断,那就需要重新规划路径,或者降低速度目标。我在高速上遇到过这种情况——前方事故车辆横在路中间,ST图上可通行区域被完全阻断。这时候速度规划必须通知路径规划模块重新选路。
下面这张SVG图,展示了ST图的核心构建逻辑:
4.5 实际项目中的ST图应用技巧
最后,分享几个我在实际项目中积累的ST图应用技巧:
- 多障碍物重叠处理:当多个障碍物在ST图上重叠时,取它们的并集作为不可通行区域。别取交集,那会漏掉障碍物。
- 障碍物优先级:不是所有障碍物都需要投影到ST图上。远处的、不在自车车道上的障碍物,可以忽略。我一般只考虑自车车道及相邻车道、距离100米以内的障碍物。
- ST图的可视化调试:一定要把ST图画出来看。我每次调试都会把ST图实时显示在屏幕上,障碍物投影区域用红色标出,规划轨迹用蓝色标出。一眼就能看出问题在哪。
避坑指南:我曾经在ST图里忘了考虑自车的加速度限制。结果规划出来的轨迹在ST图上看起来完美避开了所有障碍物,但实际车辆根本执行不了——加速度太大了。所以,构建ST图时一定要把车辆动力学约束考虑进去,比如最大加速度、最大减速度、最大速度等。