自动驾驶决策
一句话概述
自动驾驶中的行为决策是连接感知和控制的核心环节——需要决定变道、超车、路口通行等高层次策略。RL特别适合处理驾驶中的多智能体交互、不确定性和长时域规划,从简单的车道保持到复杂的无保护左转,RL与基于规则的方法正在融合形成可靠的安全决策系统。
教学与演示
自动驾驶中的决策问题
自动驾驶系统通常分为三层架构:
- undefined
传统决策系统依赖有限状态机和基于规则的行为树——工程师枚举所有可能场景并编写对应的if-else逻辑。问题在于:真实世界的驾驶场景无穷无尽,手工规则永远无法覆盖所有情况(「长尾问题」)。
RL恰好适合这个角色——它不需要预定义所有场景,而是从经验中学习通用的决策策略。
大白话 传统自动驾驶的决策就像一本厚厚的「驾驶手册」——「如果前方有车且车速 < 60,则变道超车」。但真实驾驶中有1000种「如果」需要判断。RL不记手册,而是像人类司机一样——通过无数次(仿真)驾驶经验「练出车感」。
自动驾驶决策的RL建模
将驾驶建模为RL问题:
- undefined
层次化动作空间:自动驾驶通常使用分层RL,将决策分解为:
- undefined
大白话 驾驶决策就像下棋时「走哪步」加上「用多大力气走」——高层决定「要不要超车」,低层决定「超车时方向盘打多少度」。这个分层设计让RL更高效。
多智能体交互
自动驾驶本质上是一个多智能体问题——路上的所有车辆都在互相影响。一辆车的变道决策会影响周围车辆的行为,而这些车辆的反应又会影响本车的后续决策。
与其他多智能体场景不同,自动驾驶中智能体之间没有通信通道——只能通过「行为推断」(观察对方的轨迹预测意图)来交互。
这意味着一辆自动驾驶汽车需要对周围车辆的未来行为进行预测,而预测又依赖于「对方怎么预测我的行为」——这是一种递归推理(Recursive Reasoning)。
大白话 老司机开车时会有「预判」——看前车微微往左偏就知道它可能要变道。自动驾驶也需要这种能力,不过是通过概率模型(其他车辆的轨迹预测)来实现的。更高级的是「我预判你预判了我的预判」这种多层推理。
安全约束RL
普通RL只优化期望奖励,但自动驾驶要求绝对安全——即使发生概率极低的危险情况也是不可接受的。
约束马尔可夫决策过程(CMDP) 通过引入安全约束:
其中J_C是安全代价(如碰撞次数),d是安全阈值。这个约束表示:在不超过安全风险上限的前提下最大化效率等目标。
主要安全RL方法:
- undefined
大白话 普通RL会说「99%概率成功就挺好的」。但自动驾驶需要「99.9999%才够」。安全RL就是给RL加了一个「绝对不能做的事」清单——速度再快、效率再高,只要不安全就一票否决。
逆强化学习与驾驶风格
逆强化学习(IRL)在自动驾驶中有着独特的应用——从人类驾驶数据中推断「什么才是好驾驶」。
IRL的核心思想:给定专家演示轨迹,推断驱动这些行为的奖励函数。
通过IRL学到的奖励函数不仅包含「安全」和「效率」,还隐含了人类的驾驶风格偏好(如某些司机偏保守、某些偏激进)。这使得RL学习到的策略更像「人类司机」而不是「最优但吓人的机器人司机」。
大白话 IRL就像看老司机开车视频,倒推他在心里是怎么打分的——「他为什么在这里减速?」「他为什么在那个时机变道?」。由此推断出一个打分函数,然后RL按照这个打分函数去学习,学出来的策略就更像人类、更自然。
什么用
RL在自动驾驶中的实际应用:
- undefined
大白话 目前商用自动驾驶主要靠「规则+优化」来决策,RL更多在仿真验证和边缘场景处理中发挥作用。但趋势是RL正在从「锦上添花」变成「核心引擎」——特别是在处理规则写不完的长尾场景时。
哪些坑
| 坑点 | 原因 | 解决方案 |
|---|---|---|
| 安全性保证 | RL只能优化奖励,不保证绝对安全 | CMDP、安全层、Simulation验证覆盖 |
| 长尾分布 | 危险场景极少但最重要 | 重要采样、对抗生成危险场景 |
| 仿真现实差距 | 驾驶仿真与真实世界差异大 | 域随机化、真实数据校准 |
| 多智能体复杂度 | 交通参与者数量大且多样 | 分层RL、注意力机制、交互预测模型 |
| 奖励设计困难 | 安全/效率/舒适三者难以平衡 | 多目标RL、IRL推断、人类偏好学习 |
| 可解释性 | 黑盒RL决策难以通过安全认证 | XAI、注意力可视化、决策溯源 |
核心代码演示
"""
自动驾驶行为决策 - 高速公路简化场景
演示层次化动作空间和安全约束
"""
import numpy as np
# ===== 高速公路驾驶环境 =====
class HighwayEnv:
"""
简化3车道高速公路环境
自车需要在车流中安全、高效地行驶
"""
def __init__(self, n_lanes=3, highway_length=500):
self.n_lanes = n_lanes
self.highway_length = highway_length
self.max_speed = 30.0 # m/s (108km/h)
self.target_speed = 25.0
self.reset()
def reset(self):
# 自车状态:横向位置(车道)、纵向位置、速度
self.ego_lane = 1 # 中间车道 (0, 1, 2)
self.ego_pos = 0.0
self.ego_speed = 20.0 # 初始速度
# 周围车辆:[lanes, positions, speeds]
self.n_traffic = np.random.randint(3, 8)
self.traffic = {
'lane': np.random.randint(0, self.n_lanes, self.n_traffic),
'pos': np.random.uniform(10, 100, self.n_traffic),
'speed': np.random.uniform(15, 28, self.n_traffic)
}
self.time = 0
return self.get_state()
def get_state(self):
"""感知状态:周围车辆相对于自车的信息"""
state = [self.ego_speed / self.max_speed,
self.ego_lane / (self.n_lanes - 1)]
# 对每条车道,找到前后最近的车
for lane in range(self.n_lanes):
for direction in ['front', 'rear']:
dist, spd = self._nearest_vehicle(lane, direction)
state.extend([dist / 50.0, spd / self.max_speed])
return np.array(state)
def _nearest_vehicle(self, lane, direction):
"""找到最近车辆的距离和速度"""
best_dist = 50.0 if direction == 'front' else -50.0
best_speed = self.target_speed
for i in range(self.n_traffic):
if self.traffic['lane'][i] == lane:
rel_pos = self.traffic['pos'][i] - self.ego_pos
if direction == 'front' and 0 < rel_pos < best_dist:
best_dist, best_speed = rel_pos, self.traffic['speed'][i]
elif direction == 'rear' and best_dist < rel_pos < 0:
best_dist, best_speed = rel_pos, self.traffic['speed'][i]
return best_dist, best_speed
def step(self, action):
"""
动作空间(层次化):
0: 保持车道+目标速度 = target_speed
1: 加速(+2 m/s)
2: 减速(-2 m/s)
3: 左变道
4: 右变道
"""
# 动作执行
if action == 1: # 加速
self.ego_speed = min(self.ego_speed + 2.0, self.max_speed)
elif action == 2: # 减速
self.ego_speed = max(self.ego_speed - 2.0, 5.0)
elif action == 3: # 左变道
if self.ego_lane > 0 and self._lane_change_safe(self.ego_lane - 1):
self.ego_lane -= 1
elif action == 4: # 右变道
if self.ego_lane < self.n_lanes - 1 and self._lane_change_safe(self.ego_lane + 1):
self.ego_lane += 1
# 更新位置
self.ego_pos += self.ego_speed * 0.1 # 0.1s时间步
# 更新周围车辆
for i in range(self.n_traffic):
self.traffic['pos'][i] += self.traffic['speed'][i] * 0.1
# 车辆驶出视野后重新生成
if self.traffic['pos'][i] > self.ego_pos + 100:
self.traffic['pos'][i] = self.ego_pos - np.random.uniform(20, 50)
self.traffic['lane'][i] = np.random.randint(0, self.n_lanes)
self.traffic['speed'][i] = np.random.uniform(15, 28)
# 奖励计算
reward = 0.0
done = False
# 速度效率奖励
speed_ratio = self.ego_speed / self.target_speed
reward += 0.1 * min(speed_ratio, 1.0) # 越接近目标速度越好
# 安全检查:碰撞(安全约束不可违反)
collision = self._check_collision()
if collision:
reward -= 100.0 # 碰撞惩罚巨大
done = True
# 舒适度惩罚(加速度变化)
if action in [1, 2]: # 加速/减速
reward -= 0.05 # 小幅惩罚频繁加减速
self.time += 1
if self.time >= 200: # 20秒的episode
done = True
return self.get_state(), reward, done
def _lane_change_safe(self, target_lane):
"""安全检查:变道是否安全"""
front_dist, _ = self._nearest_vehicle(target_lane, 'front')
rear_dist, rear_spd = self._nearest_vehicle(target_lane, 'rear')
safe_dist = max(5.0, abs(self.ego_speed - rear_spd) * 0.5)
return front_dist > 10.0 and (rear_dist < -safe_dist or rear_dist > 0)
def _check_collision(self):
"""检查是否发生碰撞"""
for i in range(self.n_traffic):
if self.traffic['lane'][i] == self.ego_lane:
dist = abs(self.traffic['pos'][i] - self.ego_pos)
if dist < 4.0: # 安全距离4m
return True
return False
# ===== 演示自动驾驶决策 =====
env = HighwayEnv(n_lanes=3)
state = env.reset()
print("=== 高速公路驾驶决策演示 ===\n")
print(f"初始状态:车道={env.ego_lane}, 速度={env.ego_speed:.0f}m/s")
print(f"周围车辆:{env.n_traffic}辆")
print(f"状态向量维度:{len(state)}(包含各车道前后车辆信息)")
# 演示一个简单的基于规则的策略(传统方法)
print(f"\n--- 传统规则策略 ---")
actions = ['保持', '加速', '减速', '左变道', '右变道']
for step in range(5):
# 简单规则:前方有车且速度慢 → 变道
front_dist, front_speed = env._nearest_vehicle(env.ego_lane, 'front')
if front_dist < 20 and front_speed < env.ego_speed:
# 检查左侧
left_dist, _ = env._nearest_vehicle(env.ego_lane - 1 if env.ego_lane > 0 else 0, 'front')
if env.ego_lane > 0 and left_dist > 20:
action = 3 # 左变道
elif env.ego_lane < 2:
action = 4 # 右变道
else:
action = 2 # 减速
elif env.ego_speed < env.target_speed:
action = 1 # 加速
else:
action = 0 # 保持
next_state, reward, done = env.step(action)
print(f" 步骤{step+1}: {actions[action]} | 速度={env.ego_speed:.0f} | "
f"车道={env.ego_lane} | 前方={front_dist:.0f}m | 奖励={reward:.2f}")
print(f"\n关键洞察:")
print("1. 传统规则:if (前方有慢车) → 变道 — 简单但有盲区")
print("2. RL方法:从千万次仿真经验中学到「什么时机变道最优」")
print("3. 安全约束:RL输出必须经过安全检查器过滤")
"""
安全约束强化学习 - CMDP (Constrained MDP) 简化演示
Lagrangian方法:将安全约束转化为自适应惩罚
"""
import numpy as np
def lagrangian_update(policy_gradient, constraint_gradient,
lambda_param, cost_limit, lr_lambda=0.01):
"""
Lagrangian乘子法更新
将带约束的目标转化为无约束的Lagrangian对偶问题
max_{π} min_{λ≥0} J(π) - λ * (J_C(π) - d)
参数:
- policy_gradient: 主目标的梯度
- constraint_gradient: 安全约束的梯度
- lambda_param: Lagrangian乘子
- cost_limit: 安全成本上限 d
- lr_lambda: 乘子学习率
"""
# 1. 策略更新:最大化 Lagrangian
# ∇_π L = ∇_π J(π) - λ * ∇_π J_C(π)
combined_gradient = policy_gradient - lambda_param * constraint_gradient
# 2. 乘子更新:梯度下降(注意是min λ)
# ∇_λ L = -(J_C - d)
cost_overshoot = constraint_gradient - cost_limit # 实际成本超过上限的量
lambda_param = max(0, lambda_param + lr_lambda * cost_overshoot)
return combined_gradient, lambda_param
# ===== 演示Lagrangian安全RL =====
print("=== 安全约束RL:Lagrangian方法 ===\n")
# 模拟训练过程
np.random.seed(42)
lambda_val = 0.0 # 初始乘子(开始时不对不安全行为惩罚)
cost_limit = 0.1 # 安全上限:最多允许10%的概率出现不安全行为
print(f"初始 λ = {lambda_val:.3f}(不惩罚不安全行为)")
print(f"安全上限 d = {cost_limit}(允许10%不安全事件)")
print()
for episode in range(10):
# 模拟:奖励梯度和安全梯度
reward_grad = 1.0 # 提升奖励的方向
cost_grad = np.random.uniform(0.0, 0.3) # 当前策略的安全成本
# Lagrangian更新
combined_grad, lambda_val = lagrangian_update(
reward_grad, cost_grad, lambda_val, cost_limit
)
over_limit = cost_grad > cost_limit
print(f"Episode {episode+1:2d}: 成本={cost_grad:.2f} "
f"{'(超标!)' if over_limit else '(安全)'} | "
f"λ={lambda_val:.3f} | "
f"有效梯度={combined_grad:.3f}")
print(f"\nLagrangian的工作原理:")
print(f"1. 安全时(成本低):λ → 0,策略自由追求效率")
print(f"2. 危险时(成本高):λ ↑,策略被迫考虑安全")
print(f"3. 自动平衡:λ在安全和效率之间寻找最优折中")概念关系图谱
| 概念 | 与自动驾驶决策的关系 | 说明 |
|---|---|---|
| POMDP | 数学框架 | 驾驶是不完美信息问题(遮挡、意图不可知) |
| 层次化RL | 架构设计 | 分离行为决策和运动规划两个抽象层次 |
| 安全约束RL | 核心要求 | 保证自动驾驶中碰撞等安全事件必须趋近于零 |
| 逆强化学习 | 奖励获取 | 从人类驾驶数据中推断奖励函数和驾驶风格 |
| 多智能体RL | 交互建模 | 驾驶本质是多车交互,需考虑他人行为 |
| 轨迹预测 | 辅助模块 | 预测周围车辆未来轨迹以辅助决策 |
| 端到端学习 | 替代方案 | 从像素直接输出控制信号,跳过中间模块 |
| 仿真测试 | 训练基础 | 不可能在真实道路上探索试错 |
重点答疑
大白话 自动驾驶的决策层就像坐在驾驶位上的「大脑」——从眼睛(传感器)看到路况后,决定「要超车、要刹车、还是保持」。RL让这个大脑不是死记硬背「交规」,而是像老司机一样「有预见性」地开车。
💡 核心要点:自动驾驶RL决策的三个核心挑战——(1)安全是硬约束不是软目标(需要CMDP/安全层);(2)驾驶是多智能体交互(需要预测+推理);(3)长尾场景无限多(需要仿真+对抗生成)。这不是一个「算法选型」问题,而是一个系统设计问题。
- undefined
章节单词汇总
| 英文 | 音标 | 术语 | 释义 |
|---|---|---|---|
| Behavior Decision | /bɪˈheɪvjə dɪˈsɪʒən/ | 行为决策 | 选择高层驾驶行为(变道、跟车、超车等) |
| Constrained MDP | /kənˈstreɪnd em diː piː/ | 约束马尔可夫决策过程 | 带安全约束的MDP框架 |
| Lagrangian Method | /ləˈɡrændʒiən ˈmeθəd/ | 拉格朗日乘子法 | 将约束优化转化为无约束对偶问题 |
| Recursive Reasoning | /rɪˈkɜːsɪv ˈriːzənɪŋ/ | 递归推理 | 我预判你预判了我预判的...多层博弈推理 |
| Trajectory Prediction | /trəˈdʒektəri prɪˈdɪkʃən/ | 轨迹预测 | 预测周围交通参与者的未来运动轨迹 |
| Safety Layer | /ˈseɪfti ˈleɪə/ | 安全层 | 在RL输出之上过滤不安全动作的后处理模块 |
| Long-tail | /lɒŋ teɪl/ | 长尾分布 | 极少发生但极其重要的边缘场景 |
| Shadow Mode | /ˈʃædəʊ məʊd/ | 影子模式 | 策略静默运行对比人类行为但不实际控制车辆 |
| End-to-End | /end tuː end/ | 端到端 | 从传感器原始数据直接输出控制信号 |
| Ego Vehicle | /ˈiːɡəʊ ˈviːɪkəl/ | 自车 | 自动驾驶系统的参考车辆(自身) |
面试练习
- undefined
- undefined