目录
- 第一部分:自动驾驶仿真概述
- 第一章:为什么需要自动驾驶仿真
- 第二章:仿真平台分类与对比
- 第三章:仿真系统架构
- 第二部分:主流仿真平台详解
- 第四章:CARLA------最完整的开源仿真平台
- 第五章:SUMO------交通流仿真
- 第六章:AirSim------无人机与自动驾驶仿真
- 第七章:LGSVL------高保真仿真
- 第八章:NVIDIA DRIVE Sim 与 Omniverse
- 第三部分:传感器仿真
- 第九章:相机仿真
- 第十章:激光雷达(LiDAR)仿真
- 第十一章:毫米波雷达仿真
- 第十二章:多传感器融合仿真
- 第四部分:场景与交通仿真
- 第十三章:场景描述语言
- 第十四章:交通流生成
- 第十五章:对抗性场景生成
- 第十六章:基于学习的场景生成
- 第五部分:仿真与真实世界
- 第十七章:Sim-to-Real 迁移
- 第十八章:仿真验证与测试
- 第十九章:仿真驱动的开发流程
- 第六部分:代码实践
- 第二十章:CARLA Python API 实战
- 第二十一章:传感器数据处理
- 第二十二章:场景构建与测试
- 附录
第一部分:自动驾驶仿真概述
第一章:为什么需要自动驾驶仿真
1.1 自动驾驶测试的挑战
1.1.1 里程测试的不可行性
问题:自动驾驶系统需要在各种场景下测试安全性。
数据:
| 指标 | 数值 |
|---|---|
| 人类驾驶员致命事故率 | ~1.1 次/亿英里 |
| 要证明比人类安全 10 倍 | 需要 ~100 亿英里测试 |
| 以 100 辆车、每天 24 小时测试 | 需要 ~500 年 |
结论:纯路测无法验证自动驾驶的安全性------必须依赖仿真。
1.1.2 长尾问题
定义 1.1(长尾场景):在真实驾驶中,99% 的场景是常见的(直行、转弯、跟车),但 1% 的场景是罕见但关键的(行人突然冲出、逆行车辆、恶劣天气)。
问题:路测很难遇到这些长尾场景------但自动驾驶系统必须能处理它们。
仿真优势 :可以系统性地生成各种长尾场景,确保覆盖。
1.1.3 安全性要求
定义 1.2(功能安全) :ISO 26262 标准要求汽车电子系统的失效率低于 10−710^{-7}10−7/小时(ASIL D 级别)。
仿真作用:
- 单元测试:测试各个模块(感知、规划、控制)
- 集成测试:测试模块间的交互
- 系统测试:测试完整的自动驾驶系统
- 回归测试:确保新版本不引入 bug
1.2 仿真的优势
| 优势 | 说明 | 量化指标 |
|---|---|---|
| 安全性 | 测试危险场景不会造成实际损害 | 0 人员风险 |
| 可重复性 | 精确重复同一场景 | 100% 可重复 |
| 效率 | 比路测快 1000 倍以上 | 1000x 加速 |
| 覆盖性 | 可以生成任意场景 | 100% 场景覆盖 |
| 成本 | 比路测便宜 100 倍以上 | 100x 成本降低 |
| 并行化 | 可以同时运行多个仿真 | 1000+ 并发 |
1.3 仿真的分类
| 类型 | 说明 | 精度 | 速度 | 代表 |
|---|---|---|---|---|
| 软件在环(SIL) | 纯软件仿真 | 中 | 快 | CARLA |
| 硬件在环(HIL) | 真实硬件 + 仿真环境 | 高 | 中 | dSPACE |
| 车辆在环(VIL) | 真实车辆 + 虚拟场景 | 最高 | 慢 | 测试场 |
| 模型在环(MIL) | 算法模型测试 | 低 | 最快 | MATLAB |
第二章:仿真平台分类与对比
2.1 主流仿真平台
| 平台 | 开发者 | 开源 | 主要用途 | 渲染引擎 | 语言 |
|---|---|---|---|---|---|
| CARLA | Intel/CVC | ✅ | 自动驾驶全栈 | Unreal Engine | Python/C++ |
| SUMO | DLR | ✅ | 交通流仿真 | 无(宏观) | Python/C++ |
| AirSim | Microsoft | ✅ | 无人机/自动驾驶 | Unreal Engine | Python/C++ |
| LGSVL | LG | ✅ | 自动驾驶 | Unity | Python/C++ |
| NVIDIA DRIVE Sim | NVIDIA | ❌ | 自动驾驶 | Omniverse | Python/C++ |
| Waymo Open Sim | Waymo | 部分 | 自动驾驶 | 自研 | Python |
| MetaDrive | PKU | ✅ | 强化学习 | Panda3D | Python |
| nuPlan | Motional | 部分 | 规划测试 | 自研 | Python |
| OpenSCENARIO | ASAM | 标准 | 场景描述 | N/A | XML |
2.2 平台对比矩阵
2.2.1 功能对比
| 功能 | CARLA | SUMO | AirSim | LGSVL | DRIVE Sim |
|---|---|---|---|---|---|
| 3D 渲染 | ✅ | ❌ | ✅ | ✅ | ✅ |
| 相机仿真 | ✅ | ❌ | ✅ | ✅ | ✅ |
| LiDAR 仿真 | ✅ | ❌ | ✅ | ✅ | ✅ |
| 雷达仿真 | ✅ | ❌ | ❌ | ✅ | ✅ |
| 交通流 | ✅ | ✅ | ❌ | ✅ | ✅ |
| 行人仿真 | ✅ | ❌ | ❌ | ✅ | ✅ |
| 天气系统 | ✅ | ❌ | ✅ | ✅ | ✅ |
| 地图编辑器 | ✅ | ✅ | ❌ | ✅ | ✅ |
| Python API | ✅ | ✅ | ✅ | ✅ | ✅ |
| ROS 集成 | ✅ | ✅ | ✅ | ✅ | ✅ |
2.2.2 性能对比
| 指标 | CARLA | SUMO | AirSim | LGSVL |
|---|---|---|---|---|
| 渲染帧率 | 30-60 FPS | N/A | 30-60 FPS | 30-60 FPS |
| 仿真速度 | 实时 | 10x 实时 | 实时 | 实时 |
| 最大车辆数 | 100+ | 10000+ | 10+ | 100+ |
| 最大地图 | 10km² | 无限 | 10km² | 100km² |
| GPU 需求 | 高 | 低 | 高 | 高 |
第三章:仿真系统架构
3.1 典型仿真系统架构
┌─────────────────────────────────────────────────────────────┐
│ 自动驾驶仿真系统 │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 场景管理 │ │ 交通仿真 │ │ 传感器 │ │ 环境仿真 │ │
│ │ │ │ │ │ 仿真 │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 渲染引擎 │ │
│ │ (Unreal Engine / Unity / Omniverse) │ │
│ └──────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 物理引擎 │ │
│ │ (碰撞检测、刚体动力学) │ │
│ └──────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 自动驾驶 │ │ 数据记录 │ │ 评估 │ │ 可视化 │ │
│ │ 算法接口 │ │ 与回放 │ │ 与报告 │ │ 与调试 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
3.2 核心模块
3.2.1 场景管理模块
功能:
- 场景加载与初始化
- 场景元素管理(车辆、行人、交通标志)
- 场景状态更新
- 场景重置与回放
3.2.2 交通仿真模块
功能:
- 交通流生成
- 车辆行为模型
- 交通信号控制
- 行人行为模拟
3.2.3 传感器仿真模块
功能:
- 相机图像渲染
- LiDAR 点云生成
- 雷达目标检测
- GPS/IMU 仿真
3.2.4 环境仿真模块
功能:
- 天气系统(雨、雪、雾)
- 光照变化(白天、夜晚)
- 路面状态(干燥、湿滑)
- 动态障碍物
第二部分:主流仿真平台详解
第四章:CARLA------最完整的开源仿真平台
4.1 CARLA 概述
4.1.1 简介
CARLA(Car Learning to Act)是由 Intel 和巴塞罗那计算机视觉中心(CVC)开发的开源自动驾驶仿真平台。
特点:
- 基于 Unreal Engine 4 的高保真渲染
- 丰富的传感器仿真(相机、LiDAR、雷达、语义分割)
- 灵活的场景定制
- Python/C++ API
- 支持 ROS/ROS2
4.1.2 CARLA 的版本历史
| 版本 | 发布时间 | 主要特性 |
|---|---|---|
| 0.8 | 2018 | 基础功能 |
| 0.9 | 2019 | 新 API、多城镇 |
| 0.9.10 | 2020 | OpenDRIVE 支持 |
| 0.9.12 | 2021 | 改进的交通管理 |
| 0.9.14 | 2022 | RSS 安全模型 |
| 0.9.15 | 2023 | 性能优化 |
4.2 CARLA 架构
4.2.1 系统架构
┌─────────────────────────────────────────────┐
│ CARLA Server │
│ ┌─────────────────────────────────────┐ │
│ │ Unreal Engine 4 │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │ 场景 │ │ 渲染 │ │ 物理 │ │ │
│ │ └──────┘ └──────┘ └──────┘ │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ CARLA Core │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │传感器│ │ 交通 │ │ 场景 │ │ │
│ │ │ 仿真 │ │ 管理 │ │ 管理 │ │ │
│ │ └──────┘ └──────┘ └──────┘ │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
│
│ TCP/IP
│
┌─────────────────────────────────────────────┐
│ CARLA Client │
│ ┌─────────────────────────────────────┐ │
│ │ Python/C++ API │ │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ 自动驾驶算法 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
4.2.2 世界(World)
定义 4.1(World):CARLA 中的 World 代表整个仿真环境,包含:
- 地图(Map)
- 天气(Weather)
- 光照(Lighting)
- 所有 Actor
4.2.3 Actor
定义 4.2(Actor):仿真中的动态对象,包括:
- 车辆(Vehicle)
- 行人(Walker)
- 传感器(Sensor)
- 交通标志(Traffic Sign)
- 交通信号灯(Traffic Light)
4.2.4 地图
CARLA 内置地图:
| 地图 | 描述 | 大小 |
|---|---|---|
| Town01 | 小镇 | 1km² |
| Town02 | 小镇(更简单) | 0.5km² |
| Town03 | 城市 | 2km² |
| Town04 | 高速公路 | 5km² |
| Town05 | 城市(复杂) | 3km² |
| Town06 | 高速公路(长) | 10km² |
| Town07 | 乡村 | 2km² |
| Town10 | 城市(新) | 3km² |
| Town11 | 大型城市 | 10km² |
| Town12 | 大型城市 | 10km² |
| Town13 | 大型城市 | 10km² |
| Town14 | 大型城市 | 10km² |
| Town15 | 大型城市 | 10km² |
4.3 CARLA 传感器系统
4.3.1 传感器类型
| 传感器 | 输出 | 频率 | 用途 |
|---|---|---|---|
| RGB Camera | 图像 | 30 FPS | 感知 |
| Semantic Segmentation | 语义图 | 30 FPS | 训练 |
| Depth Camera | 深度图 | 30 FPS | 3D 感知 |
| Instance Segmentation | 实例图 | 30 FPS | 目标检测 |
| LiDAR | 点云 | 10-20 FPS | 3D 感知 |
| Semantic LiDAR | 语义点云 | 10-20 FPS | 3D 语义 |
| Radar | 目标列表 | 20 FPS | 目标检测 |
| GNSS | 位置 | 10 FPS | 定位 |
| IMU | 加速度/角速度 | 100 FPS | 惯性导航 |
| Collision | 碰撞事件 | 实时 | 安全检测 |
| Lane Invasion | 车道偏离 | 实时 | 车道保持 |
4.3.2 相机模型
针孔相机模型:
(uv1)=1Z(fx0cx0fycy001)(XYZ)\begin{pmatrix} u \\ v \\ 1 \end{pmatrix} = \frac{1}{Z} \begin{pmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} X \\ Y \\ Z \end{pmatrix} uv1 =Z1 fx000fy0cxcy1 XYZ
其中:
- (u,v)(u, v)(u,v):像素坐标
- (X,Y,Z)(X, Y, Z)(X,Y,Z):3D 坐标
- fx,fyf_x, f_yfx,fy:焦距
- cx,cyc_x, c_ycx,cy:主点
4.3.3 LiDAR 仿真
CARLA LiDAR 参数:
| 参数 | 说明 | 典型值 |
|---|---|---|
| channels | 激光通道数 | 32, 64, 128 |
| range | 最大探测距离 | 100m |
| points_per_second | 每秒点数 | 100K-3M |
| rotation_frequency | 旋转频率 | 10-20 Hz |
| upper_fov | 上视场角 | 15°-30° |
| lower_fov | 下视场角 | -25°--15° |
LiDAR 点云生成:
python
# CARLA LiDAR 配置示例
lidar_bp = world.get_blueprint_library().find('sensor.lidar.ray_cast')
lidar_bp.set_attribute('channels', '64')
lidar_bp.set_attribute('range', '100')
lidar_bp.set_attribute('points_per_second', '1200000')
lidar_bp.set_attribute('rotation_frequency', '10')
lidar_bp.set_attribute('upper_fov', '15')
lidar_bp.set_attribute('lower_fov', '-25')
4.4 CARLA 交通系统
4.4.1 交通管理器(Traffic Manager)
功能:
- 自动生成交通流
- 控制 NPC 车辆行为
- 交通信号灯控制
- 碰撞避免
行为参数:
| 参数 | 说明 | 范围 |
|---|---|---|
| speed_limit_percentage | 超速百分比 | 0-100 |
| distance_to_leading_vehicle | 跟车距离 | 1-10m |
| ignore_lights_percentage | 闯红灯概率 | 0-100 |
| ignore_signs_percentage | 忽略标志概率 | 0-100 |
| ignore_walkers_percentage | 忽略行人概率 | 0-100 |
| random_left_lanechange_percentage | 随机变道(左)概率 | 0-100 |
| random_right_lanechange_percentage | 随机变道(右)概率 | 0-100 |
4.4.2 车辆行为模型
IDM(Intelligent Driver Model):
v˙=a1−(vv0)δ−(s∗(v,Δv)s)2\dot{v} = a \left1 - \\left(\\frac{v}{v_0}\\right)\^\\delta - \\left(\\frac{s\^\*(v, \\Delta v)}{s}\\right)\^2\\rightv˙=a1−(v0v)δ−(ss∗(v,Δv))2
其中:
s∗(v,Δv)=s0+vT+vΔv2abs^*(v, \Delta v) = s_0 + vT + \frac{v \Delta v}{2\sqrt{ab}}s∗(v,Δv)=s0+vT+2ab vΔv
- v0v_0v0:期望速度
- s0s_0s0:最小间距
- TTT:期望时间头距
- aaa:最大加速度
- bbb:舒适减速度
- δ\deltaδ:加速度指数
MOBIL(Minimizing Overall Braking Induced by Lane change):
a~c−ac+p(a~n−an+a~o−ao)>ath\tilde{a}c - a_c + p(\tilde{a}n - a_n + \tilde{a}{o} - a{o}) > a_{\text{th}}a~c−ac+p(a~n−an+a~o−ao)>ath
其中:
- a~c\tilde{a}_ca~c:变道后自车加速度
- aca_cac:当前自车加速度
- a~n,an\tilde{a}_n, a_na~n,an:新后车加速度变化
- a~o,ao\tilde{a}{o}, a{o}a~o,ao:旧后车加速度变化
- ppp:礼貌系数
- atha_{\text{th}}ath:变道阈值
第五章:SUMO------交通流仿真
5.1 SUMO 概述
5.1.1 简介
SUMO(Simulation of Urban MObility)是由德国航空航天中心(DLR)开发的开源交通流仿真器。
特点:
- 微观交通仿真(每辆车独立控制)
- 支持大规模网络(10000+ 车辆)
- 多种交通模式(车辆、行人、公共交通)
- 丰富的 API(TraCI)
- 与 CARLA 集成
5.1.2 SUMO vs CARLA
| 特性 | SUMO | CARLA |
|---|---|---|
| 渲染 | 无 3D 渲染 | 高保真 3D |
| 交通仿真 | 专业级 | 基础级 |
| 规模 | 10000+ 车辆 | 100+ 车辆 |
| 传感器 | 无 | 完整 |
| 速度 | 10x 实时 | 实时 |
| 用途 | 交通分析 | 自动驾驶测试 |
5.2 SUMO 网络
5.2.1 路网元素
| 元素 | 说明 | XML 标签 |
|---|---|---|
| Edge | 道路 | <edge> |
| Lane | 车道 | <lane> |
| Junction | 交叉口 | <junction> |
| Connection | 连接 | <connection> |
| Traffic Light | 信号灯 | <tlLogic> |
5.2.2 路网文件格式
xml
<!-- SUMO 路网文件示例 -->
<net>
<edge id="edge1" from="node1" to="node2">
<lane id="edge1_0" index="0" speed="13.89" length="100"/>
<lane id="edge1_1" index="1" speed="13.89" length="100"/>
</edge>
<junction id="node1" type="priority" x="0" y="0"/>
<junction id="node2" type="traffic_light" x="100" y="0"/>
<tlLogic id="node2" type="static" programID="0">
<phase duration="30" state="GGrr"/>
<phase duration="5" state="yyrr"/>
<phase duration="30" state="rrGG"/>
<phase duration="5" state="rryy"/>
</tlLogic>
</net>
5.3 SUMO 车辆模型
5.3.1 跟车模型
Krauss 模型:
vsafe=vl+g−vlτv+vl2b+τv_{\text{safe}} = v_l + \frac{g - v_l \tau}{\frac{v + v_l}{2b} + \tau}vsafe=vl+2bv+vl+τg−vlτ
vdes=min(vmax,v+aτ,vsafe)v_{\text{des}} = \min(v_{\max}, v + a\tau, v_{\text{safe}})vdes=min(vmax,v+aτ,vsafe)
vnew=max(0,vdes−η⋅a⋅τ)v_{\text{new}} = \max(0, v_{\text{des}} - \eta \cdot a \cdot \tau)vnew=max(0,vdes−η⋅a⋅τ)
其中:
- vlv_lvl:前车速度
- ggg:与前车的间距
- τ\tauτ:反应时间
- bbb:最大减速度
- η\etaη:随机扰动参数
5.3.2 变道模型
LC2013 模型:
| 参数 | 说明 | 默认值 |
|---|---|---|
| lcStrategic | 战略变道 | 1.0 |
| lcCooperative | 合作变道 | 1.0 |
| lcSpeedGain | 速度收益 | 1.0 |
| lcKeepRight | 靠右行驶 | 1.0 |
| lcAssertive | 主动程度 | 1.0 |
| lcPushy | 强制程度 | 0.0 |
5.4 TraCI API
5.4.1 基本操作
python
import traci
# 连接 SUMO
traci.start(["sumo-gui", "-c", "config.sumocfg"])
# 仿真循环
while traci.simulation.getMinExpectedNumber() > 0:
# 获取所有车辆
vehicles = traci.vehicle.getIDList()
for veh_id in vehicles:
# 获取位置
pos = traci.vehicle.getPosition(veh_id)
# 获取速度
speed = traci.vehicle.getSpeed(veh_id)
# 获取车道
lane = traci.vehicle.getLaneID(veh_id)
# 仿真步进
traci.step()
traci.close()
第六章:AirSim------无人机与自动驾驶仿真
6.1 AirSim 概述
6.1.1 简介
AirSim(Aerial Informatics and Robotics Simulation)是由 Microsoft 开发的开源仿真平台。
特点:
- 支持无人机和自动驾驶
- 基于 Unreal Engine 的高保真渲染
- 丰富的传感器(相机、LiDAR、IMU、GPS)
- Python/C++ API
- 支持强化学习
6.1.2 AirSim 的 API
python
import airsim
# 连接
client = airsim.CarClient()
client.confirmConnection()
# 获取图像
responses = client.simGetImages([
airsim.ImageRequest("0", airsim.ImageType.Scene),
airsim.ImageRequest("0", airsim.ImageType.DepthPlanar),
])
# 控制车辆
car_controls = airsim.CarControls()
car_controls.throttle = 0.5
car_controls.steering = 0.1
client.setCarControls(car_controls)
第七章:LGSVL------高保真仿真
7.1 LGSVL 概述
7.1.1 简介
LGSVL Simulator 是由 LG Electronics 开发的自动驾驶仿真平台。
特点:
- 高保真 3D 渲染(Unity)
- 支持多种传感器
- 与 Apollo/Autoware 集成
- 云端仿真支持
- 场景编辑器
7.1.2 LGSVL 的传感器
| 传感器 | 参数 | 输出 |
|---|---|---|
| Camera | 分辨率、FOV | RGB 图像 |
| LiDAR | 通道、范围 | 点云 |
| Radar | 范围、FOV | 目标列表 |
| Ultrasonic | 范围 | 距离 |
| GPS | 精度 | 位置 |
| IMU | 频率 | 加速度/角速度 |
| CAN Bus | - | 车辆状态 |
第八章:NVIDIA DRIVE Sim 与 Omniverse
8.1 NVIDIA DRIVE Sim
8.1.1 简介
NVIDIA DRIVE Sim 是基于 Omniverse 构建的自动驾驶仿真平台。
特点:
- 物理级精确渲染(RTX 光线追踪)
- 传感器仿真(相机、LiDAR、雷达)
- 场景生成工具
- 云端大规模仿真
- 与 NVIDIA DRIVE 平台集成
8.1.2 Omniverse 技术栈
┌─────────────────────────────────────┐
│ NVIDIA DRIVE Sim │
├─────────────────────────────────────┤
│ Omniverse Kit │
│ (场景编辑、资产管理、仿真控制) │
├─────────────────────────────────────┤
│ Omniverse RTX │
│ (光线追踪渲染、物理仿真) │
├─────────────────────────────────────┤
│ PhysX 5 │
│ (刚体动力学、碰撞检测) │
├─────────────────────────────────────┤
│ CUDA / TensorRT │
│ (GPU 计算、AI 推理) │
└─────────────────────────────────────┘
8.2 传感器仿真技术
8.2.1 光线追踪相机
原理:从相机位置发射光线,计算光线与场景的交点,得到像素颜色。
优势:
- 真实的光照效果
- 准确的反射和折射
- 精确的阴影
8.2.2 LiDAR 物理仿真
考虑因素:
- 激光束的发射角度
- 物体表面的反射特性
- 大气衰减
- 多路径反射
- 串扰
第三部分:传感器仿真
第九章:相机仿真
9.1 相机模型
9.1.1 针孔相机模型
世界坐标到像素坐标的变换:
(uv1)=1ZcKR∣t(XwYwZw1)\begin{pmatrix} u \\ v \\ 1 \end{pmatrix} = \frac{1}{Z_c} K R \| t \begin{pmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{pmatrix} uv1 =Zc1KR∣t XwYwZw1
其中:
- KKK:内参矩阵
- R∣tR\|tR∣t:外参矩阵
- (Xw,Yw,Zw)(X_w, Y_w, Z_w)(Xw,Yw,Zw):世界坐标
- (u,v)(u, v)(u,v):像素坐标
9.1.2 畸变模型
径向畸变:
xdistorted=x(1+k1r2+k2r4+k3r6)x_{\text{distorted}} = x(1 + k_1 r^2 + k_2 r^4 + k_3 r^6)xdistorted=x(1+k1r2+k2r4+k3r6)
ydistorted=y(1+k1r2+k2r4+k3r6)y_{\text{distorted}} = y(1 + k_1 r^2 + k_2 r^4 + k_3 r^6)ydistorted=y(1+k1r2+k2r4+k3r6)
切向畸变:
xdistorted=x+2p1xy+p2(r2+2x2)x_{\text{distorted}} = x + 2p_1 xy + p_2(r\^2 + 2x\^2)xdistorted=x+2p1xy+p2(r2+2x2)
ydistorted=y+p1(r2+2y2)+2p2xyy_{\text{distorted}} = y + p_1(r\^2 + 2y\^2) + 2p_2 xyydistorted=y+p1(r2+2y2)+2p2xy
9.2 图像渲染技术
9.2.1 光栅化渲染
流程:
- 顶点变换(模型 → 世界 → 相机 → 裁剪 → 屏幕)
- 三角形装配
- 光栅化(三角形 → 片元)
- 片元着色(计算像素颜色)
- 深度测试
9.2.2 光线追踪渲染
流程:
- 从相机发射光线
- 计算光线与场景的交点
- 计算交点处的着色(直接光照 + 间接光照)
- 递归追踪反射/折射光线
9.3 数据增强
9.3.1 图像增强方法
| 方法 | 说明 | 用途 |
|---|---|---|
| 颜色抖动 | 改变亮度、对比度、饱和度 | 鲁棒性 |
| 模糊 | 高斯模糊、运动模糊 | 模拟运动 |
| 噪声 | 高斯噪声、泊松噪声 | 模拟传感器噪声 |
| 遮挡 | 随机遮挡部分图像 | 鲁棒性 |
| 几何变换 | 旋转、缩放、平移 | 数据增强 |
第十章:激光雷达(LiDAR)仿真
10.1 LiDAR 原理
10.1.1 飞行时间(ToF)原理
距离计算:
d=c⋅Δt2d = \frac{c \cdot \Delta t}{2}d=2c⋅Δt
其中:
- ccc:光速(3×1083 \times 10^83×108 m/s)
- Δt\Delta tΔt:激光往返时间
10.1.2 LiDAR 参数
| 参数 | 说明 | 典型值 |
|---|---|---|
| 通道数 | 激光器数量 | 16, 32, 64, 128 |
| 探测距离 | 最大探测距离 | 100-300m |
| 精度 | 距离精度 | ±2cm |
| 垂直 FOV | 垂直视场角 | 25°-40° |
| 水平 FOV | 水平视场角 | 360° |
| 角分辨率 | 角度分辨率 | 0.1°-0.4° |
| 帧率 | 旋转频率 | 10-20 Hz |
| 点密度 | 每秒点数 | 300K-3M |
10.2 LiDAR 仿真方法
10.2.1 光线投射法
原理:从 LiDAR 位置发射光线,计算光线与场景的交点。
算法:
对每个激光通道 i:
对每个水平角度 θ:
计算光线方向 d = R(θ, φ_i) * [1, 0, 0]^T
计算光线与场景的交点
如果交点存在:
记录距离、强度、坐标
10.2.2 点云生成
极坐标到笛卡尔坐标:
x=dcosϕcosθx = d \cos\phi \cos\thetax=dcosϕcosθ
y=dcosϕsinθy = d \cos\phi \sin\thetay=dcosϕsinθ
z=dsinϕz = d \sin\phiz=dsinϕ
其中:
- ddd:距离
- ϕ\phiϕ:垂直角度
- θ\thetaθ:水平角度
10.3 LiDAR 噪声模型
10.3.1 距离噪声
dmeasured=dtrue+N(0,σd2)d_{\text{measured}} = d_{\text{true}} + \mathcal{N}(0, \sigma_d^2)dmeasured=dtrue+N(0,σd2)
其中 σd\sigma_dσd 通常为 1-3cm。
10.3.2 角度噪声
θmeasured=θtrue+N(0,σθ2)\theta_{\text{measured}} = \theta_{\text{true}} + \mathcal{N}(0, \sigma_\theta^2)θmeasured=θtrue+N(0,σθ2)
10.3.3 检测概率
Pdetect=exp(−d22dmax2)⋅ρP_{\text{detect}} = \exp\left(-\frac{d^2}{2d_{\max}^2}\right) \cdot \rhoPdetect=exp(−2dmax2d2)⋅ρ
其中 ρ\rhoρ 是表面反射率。
第十一章:毫米波雷达仿真
11.1 雷达原理
11.1.1 FMCW 雷达
调频连续波(FMCW):发射频率随时间线性变化的信号。
距离计算:
d=c⋅fb⋅Tc2Bd = \frac{c \cdot f_b \cdot T_c}{2B}d=2Bc⋅fb⋅Tc
其中:
- fbf_bfb:拍频
- TcT_cTc:调频周期
- BBB:带宽
速度计算:
v=c⋅fd2fcv = \frac{c \cdot f_d}{2f_c}v=2fcc⋅fd
其中:
- fdf_dfd:多普勒频移
- fcf_cfc:载波频率
11.1.2 雷达参数
| 参数 | 说明 | 典型值 |
|---|---|---|
| 探测距离 | 最大探测距离 | 150-300m |
| 距离精度 | 距离分辨率 | 0.1-0.5m |
| 速度精度 | 速度分辨率 | 0.1-0.5 m/s |
| 角度精度 | 角度分辨率 | 1°-3° |
| 更新率 | 数据更新频率 | 10-20 Hz |
| FOV | 视场角 | ±60° |
11.2 雷达仿真
11.2.1 目标检测仿真
雷达方程:
Pr=PtG2λ2σ(4π)3R4P_r = \frac{P_t G^2 \lambda^2 \sigma}{(4\pi)^3 R^4}Pr=(4π)3R4PtG2λ2σ
其中:
- PrP_rPr:接收功率
- PtP_tPt:发射功率
- GGG:天线增益
- λ\lambdaλ:波长
- σ\sigmaσ:雷达截面积(RCS)
- RRR:距离
11.2.2 RCS 模型
| 物体 | RCS (dBsm) | 说明 |
|---|---|---|
| 行人 | -10 | 小型目标 |
| 自行车 | -5 | 中型目标 |
| 轿车 | 10 | 大型目标 |
| 卡车 | 20 | 大型目标 |
第十二章:多传感器融合仿真
12.1 传感器标定
12.1.1 外参标定
问题:确定传感器之间的相对位姿。
方法:
- 使用棋盘格标定
- 使用特征点匹配
- 使用优化方法
12.1.2 时间同步
问题:不同传感器的时间戳可能不同步。
方法:
- 硬件同步(触发信号)
- 软件同步(时间戳对齐)
- 插值同步
12.2 融合算法仿真
12.2.1 早期融合
方法:在原始数据层融合。
优点:信息保留完整。
缺点:计算量大。
12.2.2 晚期融合
方法:在目标层融合。
优点:计算量小。
缺点:信息损失。
12.2.3 混合融合
方法:结合早期和晚期融合。
第四部分:场景与交通仿真
第十三章:场景描述语言
13.1 OpenSCENARIO
13.1.1 简介
OpenSCENARIO 是 ASAM(自动化和测量系统标准化协会)制定的场景描述标准。
用途:描述动态场景,包括车辆行为、交通信号、事件触发等。
13.1.2 OpenSCENARIO 结构
xml
<OpenSCENARIO>
<FileHeader/>
<ParameterDeclarations/>
<CatalogLocations/>
<RoadNetwork>
<LogicFile/>
<SceneGraphFile/>
</RoadNetwork>
<Entities>
<ObjectController>
<CatalogReference/>
</ObjectController>
</Entities>
<Storyboard>
<Init>
<Actions/>
</Init>
<Story>
<Act>
<Sequence>
<Maneuver>
<Event>
<Action>
<Private/>
</Action>
<StartTrigger/>
</Event>
</Maneuver>
</Sequence>
</Act>
</Story>
</Storyboard>
</OpenSCENARIO>
13.2 OpenDRIVE
13.2.1 简介
OpenDRIVE 是描述道路网络的标准格式。
元素:
- Road(道路)
- Junction(交叉口)
- Lane(车道)
- Signal(信号)
- Object(物体)
13.2.2 道路参考线
三次多项式:
y(x)=a+bx+cx2+dx3y(x) = a + bx + cx^2 + dx^3y(x)=a+bx+cx2+dx3
螺旋线(Clothoid):
κ(s)=κ0+sac\kappa(s) = \kappa_0 + \frac{s}{a_c}κ(s)=κ0+acs
其中 κ\kappaκ 是曲率,sss 是弧长。
第十四章:交通流生成
14.1 交通流理论
14.1.1 基本关系
流量-密度-速度关系:
q=k⋅vq = k \cdot vq=k⋅v
其中:
- qqq:流量(vehicles/hour)
- kkk:密度(vehicles/km)
- vvv:速度(km/h)
14.1.2 Greenshields 模型
v=vf(1−kkj)v = v_f \left(1 - \frac{k}{k_j}\right)v=vf(1−kjk)
其中:
- vfv_fvf:自由流速度
- kjk_jkj:阻塞密度
14.2 交通流生成方法
14.2.1 基于 OD 矩阵
方法:定义起点-终点(OD)矩阵,生成交通流。
python
# OD 矩阵示例
od_matrix = {
('A', 'B'): 100, # 从 A 到 B 的车辆数
('A', 'C'): 50,
('B', 'A'): 80,
('B', 'C'): 60,
}
14.2.2 基于流量数据
方法:使用真实交通流量数据生成仿真。
第十五章:对抗性场景生成
15.1 对抗性场景
15.1.1 定义
定义 15.1(对抗性场景):故意设计的、可能导致自动驾驶系统失败的场景。
15.1.2 场景类型
| 类型 | 说明 | 例子 |
|---|---|---|
| 切入 | 车辆突然切入 | 高速公路切入 |
| 切出 | 车辆突然切出 | 紧急避让 |
| 行人 | 行人突然出现 | 鬼探头 |
| 逆行 | 车辆逆行 | 逆行车辆 |
| 静止 | 静止障碍物 | 抛锚车辆 |
15.2 场景生成方法
15.2.1 基于规则
方法:定义规则生成场景。
15.2.2 基于优化
方法:使用优化算法搜索最危险的场景。
15.2.3 基于学习
方法:使用强化学习或 GAN 生成场景。
第十六章:基于学习的场景生成
16.1 强化学习方法
16.1.1 问题形式化
状态:场景中所有物体的位置、速度。
动作:控制交通车辆的行为。
奖励:自动驾驶车辆的性能指标。
16.1.2 算法
| 算法 | 说明 | 适用场景 |
|---|---|---|
| PPO | 近端策略优化 | 连续动作 |
| SAC | 软演员-评论家 | 连续动作 |
| DQN | 深度 Q 网络 | 离散动作 |
16.2 生成对抗网络(GAN)
16.2.1 场景 GAN
生成器:生成场景参数。
判别器:判断场景是否真实。
训练目标:
minGmaxDV(D,G)=Ex∼pdatalogD(x)+Ez∼pzlog(1−D(G(z)))\min_G \max_D V(D, G) = \mathbb{E}{x \sim p{\text{data}}} \\log D(x) + \mathbb{E}_{z \sim p_z} \\log(1 - D(G(z)))GminDmaxV(D,G)=Ex∼pdatalogD(x)+Ez∼pzlog(1−D(G(z)))
第五部分:仿真与真实世界
第十七章:Sim-to-Real 迁移
17.1 仿真与真实的差距
17.1.1 差距来源
| 来源 | 说明 | 解决方法 |
|---|---|---|
| 渲染差距 | 仿真图像不够真实 | 域随机化 |
| 物理差距 | 物理模型不准确 | 参数标定 |
| 传感器差距 | 传感器噪声不同 | 噪声建模 |
| 行为差距 | 交通行为不真实 | 真实数据驱动 |
17.1.2 域随机化
方法:在训练时随机化仿真参数,使模型对参数变化鲁棒。
随机化参数:
- 光照条件
- 天气
- 材质
- 传感器噪声
- 物体外观
17.2 域适应
17.2.1 方法
| 方法 | 说明 | 优点 |
|---|---|---|
| 域随机化 | 随机化仿真参数 | 简单有效 |
| 域适应 | 学习仿真到真实的映射 | 精度高 |
| 风格迁移 | 将仿真图像转为真实风格 | 视觉效果好 |
| 混合训练 | 同时使用仿真和真实数据 | 鲁棒性好 |
第十八章:仿真验证与测试
18.1 测试方法
18.1.1 关键场景测试
方法:测试已知的关键场景。
18.1.2 随机测试
方法:随机生成场景进行测试。
18.1.3 覆盖率测试
方法:确保测试覆盖所有可能的场景。
18.2 安全指标
18.2.1 常用指标
| 指标 | 公式 | 说明 |
|---|---|---|
| TTC | d/Δvd / \Delta vd/Δv | 碰撞时间 |
| PET | t2−t1t_2 - t_1t2−t1 | 后侵入时间 |
| DRAC | (Δv)22d\frac{(\Delta v)^2}{2d}2d(Δv)2 | 减速度 |
| MIIT | min(tcollision)\min(t_{\text{collision}})min(tcollision) | 最小交互时间 |
18.2.2 安全准则
RSS(Responsibility-Sensitive Safety):
dsafe=vr⋅ρ+12amax⋅ρ2+(vr+ρ⋅amax)22abrake−vf22abraked_{\text{safe}} = v_r \cdot \rho + \frac{1}{2} a_{\text{max}} \cdot \rho^2 + \frac{(v_r + \rho \cdot a_{\text{max}})^2}{2 a_{\text{brake}}} - \frac{v_f^2}{2 a_{\text{brake}}}dsafe=vr⋅ρ+21amax⋅ρ2+2abrake(vr+ρ⋅amax)2−2abrakevf2
第六部分:代码实践
第十九章:CARLA Python API 实战
19.1 基本操作
python
import carla
import random
def main():
# 连接到 CARLA
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
# 获取世界
world = client.get_world()
# 获取蓝图库
blueprint_library = world.get_blueprint_library()
# 获取地图
map = world.get_map()
# 获取所有车辆蓝图
vehicle_blueprints = blueprint_library.filter('vehicle.*')
# 获取所有出生点
spawn_points = map.get_spawn_points()
# 生成车辆
for i in range(10):
bp = random.choice(vehicle_blueprints)
transform = random.choice(spawn_points)
vehicle = world.try_spawn_actor(bp, transform)
# 获取所有车辆
vehicles = world.get_actors().filter('vehicle.*')
print(f"生成了 {len(vehicles)} 辆车")
if __name__ == '__main__':
main()
19.2 传感器配置
python
def setup_sensors(world, vehicle):
"""配置传感器。"""
blueprint_library = world.get_blueprint_library()
# RGB 相机
camera_bp = blueprint_library.find('sensor.camera.rgb')
camera_bp.set_attribute('image_size_x', '1920')
camera_bp.set_attribute('image_size_y', '1080')
camera_bp.set_attribute('fov', '90')
camera_transform = carla.Transform(carla.Location(x=1.5, z=2.4))
camera = world.spawn_actor(camera_bp, camera_transform, attach_to=vehicle)
# LiDAR
lidar_bp = blueprint_library.find('sensor.lidar.ray_cast')
lidar_bp.set_attribute('channels', '64')
lidar_bp.set_attribute('range', '100')
lidar_bp.set_attribute('points_per_second', '1200000')
lidar_transform = carla.Transform(carla.Location(x=0, z=2.4))
lidar = world.spawn_actor(lidar_bp, lidar_transform, attach_to=vehicle)
# 雷达
radar_bp = blueprint_library.find('sensor.other.radar')
radar_bp.set_attribute('horizontal_fov', '30')
radar_bp.set_attribute('vertical_fov', '30')
radar_transform = carla.Transform(carla.Location(x=2.0, z=1.0))
radar = world.spawn_actor(radar_bp, radar_transform, attach_to=vehicle)
return camera, lidar, radar
19.3 数据记录
python
import numpy as np
from PIL import Image
class DataRecorder:
"""数据记录器。"""
def __init__(self):
self.images = []
self.point_clouds = []
self.timestamps = []
def camera_callback(self, image):
"""相机回调。"""
array = np.frombuffer(image.raw_data, dtype=np.uint8)
array = array.reshape((image.height, image.width, 4))
array = array[:, :, :3] # 去掉 alpha 通道
self.images.append(array)
self.timestamps.append(image.timestamp)
def lidar_callback(self, point_cloud):
"""LiDAR 回调。"""
points = np.frombuffer(point_cloud.raw_data, dtype=np.float32)
points = points.reshape((-1, 4)) # x, y, z, intensity
self.point_clouds.append(points)
def save(self, output_dir):
"""保存数据。"""
import os
os.makedirs(output_dir, exist_ok=True)
for i, img in enumerate(self.images):
Image.fromarray(img).save(f"{output_dir}/image_{i:06d}.png")
for i, pc in enumerate(self.point_clouds):
np.save(f"{output_dir}/pointcloud_{i:06d}.npy", pc)
第二十章:传感器数据处理
20.1 点云处理
python
import numpy as np
def process_point_cloud(points, max_range=100, min_range=1):
"""处理点云数据。
Args:
points: 点云 (N, 4) - x, y, z, intensity
max_range: 最大距离
min_range: 最小距离
Returns:
processed: 处理后的点云
"""
# 计算距离
distances = np.linalg.norm(points[:, :3], axis=1)
# 距离过滤
mask = (distances >= min_range) & (distances <= max_range)
points = points[mask]
# 地面过滤(简单的高度阈值)
ground_mask = points[:, 2] > -1.5
points = points[ground_mask]
return points
def voxel_downsample(points, voxel_size=0.1):
"""体素下采样。
Args:
points: 点云 (N, 3)
voxel_size: 体素大小
Returns:
downsampled: 下采样后的点云
"""
# 计算体素索引
voxel_indices = np.floor(points / voxel_size).astype(int)
# 去重
unique_indices, inverse = np.unique(voxel_indices, axis=0, return_inverse=True)
# 计算每个体素的中心
downsampled = np.zeros((len(unique_indices), 3))
for i in range(len(unique_indices)):
mask = inverse == i
downsampled[i] = points[mask].mean(axis=0)
return downsampled
20.2 图像处理
python
import numpy as np
def undistort_image(image, K, dist_coeffs):
"""去畸变。
Args:
image: 输入图像
K: 内参矩阵
dist_coeffs: 畸变系数
Returns:
undistorted: 去畸变后的图像
"""
import cv2
h, w = image.shape[:2]
new_K, roi = cv2.getOptimalNewCameraMatrix(K, dist_coeffs, (w, h), 1)
undistorted = cv2.undistort(image, K, dist_coeffs, None, new_K)
return undistorted
def compute_optical_flow(prev_image, curr_image):
"""计算光流。
Args:
prev_image: 前一帧图像
curr_image: 当前帧图像
Returns:
flow: 光流 (H, W, 2)
"""
import cv2
prev_gray = cv2.cvtColor(prev_image, cv2.COLOR_BGR2GRAY)
curr_gray = cv2.cvtColor(curr_image, cv2.COLOR_BGR2GRAY)
flow = cv2.calcOpticalFlowFarneback(prev_gray, curr_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
return flow
第二十一章:场景构建与测试
21.1 场景构建
python
import carla
def create_scenario(world, ego_spawn_point):
"""创建测试场景。"""
blueprint_library = world.get_blueprint_library()
# 生成自车
ego_bp = blueprint_library.find('vehicle.tesla.model3')
ego_bp.set_attribute('role_name', 'ego')
ego_vehicle = world.spawn_actor(ego_bp, ego_spawn_point)
# 生成旁车
npc_bp = blueprint_library.find('vehicle.audi.a2')
npc_transform = carla.Transform(
carla.Location(
x=ego_spawn_point.location.x + 20,
y=ego_spawn_point.location.y,
z=ego_spawn_point.location.z
),
ego_spawn_point.rotation
)
npc_vehicle = world.spawn_actor(npc_bp, npc_transform)
return ego_vehicle, npc_vehicle
def run_scenario(world, ego_vehicle, npc_vehicle, duration=10):
"""运行场景。"""
import time
# 获取交通管理器
tm = client.get_trafficmanager()
# 设置旁车行为
tm.set_desired_speed(npc_vehicle, 30) # 30 km/h
tm.vehicle_percentage_speed_difference(npc_vehicle, -20)
# 运行仿真
for i in range(duration * 20): # 20 FPS
# 获取自车状态
ego_transform = ego_vehicle.get_transform()
ego_velocity = ego_vehicle.get_velocity()
# 获取旁车状态
npc_transform = npc_vehicle.get_transform()
npc_velocity = npc_vehicle.get_velocity()
# 计算 TTC
delta_pos = npc_transform.location - ego_transform.location
delta_vel = npc_velocity - ego_velocity
distance = delta_pos.length()
relative_speed = delta_vel.length()
if relative_speed > 0:
ttc = distance / relative_speed
print(f"Time {i/20:.1f}s: TTC = {ttc:.2f}s, Distance = {distance:.2f}m")
world.tick()
time.sleep(0.05)
return ego_vehicle, npc_vehicle
21.2 自动驾驶算法集成
python
class SimpleAutopilot:
"""简单的自动驾驶算法。"""
def __init__(self, target_speed=30):
self.target_speed = target_speed
def run_step(self, vehicle, world):
"""执行一步。"""
# 获取车辆状态
velocity = vehicle.get_velocity()
speed = 3.6 * (velocity.x**2 + velocity.y**2 + velocity.z**2)**0.5 # km/h
# 获取前方车辆
ahead_vehicle = self._get_ahead_vehicle(vehicle, world)
# 纵向控制
if ahead_vehicle is not None:
distance = self._get_distance(vehicle, ahead_vehicle)
if distance < 10:
throttle = 0
brake = 0.5
elif distance < 30:
throttle = 0.3
brake = 0
else:
throttle = 0.5
brake = 0
else:
if speed < self.target_speed:
throttle = 0.5
brake = 0
else:
throttle = 0
brake = 0.2
# 横向控制
waypoint = self._get_target_waypoint(vehicle, world)
steer = self._compute_steer(vehicle, waypoint)
# 构建控制
control = carla.VehicleControl()
control.throttle = throttle
control.brake = brake
control.steer = steer
return control
附录
A.1 CARLA 常用 API
| API | 说明 |
|---|---|
world.spawn_actor() |
生成 Actor |
vehicle.apply_control() |
应用控制 |
sensor.listen() |
监听传感器数据 |
world.tick() |
仿真步进 |
world.get_actors() |
获取所有 Actor |
map.get_spawn_points() |
获取出生点 |
world.set_weather() |
设置天气 |
A.2 SUMO 常用 TraCI 命令
| 命令 | 说明 |
|---|---|
traci.vehicle.getIDList() |
获取所有车辆 ID |
traci.vehicle.getPosition() |
获取位置 |
traci.vehicle.getSpeed() |
获取速度 |
traci.vehicle.setSpeed() |
设置速度 |
traci.vehicle.moveToXY() |
移动到指定位置 |
traci.trafficlight.getPhase() |
获取信号灯相位 |
traci.simulationStep() |
仿真步进 |
A.3 常用传感器参数
| 传感器 | 参数 | 说明 |
|---|---|---|
| RGB Camera | image_size_x | 图像宽度 |
| RGB Camera | image_size_y | 图像高度 |
| RGB Camera | fov | 视场角 |
| LiDAR | channels | 通道数 |
| LiDAR | range | 探测距离 |
| LiDAR | points_per_second | 每秒点数 |
| Radar | horizontal_fov | 水平视场角 |
| Radar | vertical_fov | 垂直视场角 |
参考文献
- Dosovitskiy, A., et al. (2017). CARLA: An open urban driving simulator. CoRL.
- Lopez, P., et al. (2018). Lanelet2: A map format for highly automated driving. IV.
- Krajzewicz, D., et al. (2012). Recent development and applications of SUMO. SIMULATION.
- Shah, S., et al. (2018). AirSim: High-fidelity visual and physical simulation for autonomous vehicles. Field Robotics.
- Rong, G., et al. (2020). LGSVL Simulator: A high fidelity simulator for autonomous driving. ITSC.
- NVIDIA. (2022). NVIDIA DRIVE Sim Technical Brief.
- ASAM. (2021). OpenSCENARIO V2.0 Specification.
- ASAM. (2021). OpenDRIVE V1.7 Specification.
- Shalev-Shwartz, S., et al. (2017). On a formal model of safe and scalable self-driving cars. arXiv.
- Treiber, M., et al. (2000). Congested traffic states in empirical observations and microscopic simulations. Physical Review E.