自动驾驶汽车¶
自动驾驶汽车是商业上最先进的自主系统,将感知、预测、规划和控制集成到一辆车中。本章涵盖自动驾驶技术栈、高精地图、运动预测、规划、端到端驾驶、仿真、安全标准以及自动驾驶等级
-
可以说,自动驾驶汽车是在大规模尝试中最难的机器人问题。与在受控环境中运行的工厂机器人不同,自动驾驶汽车必须应对一个开放的世界:不可预测的人类驾驶员、乱穿马路的行人、一夜之间出现的施工区域,以及每分钟都在变化的天气。
-
其风险也格外高。自动驾驶汽车在高速公路上行驶,周围是易受伤害的道路使用者。对于安全关键故障,误差容忍度几乎为零。
自动驾驶技术栈¶
- 经典的自动驾驶架构是一个模块化流水线,包含四个阶段,每个阶段依次馈入下一个阶段:
-
感知(本章文件1中已介绍)将原始传感器数据处理成结构化的场景表示:带有3D位置、速度和类别标签的检测到的物体;车道标记;交通信号灯;可行驶区域边界。
-
预测 预测其他交通参与者(车辆、行人、自行车)未来的移动方式。给定场景的当前状态,预测模块输出每个参与者在未来一段时间(通常为3-8秒)的轨迹。
-
规划 决定自车应该做什么:遵循哪条路径、何时变道、何时让行、何时加速或刹车。它接收预测后的场景,并为自车生成一条安全、舒适且能朝着目的地前进的轨迹。
-
控制 将规划的轨迹转换为执行器命令:转向角、油门和刹车。这是最底层的环节,将抽象的轨迹转化为实际的物理运动。
-
模块化设计有明显的工程优势:每个模块可以独立开发、测试和改进。但它也有缺点:错误会向下游传播(漏检对规划器不可见),并且在每个接口处都会丢失信息(规划器看到的是边界框,而不是产生这些框的丰富传感器数据)。
高精地图¶
-
高精地图 是详细的、厘米级精度的数字地图,编码了道路结构:车道边界、车道连通性(在交叉口哪个车道连接到哪个车道)、交通标志位置、限速、人行横道位置以及道路表面高程。
-
高精地图为驾驶任务提供了强大的先验信息。感知模块不需要每一帧都从头发现车道边界;它只需将车辆在地图中定位,并验证现实与存储的结构是否匹配。这大大简化了规划。
-
构建高精地图需要配备高端激光雷达、摄像头和RTK-GPS的专业测绘车辆。随着道路变化,这些地图必须被维护和更新。这成本高昂,并且不容易扩展到地球上的每一条道路。
-
无地图驾驶(也称为“在线建图”)旨在消除对预建高精地图的依赖。相反,车辆实时从其传感器构建局部地图。像 MapTR 和 MapTRv2 这样的模型使用Transformer架构,直接从摄像头图像预测矢量化的地图元素(车道中心线、道路边界、人行横道),输出为有序点序列的多段线。
-
无地图方法用地图精度换取了可扩展性:只要汽车能开上某条路,它就能绘制这条路。但它要求感知系统足够鲁棒,能够实时检测所有相关的道路结构,包括在复杂交叉口、高速公路匝道和施工区域中。
-
在实践中,许多系统使用混合方法:轻量级地图提供粗略的道路拓扑(来自现有地图供应商),再由车辆的传感器实时丰富细节。
运动预测¶
-
预测其他道路使用者将去哪里是自动驾驶中最困难的子问题之一。人类是不可预测的,意图是隐藏的,可能的未来分支空间迅速膨胀。
-
预测模型的输入是场景上下文:所有检测到的参与者在近期(通常为1-2秒历史)的位置和速度,以及静态上下文(车道几何形状、交通信号、道路边界)。
-
输出是每个参与者的一组预测轨迹,通常覆盖未来3-8秒。由于未来是不确定的,好的预测模型会输出多条可能轨迹及其关联概率,而不是单个点估计。
-
轨迹预测 作为一个回归问题:预测每个参与者在离散未来时刻的 \((x, y)\) 坐标。损失通常是在 \(K\) 条预测轨迹上的最小平均位移误差:
-
这是一个“K个中最好的”指标:如果模型的 \(K\) 条预测中有一条接近真实轨迹,模型就获得分数。这鼓励多样化的、多模态的预测。
-
社会力 将行人行为建模为动力系统,其中每个人受到吸引力(朝向其目标)和排斥力(远离其他行人和障碍物)。人 \(i\) 的加速度为:
-
这是一个类似于本章文件2中机器人动力学方程的微分方程组。该模型很优雅,但依赖于手工调校的力参数,并且在处理复杂多智能体交互时存在困难。
-
用于预测的图神经网络 将场景建模为图:每个参与者是一个节点,边表示空间关系(邻近、共享车道)。节点之间的消息传递捕捉交互:“这辆车正在给那个行人让行”或“这两辆车正在汇入同一条车道”。
-
现代预测架构(例如 MTR、QCNet)使用基于Transformer的模型,联合推理参与者的历史、地图上下文以及参与者之间的交互。参与者通过交叉注意力关注相关的地图特征(它们当前所在的车道、即将到来的交叉口)以及其他参与者(前方的车辆、人行横道上的行人)。输出是通过自回归或混合模型生成的一组轨迹假设。
-
目标条件预测 首先预测参与者可能去的目标点(一组候选目标点,如车道终点或交叉口出口),然后预测到达每个目标的轨迹。这将问题分解为“去哪里”(离散、可管理)和“怎么去”(给定目标后的连续路径),使得多模态预测问题更易于处理。
规划¶
-
在给定预测场景后,规划器必须为自车生成一条轨迹。这是一个带约束的优化问题:找到一条安全、舒适、高效且合法的轨迹。
-
基于规则的规划器 将驾驶行为编码为一组 if-then 规则:“如果行人在人行横道上,则让行”、“如果与前车的间隙小于2秒,则不进行变道”、“如果接近红灯,则减速到停止线处停车”。这些规则具有可解释性和可审计性,但在复杂场景下会变得难以管理(成千上万条规则、许多边界情况、规则之间的相互作用)。
-
基于优化的规划器 将驾驶问题表述为轨迹优化。自车轨迹被参数化(例如,作为未来时刻的一个 \((x, y, \theta, v)\) 状态序列),并最小化一个目标函数:
-
进度项惩罚偏离期望路线。舒适项惩罚高的横向加速度、加加速度(加速度的导数)以及急转向,因为乘客会感觉到这些。安全项惩罚接近其他交通参与者,使用预测轨迹来评估碰撞风险。
-
这是带约束优化(第3章):在不等式约束下最小化成本函数。权重 \(w_1, w_2, w_3\) 在相互竞争的目标之间进行权衡(激进驾驶更快,但舒适性和安全性较差)。
-
基于学习的规划器 使用在人类驾驶数据上训练的神经网络来生成轨迹。模型观察场景并直接输出规划好的轨迹,从专家人类驾驶的示例中隐式学习复杂的权衡关系。
-
其优势在于能够整体捕捉人类驾驶行为,包括那些微妙且难以形式化的方面:汇入车流的激进程度、在交叉口何时向前挪动、给骑行者留出多少空间。缺点是与模仿学习(文件2)相同的分布偏移问题:模型在训练数据中代表性不足的情况下可能表现出不可预测的行为。
端到端驾驶¶
-
端到端驾驶 完全消除了模块之间的界限。单个神经网络接收原始传感器输入(摄像头图像、激光雷达点云),并直接输出驾驶命令(转向、油门、刹车)或规划好的轨迹。没有独立的感知、预测或规划模块。
-
其吸引力在于,整个系统针对最终任务(安全驾驶)进行了联合优化,因此在模块边界处不会丢失信息。感知模块学习提取规划器确切需要的特征,而不是可能无法捕捉任务相关细节的通用物体检测结果。
-
UniAD(统一自动驾驶)是一个里程碑式的端到端架构。它通过BEV编码器处理多摄像头图像,然后应用一系列基于Transformer的模块:跟踪、在线建图、运动预测、占用预测和规划。尽管它有内部模块,但它们都是可微分的,并且以端到端方式联合训练,规划损失通过整个网络反向传播。
-
UniAD中的规划模块通过关注预测的BEV特征、预测的参与者的轨迹和预测的占用,来生成自车的未来路径点。这是多元链式法则(第3章)的实际应用:梯度从规划损失一直流回图像编码器,告诉感知特征如何对规划更有用。
-
最近的端到端方法使用了VLA风格的架构(本章文件3)。像 DriveVLM 这样的模型接收摄像头图像和导航指令(或路线),并使用VLM主干生成驾驶动作。这带来了大规模预训练的好处(视觉理解、推理)直接进入驾驶技术栈。
-
端到端驾驶的矛盾在于可解释性。模块化系统可以报告“我在 (x, y) 检测到一个行人并预测他会横穿”——故障模式是可诊断的。端到端系统是一个产生转向角的黑盒。当它失败时,诊断原因很困难,这对安全认证是一个严重的担忧。
用于驾驶的世界模型¶
-
世界模型 学习根据当前状态和自车动作来预测驾驶场景的未来状态:\(p(s_{t+1} \mid s_t, a_t)\)(如第10章所述)。在驾驶中,这意味着生成真实的未来帧或BEV布局:“如果我加速并向左打方向,3秒后场景会像这样”。
-
世界模型为自动驾驶提供了两种强大的能力:
-
基于想象的规划:规划器不必承诺一个动作并等待结果,而是可以通过在世界模型中展开多个候选轨迹来“想象”它们,评估每条轨迹的安全性和舒适性,然后选择最佳的。这是基于模型的强化学习(本章文件2)在驾驶领域的应用。
-
学习到的仿真:在真实驾驶数据上训练的世界模型本质上是一个数据驱动的仿真器。它可以生成真实的场景(包括罕见的边界情况),而无需手动构建仿真器。至关重要的是,它捕捉了真实驾驶的统计模式:其他驾驶员实际的行为方式、光照如何变化、雨如何影响能见度。
-
-
GAIA-1(Wayve)是一个用于驾驶的生成式世界模型。给定过去一系列摄像头帧和自车动作,它自回归地生成未来的视频帧。它使用以动作为条件的视频扩散架构。该模型学会生成合理的未来:遵守交通规则的车辆、在人行道上行走的行人、正确转换的交通灯,所有这些都是从训练数据中涌现出来的,而不是通过编程规则设定的。
-
DriveDreamer 和 GenAD 采用了类似的方法,但在BEV空间而非像素空间中进行操作。预测未来的BEV布局比生成完整的视频帧更紧凑(类似于机器人领域的DreamerV3在潜在空间而非像素空间中进行预测,如文件2所述)。BEV世界模型预测所有参与者将去向何处、道路结构将是什么样子、自由空间在哪里,规划器直接使用这些信息。
-
神经闭环仿真 使用世界模型替代手工构建的仿真器进行测试。以真实驾驶日志为起点,世界模型生成如果自车采取了不同动作会发生什么。这使得能够进行反事实评估:“如果我晚刹0.5秒会怎样?”,而无需物理上重现该场景。
-
这与 JEPA 框架(第10章)的联系很自然。驾驶世界模型不需要预测完美的像素级未来(每个像素的确切RGB值)。它们只需要预测对规划重要的方面:参与者在哪、移动速度多快、自由空间在哪里。嵌入空间预测(JEPA风格)捕捉这些语义上有意义的属性,而不会在无关的视觉细节(如确切的云纹理)上浪费容量。
-
主要的挑战是长时域保真度。世界模型会随时间累积误差:第2帧的一个小错误会偏移所有后续帧。对于驾驶,3秒的预测视界对战术决策(我现在应该汇入吗?)有用,但30秒视界(对于路线规划等战略决策所需)仍然不可靠。目前的工作通过重新锚定(定期用真实观测重置模型)和不确定性估计(当预测变得不可靠时标记出来)来缓解这一问题。
仿真¶
-
通过在实际道路上驾驶来测试自动驾驶汽车是必要的,但还不够。危险场景(接近碰撞、边缘情况)很少见,因此按驾驶里程测试效率低下。一辆车需要行驶数亿英里才能在统计上证明其安全性,这是不可行的。
-
仿真 提供了无限、可控且安全的测试。在现实世界中罕见的场景(儿童跑上马路、轮胎爆裂、突然出现的障碍物)可以在仿真中测试数百万次。
-
CARLA 是一个基于Unreal Engine构建的开源驾驶仿真器。它提供了真实的城市环境、动态天气、交通参与者和传感器仿真(摄像头、激光雷达、雷达)。研究人员使用CARLA训练基于强化学习的驾驶智能体并评估感知算法。
-
nuPlan(Motional)是一个闭环规划基准。与开环评估(回放记录的数据并将规划器的输出与人类驾驶员的实际轨迹进行比较)不同,闭环评估允许规划器的决策影响仿真:如果规划器决定变道,仿真就会相应地演变。这测试的是响应性行为,而不仅仅是轨迹相似性。
-
开环 与 闭环 评估的区别至关重要:
-
开环:回放录制的场景,计算模型输出与人类驾驶员动作的相似度。这很容易设置,但具有误导性:一个总是预测“直行”的模型在高速公路上可能有低误差,但在第一个转弯处就会撞车。
-
闭环:模型的动作改变仿真状态,仿真随之演变。这测试了模型从自身错误中恢复并对动态情况做出反应的能力。它成本高得多,但也更有意义。
-
-
场景生成 创建压力测试用例。对抗性场景(一辆车突然刹车、一个行人藏在停泊的汽车后面)通过优化使自动驾驶系统表现最差的情况来生成。这与机器学习中的对抗训练(第6章)相关:找到使损失最大化的输入。
安全性¶
-
自动驾驶的安全性由工程标准指导,而不仅仅是机器学习指标。
-
ISO 26262(功能安全)是安全关键汽车电子系统的标准。它定义了汽车安全完整性等级,从A(最低)到D(最高),基于潜在危害的严重性、暴露率和可控性。自动驾驶系统的感知和规划组件通常是最高等级ASIL-D,需要广泛的验证、冗余和故障安全设计。
-
SOTIF(预期功能安全,ISO 21448)处理另一类危险:不是硬件故障(这是ISO 26262覆盖的),而是系统按设计工作但仍然产生不安全结果的情况。一个将白色卡车误认为是天空的感知模型(真实发生的事件)就是一个SOTIF问题:硬件工作正常,但算法的局限性导致了危险。
-
运行设计域 定义了自动驾驶系统被设计为运行的条件:特定的地理区域、道路类型(仅高速公路、城市道路、两者兼有)、天气条件(无大雪)、速度范围以及一天中的时间。在ODD之外操作是不允许的:如果系统无法处理雪地,它就不能在雪地中行驶。
-
故障安全 与 故障运行 设计:
- 故障安全:当检测到故障时,系统转换到安全状态(例如,靠边停车)。这是最低要求。
- 故障运行:尽管存在故障,系统仍使用冗余组件继续安全运行。一辆具有冗余转向、制动和计算的自动驾驶汽车可以在单个组件故障后幸存,并仍然行驶到安全地点。
-
冗余 是基础。关键的感知传感器是重复的:多个摄像头覆盖重叠的视野,激光雷达和雷达都提供独立的深度测量,双计算平台运行相同的软件。如果任何一个组件发生故障,其他组件能提供足够的信息来安全驾驶。
自动驾驶等级¶
-
SAE J3016 标准定义了六个驾驶自动化等级,从0(无自动化)到5(完全自动化):
-
等级0(无自动化):人类完成所有驾驶任务。系统可能提供警告(车道偏离预警),但不控制车辆。
-
等级1(驾驶员辅助):系统控制转向或速度之一,但不能同时控制两者。自适应巡航控制(保持速度和跟车距离)或车道保持辅助(使车辆保持在车道中心)属于等级1。
-
等级2(部分自动化):系统同时控制转向和速度,但人类必须时刻监控并随时准备接管。特斯拉Autopilot、通用汽车Super Cruise以及目前大多数“自动驾驶”功能都属于等级2。人类仍然是负责的驾驶员。
-
等级3(有条件自动化):系统在特定条件下(其ODD内)驾驶并监控环境。人类可以脱手,但必须在系统请求时准备好接管(有时间缓冲,通常为10秒以上)。梅赛德斯-奔驰Drive Pilot(在某些高速公路上,低于60公里/小时)是第一个获得认证的等级3系统。
-
等级4(高度自动化):系统在其ODD内驾驶并处理所有情况,无需人类干预。如果遇到其ODD之外的情况,它可以安全地自行停车。Waymo的机器人出租车服务在特定地理区域内以等级4运行。
-
等级5(完全自动化):系统在所有条件下、在人类能开的任何地方驾驶。不需要方向盘或踏板。这目前尚不存在。
-
-
关键区别在于谁对安全负责。在等级0-2,人类负责。在等级3-5,系统负责(在其ODD内)。这具有深刻的法律、保险和伦理意义。
-
当前行业状况是等级2(广泛部署)、等级3(开始部署)和等级4(有限地理部署)的混合。等级5仍然是一个长期研究目标。
编程任务(使用CoLab或notebook)¶
-
实现一个简单的轨迹优化规划器。给定起始位置、目标和一个障碍物,使用梯度下降找到最平滑的无碰撞路径。
import jax import jax.numpy as jnp import matplotlib.pyplot as plt # 轨迹:N个路径点,每个 (x, y) N = 20 start = jnp.array([0.0, 0.0]) goal = jnp.array([10.0, 0.0]) obstacle = jnp.array([5.0, 0.0]) obs_radius = 1.5 # 初始化:从起点到终点的直线 waypoints_init = jnp.linspace(start, goal, N) def cost(waypoints): wp = jnp.concatenate([start[None], waypoints, goal[None]], axis=0) # 平滑性:惩罚加速度(二阶差分) accel = wp[2:] - 2 * wp[1:-1] + wp[:-2] smooth_cost = jnp.sum(accel ** 2) # 避障:惩罚接近程度 dists = jnp.linalg.norm(wp - obstacle, axis=1) collision_cost = jnp.sum(jnp.maximum(0, obs_radius + 0.5 - dists) ** 2) return 10 * smooth_cost + 100 * collision_cost grad_cost = jax.grad(cost) # 优化内部路径点 waypoints = waypoints_init[1:-1] lr = 0.01 for _ in range(500): g = grad_cost(waypoints) waypoints = waypoints - lr * g # 绘图 full_path = jnp.concatenate([start[None], waypoints, goal[None]], axis=0) theta = jnp.linspace(0, 2 * jnp.pi, 100) plt.figure(figsize=(10, 4)) plt.plot(full_path[:, 0], full_path[:, 1], "b.-", label="优化后的路径") plt.plot(waypoints_init[:, 0], waypoints_init[:, 1], "r--", alpha=0.5, label="初始路径(直线)") plt.fill(obstacle[0] + obs_radius * jnp.cos(theta), obstacle[1] + obs_radius * jnp.sin(theta), alpha=0.3, color="red", label="障碍物") plt.plot(*start, "go", markersize=10); plt.plot(*goal, "g*", markersize=15) plt.legend(); plt.axis("equal"); plt.grid(True) plt.title("轨迹优化:平滑无碰撞路径") plt.show() -
模拟一个匀速运动预测模型,并与转弯车辆的真实轨迹进行比较。
import jax.numpy as jnp import matplotlib.pyplot as plt # 真实轨迹:右转车辆 dt = 0.1 T = 40 # 4秒 v = 10.0 # 米/秒 omega = 0.3 # 弧度/秒(转弯速率) # 真实轨迹(恒定转弯速率) t = jnp.arange(T) * dt theta = omega * t gt_x = (v / omega) * jnp.sin(theta) gt_y = (v / omega) * (1 - jnp.cos(theta)) # 从t=0开始的匀速预测 # 假设车辆保持初始航向直行 obs_steps = 10 # 观测前1秒 vx0 = v * jnp.cos(theta[obs_steps - 1]) vy0 = v * jnp.sin(theta[obs_steps - 1]) pred_t = jnp.arange(T - obs_steps) * dt pred_x = gt_x[obs_steps - 1] + vx0 * pred_t pred_y = gt_y[obs_steps - 1] + vy0 * pred_t plt.figure(figsize=(8, 6)) plt.plot(gt_x[:obs_steps], gt_y[:obs_steps], "ko-", label="观测到的轨迹") plt.plot(gt_x[obs_steps:], gt_y[obs_steps:], "g-", linewidth=2, label="真实未来轨迹") plt.plot(pred_x, pred_y, "r--", linewidth=2, label="匀速预测") plt.legend(); plt.axis("equal"); plt.grid(True) plt.xlabel("x (米)"); plt.ylabel("y (米)") plt.title("匀速预测 vs 转弯车辆") plt.show() -
实现一个简单的基于规则的规划器,根据检测到的障碍物决定是保持车道还是停车。
import jax.numpy as jnp def rule_based_planner(ego_speed, obstacles, speed_limit=13.9): """ 简单的基于规则的规划器。 ego_speed: 当前车速(米/秒) obstacles: 前方障碍物的 (距离, 速度) 元组列表 speed_limit: 最大允许速度(米/秒),默认约50公里/小时 返回: (目标速度, 动作标签) """ min_following_distance = 2.0 * ego_speed # 2秒规则 emergency_distance = 5.0 # 米 if not obstacles: return speed_limit, "巡航" # 找到前方最近的障碍物 closest_dist, closest_speed = min(obstacles, key=lambda o: o[0]) if closest_dist < emergency_distance: return 0.0, "紧急停车" elif closest_dist < min_following_distance: # 匹配前车速度 target = min(closest_speed, speed_limit) return target, "跟车" else: return speed_limit, "巡航" # 测试场景 scenarios = [ (13.9, [], "道路空旷"), (13.9, [(30.0, 10.0)], "前方有慢车"), (13.9, [(3.0, 0.0)], "非常接近静止车辆"), (13.9, [(50.0, 13.9)], "前方车辆速度相同"), ] for speed, obs, desc in scenarios: target, action = rule_based_planner(speed, obs) print(f"{desc:30s} → {action:15s} target_speed={target:.1f} 米/秒 ({target*3.6:.0f} 公里/小时)")