image.png
路径规划是指通过一定的规则,找到一条通过世界的路径来达到我们想去的地方。
规划的第一步是路线导航,侧重于研究如何从地图上的A点前往B点。
image.png
在路线导航时,将地图数据作为输入,并输出可行驶路径。手机导航系统是路线导航的一个示例。
在Apollo中,可以通过路线规划模块处理该任务。一旦我们构建出高水平的路线,我们就会放大至轨迹规划。该轨迹由一系列点定义,每个点都有一个关联速度和一个指示何时应抵达那个点的时间戳。通过轨迹规划,我们可以做出微妙的决策,以避开障碍物,并为乘客创造平稳的乘车体验。在Apollo中,我们通过规划模块处理该任务。路线规划的目标是,找到从地图上的A前往B的最佳路径。轨迹规划的目标是找到避免碰撞和保持舒适度的可执行轨迹。
路径规划使用三个输入:
人们试图在地图上找到从A到B的路线时,通常会沿着道路追踪路径,以查看是否存在通往目的地的任何路径,这被称为搜索。
Apollo也通过搜索来查找路线,但它使用了更智能的搜索算法。
在进行智能搜索算法以前,我们需要将地图数据重新格式化为“图形”的数据结构。
该图形由“节点”(node)和“边缘”(edge)组成。节点代表路段,边缘代表这些路段之间的连接
我们可以对一个节点移动到另一个节点所需的成本进行建模。
A* 是经典的路径查找处理算法。
具体算法参考:https://cloud.tencent.com/developer/article/1620060
高等级地图路线只是规划过程中的一部分,我们仍需要构建沿这条路线前进的低等级轨迹。
这意味着要处理一些不属于地图的物体:如其他车辆、自行车或行人。例如,我们可能需要与试图在我们前面掉头的汽车互动,或者我们可能希望超过一辆在公路上行驶的慢车。这些场景需要更低级别、更高精确度的规划。我们将这一级别的规划称为轨迹生成。
image.png
轨迹生成的目标是生成一系列路径点所定义的轨迹。我们为每个路径点分配了一个时间戳和速度。由于移动的障碍物可能会暂时阻挡部分路段,轨迹中的每个路径点都有时间戳。
我们可以将时间戳与预测模块的输出相结合,以确保我们计划通过时,轨迹上的每个路径点均未被占用。这些时间戳和空间上的两个维度(2D position)共同创建了一个三维轨迹(3D Trajectory)。我们还为每个路径点指定了一个速度,用于确保车辆按时到达每个路径点。
现实世界中的规划面临多种约束。
*首先轨迹应能免于碰撞,这意味着必须没有障碍物。
*其次,要让乘客感到舒适,所以路径点之间的过渡以及速度的任何变化都必须平滑。
*再者,路径点对车辆应实际可行,例如高速行驶的汽车不能立即做180度转弯。我们不能构建包含这种不可行机动的轨迹。
*最后,轨迹应合法。我们需要了解每个路径点的交通法律,并确保轨迹遵守这些法律法规。
在道路的任何两点,可能会有多个不会发生碰撞、行驶舒适、可行且合法的轨迹。我们如何选择最佳轨迹呢?
答案是使用“成本函数”。
成本函数为每个轨迹分配了一个“成本”,我们选择成本最低的轨迹。
image.png
轨迹“成本”由各种犯规处罚组成,例如:偏离道路中心,有可能产生碰撞,速度限制,轨迹的曲率和加速度让乘客感到不舒服等。
我们通常使用笛卡尔坐标系描述物体的位置,但笛卡尔坐标系对车辆来说并不是最佳选择。
即使给出了车辆位置(x,y),如果我们不知道道路在哪,就很难知道车辆行驶了多远也很难知道车辆是否偏离了道路中心。
笛卡尔坐标系的替代解决方案为Frenet坐标系。
image.png
Frenet坐标系描述了汽车相对于道路的位置。在Frenet框架中,s代表沿道路的距离,也被称为纵坐标。d表示与纵向线的位移,也被称为横坐标。在道路的每个点上,横轴和纵轴都是垂直的。纵坐标表示道路中的行驶距离,横坐标表示汽车偏离中心线的距离。