4. 决策规划框架
各位同学,今天我们聊点实在的。决策规划这个事儿,说白了就是让车知道“接下来该干嘛”。你想想看,一个无人车在复杂路况里跑,它得同时处理好几层问题:要去哪儿?怎么走?方向盘打多少?
我刚开始做这个方向时,也想过“能不能一个算法搞定所有”。后来发现,不行。为什么?因为不同层次的问题,对实时性、精度、抽象程度的要求完全不同。所以,分层架构就成了行业共识。
4.1 分层架构:任务规划、行为规划、运动规划
这套架构,我习惯把它比作一个公司的三层管理:
- 任务规划(Route Planning):相当于CEO,定大方向。从A到B,走哪条路,经过哪些路口。它不关心具体怎么开,只关心路径。
- 行为规划(Behavior Planning):相当于部门经理,做决策。比如“前方有车,我要变道”、“路口要减速让行”。它输出的是驾驶行为。
- 运动规划(Motion Planning):相当于执行者,算轨迹。具体到每一帧的方向盘角度、油门开度。它输出的是平滑的轨迹曲线。
我在项目中遇到过一个问题:任务规划给的路径太粗,导致行为规划频繁切换。比如明明可以直行,任务规划却建议绕个小弯。嗯,后来我们加了一层路径平滑,才解决。
核心要点:每一层只关注自己该做的事。任务规划别管方向盘,运动规划别管目的地。各司其职,系统才稳定。
下面这张图,是我自己画的架构图。你看一眼就明白了:
4.2 状态机与行为树
行为规划这块,最经典的做法就是状态机。说白了,就是给车定义好几种状态:直行、变道、左转、右转、停车。然后根据条件跳转。
我早期做的一个项目,用的就是有限状态机。代码大概长这样:
// 状态机示例(伪代码)
enum State {
CRUISE, // 巡航
FOLLOW, // 跟车
LANE_CHANGE, // 变道
STOP // 停车
}
State currentState = CRUISE;
void updateState(PerceptionData data) {
switch(currentState) {
case CRUISE:
if (data.frontCarDistance < 30m) {
currentState = FOLLOW;
}
break;
case FOLLOW:
if (data.frontCarDistance > 50m) {
currentState = CRUISE;
}
if (data.laneChangeAvailable) {
currentState = LANE_CHANGE;
}
break;
// ... 其他状态
}
}
状态机的好处是简单、直观。但问题也很明显——状态多了以后,跳转逻辑会变得一团乱麻。我曾经维护过一个有30多个状态的状态机,每次加一个新功能都提心吊胆。
后来,行为树(Behavior Tree)开始流行。它用树形结构组织行为,每个节点要么是“选择节点”(挑一个子节点执行),要么是“序列节点”(按顺序执行)。
我的建议:如果你的场景比较固定(比如园区低速车),状态机完全够用。但如果是开放道路、场景多变,行为树更灵活。我个人现在更倾向行为树,因为它好扩展、好调试。
举个例子,行为树处理“路口通行”的逻辑:
// 行为树节点示例
SequenceNode("通过路口") {
ConditionNode("是否有红绿灯") {
if (有红绿灯) {
ActionNode("根据红绿灯决策");
} else {
ActionNode("根据路权规则决策");
}
}
ActionNode("减速观察");
ActionNode("执行通过");
}
4.3 基于优化的方法
说到运动规划,就不得不提基于优化的方法。说白了,就是把轨迹规划变成一个数学优化问题——在满足约束的前提下,找一个最优解。
常见的优化目标包括:
- 平滑性(加速度变化率最小)
- 安全性(与障碍物距离最大)
- 舒适性(横向加速度最小)
- 效率(行驶时间最短)
约束条件就更多了:
- 车辆动力学约束(最大转向角、最大加速度)
- 道路边界约束(不能压线、不能上路沿)
- 障碍物约束(不能碰撞)
- 交通规则约束(红灯停、限速)
我常用的一个框架是二次规划(QP)。它把问题写成:
minimize: 0.5 * x^T * H * x + f^T * x
subject to: A * x <= b
l <= x <= u
其中x是轨迹参数(比如每个时间点的位置、速度),H矩阵控制平滑性,约束矩阵A控制安全边界。
注意:基于优化的方法虽然数学上漂亮,但实际落地时坑很多。我曾经遇到过优化不收敛的情况,车在原地打转。后来发现是约束条件写得太紧,给了一点松弛空间就好了。
还有一种方法是模型预测控制(MPC)。它滚动优化,每帧都重新算一遍。实时性要求高,但效果确实好。我建议你在做高速场景时优先考虑MPC。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 状态机 | 简单、直观、调试方便 | 状态多时维护困难 | 低速、固定场景 |
| 行为树 | 扩展性好、可复用 | 学习成本稍高 | 开放道路、复杂场景 |
| 二次规划(QP) | 数学严谨、轨迹平滑 | 可能不收敛、计算量大 | 结构化道路 |
| 模型预测控制(MPC) | 实时性好、能处理约束 | 模型依赖性强 | 高速、动态场景 |
最后说一句,没有银弹。我在实际项目中,往往是混合使用——行为规划用行为树,运动规划用MPC。你想想看,这样既保证了决策的灵活性,又保证了轨迹的平滑性。
嗯,这一章的内容就到这儿。记住,分层架构的核心是“各司其职”,别让运动规划去操心目的地,也别让任务规划去操心方向盘。
本章小结:
- 分层架构:任务规划(路径)→ 行为规划(决策)→ 运动规划(轨迹)
- 状态机适合简单场景,行为树适合复杂场景
- 基于优化的方法(QP、MPC)能生成平滑轨迹,但要注意收敛性和实时性
可可精品资料库