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图,我习惯分三步走:

  1. 确定时间范围:通常取当前时刻到未来8-10秒。太短了来不及避障,太长了预测不准。
  2. 确定位移范围:根据当前车速和最大加速度,估算车辆在时间范围内能到达的最远位置。一般取0到200米左右。
  3. 离散化网格:把连续的时间-空间离散成网格。时间步长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图的核心构建逻辑:

ST图构建与障碍物投影流程 参考线 & 自车状态 障碍物预测轨迹 道路边界信息 ST图网格构建 时间范围[0,10s] × 位移范围[0,200m] 静态障碍物投影 竖直条带区域 动态障碍物投影 倾斜平行四边形区域 可通行区域构建 障碍物膨胀 → 区域标记 → 连通性检查 核心逻辑:将三维时空障碍物投影到二维ST平面,构建可通行区域供速度规划使用

4.5 实际项目中的ST图应用技巧

最后,分享几个我在实际项目中积累的ST图应用技巧:

  • 多障碍物重叠处理:当多个障碍物在ST图上重叠时,取它们的并集作为不可通行区域。别取交集,那会漏掉障碍物。
  • 障碍物优先级:不是所有障碍物都需要投影到ST图上。远处的、不在自车车道上的障碍物,可以忽略。我一般只考虑自车车道及相邻车道、距离100米以内的障碍物。
  • ST图的可视化调试:一定要把ST图画出来看。我每次调试都会把ST图实时显示在屏幕上,障碍物投影区域用红色标出,规划轨迹用蓝色标出。一眼就能看出问题在哪。

避坑指南:我曾经在ST图里忘了考虑自车的加速度限制。结果规划出来的轨迹在ST图上看起来完美避开了所有障碍物,但实际车辆根本执行不了——加速度太大了。所以,构建ST图时一定要把车辆动力学约束考虑进去,比如最大加速度、最大减速度、最大速度等。