EasyCarla-RL 项目架构与核心实现梳理
一、项目整体架构
1.1 目录结构
EasyCarla-RL/
├── easycarla/ # 主环境模块(Python包)
│ ├── envs/ # CARLA环境封装
│ │ ├── __init__.py
│ │ └── carla_env.py # Carla环境核心实现
│ └── __init__.py
├── example/ # 高级示例代码
│ ├── agents/ # RL智能体实现
│ │ ├── __init__.py
│ │ ├── bc_diffusion.py # Behavior Cloning + Diffusion
│ │ ├── diffusion.py # 扩散模型核心
│ │ ├── helpers.py # 辅助工具函数
│ │ ├── model.py # MLP网络架构
│ │ └── ql_diffusion.py # Diffusion Q-Learning主类
│ ├── params_dql/ # 预训练模型参数
│ │ ├── actor_200.pth
│ │ └── critic_200.pth
│ ├── utils/ # 工具模块
│ │ ├── __init__.py
│ │ ├── data_sampler.py # 数据集采样器
│ │ ├── logger.py # 日志工具
│ │ ├── pytorch_util.py # PyTorch工具
│ │ └── utils.py # 通用工具
│ └── run_dql_in_carla.py # 在CARLA中运行DQL模型
├── assets/ # 静态资源(演示GIF)
├── easycarla_demo.py # 基础演示脚本
├── requirements.txt # 依赖清单
├── setup.py # 包安装配置
└── README.md # 项目说明文档
1.2 模块职责说明
| 模块 | 职责 | 核心功能 |
|---|---|---|
easycarla.envs |
CARLA环境封装 | Gym兼容接口、传感器管理、奖励计算 |
example.agents |
RL算法实现 | Diffusion Q-Learning、行为克隆 |
example.utils |
工具函数 | 数据采样、日志记录、模型保存/加载 |
二、核心算法实现
2.1 Diffusion Q-Learning 架构
2.1.1 整体架构
Diffusion Q-Learning 是一种离线强化学习算法,将扩散模型与Q学习相结合:
┌─────────────────────────────────────────────────────────────┐
│ Diffusion Q-Learning │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Actor │←───│ EMA │←───│ Critic │ │
│ │(Diffusion)│ │ (Target) │ │(Double Q)│ │
│ └────┬─────┘ └──────────┘ └────┬─────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ 训练循环 (Training Loop) │ │
│ │ BC Loss + Q Loss → Actor Update │ │
│ │ TD Error → Critic Update │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2.1.2 核心组件
1. Critic 网络 (ql_diffusion.py:17-46)
采用 Double Q-Learning 架构,包含两个独立的Q网络:
python
class Critic(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=256):
self.q1_model = nn.Sequential(
nn.Linear(state_dim + action_dim, hidden_dim),
nn.Mish(),
nn.Linear(hidden_dim, hidden_dim),
nn.Mish(),
nn.Linear(hidden_dim, hidden_dim),
nn.Mish(),
nn.Linear(hidden_dim, 1)
)
self.q2_model = nn.Sequential(...) # 结构相同
def q_min(self, state, action):
q1, q2 = self.forward(state, action)
return torch.min(q1, q2) # 取最小Q值避免过估计
2. Diffusion Actor (diffusion.py:19-181)
基于扩散模型的策略网络,支持多种beta schedule:
| 参数 | 类型 | 说明 |
|---|---|---|
beta_schedule |
str | 可选:linear、cosine、vp |
n_timesteps |
int | 扩散步数(默认100) |
loss_type |
str | 损失类型:l1 或 l2 |
clip_denoised |
bool | 是否裁剪去噪输出 |
3. MLP 模型 (model.py:12-48)
时序条件的MLP网络,输入包含:
state(307维)action(3维)time_embedding(16维) → 通过正弦位置编码生成
2.2 训练流程
训练循环在 Diffusion_QL.train() 方法中实现:
┌──────────────────────────────────────────────────────────────┐
│ 训练迭代流程 │
├──────────────────────────────────────────────────────────────┤
│ 1. 采样数据 → replay_buffer.sample(batch_size) │
│ │ │
│ ▼ │
│ 2. Critic更新 → TD目标计算 → MSE损失优化 │
│ │ │
│ ▼ │
│ 3. Actor更新 → BC Loss + η * Q Loss │
│ │ │
│ ▼ │
│ 4. 目标网络更新 → EMA更新Actor, Polyak更新Critic │
└──────────────────────────────────────────────────────────────┘
损失函数设计:
python
# Actor损失 = 行为克隆损失 + Q学习损失
bc_loss = self.actor.loss(action, state) # 模仿学习
q_loss = - q_new_action.mean() / q_abs.mean() # 最大化Q值
actor_loss = bc_loss + self.eta * q_loss # eta=0.01
三、数据集加载
3.1 数据集格式
项目提供的离线数据集存储为HDF5格式,包含约110万时间步:
easycarla_offline_dataset.hdf5
├── observations → shape: [N, 307] # 观测向量
├── actions → shape: [N, 3] # [throttle, steer, brake]
├── rewards → shape: [N] # 标量奖励
├── costs → shape: [N] # 安全成本
├── done → shape: [N] # 终止标志
├── next_observations → shape: [N, 307] # 下一时刻观测
└── info → dict
├── is_collision → shape: [N]
└── is_off_road → shape: [N]
3.2 数据采样器 (data_sampler.py)
核心功能:
- 支持多种reward调整策略
- 批量采样训练数据
- 自动转换为PyTorch张量
python
class Data_Sampler(object):
def __init__(self, data, device, reward_tune='no'):
self.state = torch.from_numpy(data['observations']).float()
self.action = torch.from_numpy(data['actions']).float()
self.next_state = torch.from_numpy(data['next_observations']).float()
self.reward = torch.from_numpy(data['rewards']).reshape(-1, 1).float()
self.not_done = 1. - torch.from_numpy(data['dones']).reshape(-1, 1).float()
def sample(self, batch_size):
ind = torch.randint(0, self.size, size=(batch_size,))
return (
self.state[ind].to(self.device),
self.action[ind].to(self.device),
self.next_state[ind].to(self.device),
self.reward[ind].to(self.device),
self.not_done[ind].to(self.device)
)
Reward调整策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
no |
不调整 | 默认 |
normalize |
标准化 (mean=0, std=1) | 通用 |
iql_antmaze |
reward - 1.0 | AntMaze环境 |
iql_locomotion |
按轨迹返回归一化 | 连续控制 |
cql_antmaze |
(reward - 0.5) * 4.0 | CQL算法 |
四、数据预处理
4.1 观测向量结构
观测向量为307维,由以下部分拼接而成:
| 组件 | 维度 | 说明 |
|---|---|---|
ego_state |
9 | 自车状态(位置、速度、角度等) |
lane_info |
2 | 车道宽度 + 横向偏移 |
lidar |
240 | LiDAR扫描数据(240个角度bin) |
nearby_vehicles |
20 | 最多5辆车 × 4特征 |
waypoints |
36 | 最多12个路点 × 3特征 |
4.2 各组件提取逻辑
1. LiDAR特征提取 (carla_env.py:513-547)
python
# LiDAR数据转换流程
max_range = 50.0
lidar_features = np.full((240,), max_range) # 初始化
for detection in self.lidar_data:
x, y = detection.point.x, detection.point.y
# 坐标变换:全局→自车局部
local_x = np.cos(-ego_yaw) * x - np.sin(-ego_yaw) * y
local_y = np.sin(-ego_yaw) * x + np.cos(-ego_yaw) * y
distance = np.sqrt(local_x**2 + local_y**2)
angle_deg = (np.degrees(np.arctan2(local_y, local_x)) + 360) % 360
index = int(angle_deg // 1.5) # 1.5°分辨率,240个bin
if index < 240:
lidar_features[index] = min(lidar_features[index], distance)
lidar_features /= max_range # 归一化到[0, 1]
2. 自车状态提取 (carla_env.py:549-592)
包含9维特征:
ego_x,ego_y: 全局坐标ego_yaw: 航向角(弧度)speed: 速度大小angular_velocity.z: 角速度acceleration.x/y: 加速度分量front_vehicle_distance: 前车距离relative_speed: 相对前车速度
3. 周围车辆信息 (carla_env.py:594-633)
最多检测5辆周围车辆,每辆车4个特征:
local_x,local_y: 相对自车的局部坐标yaw_diff: 相对航向角speed: 车辆速度
4. 路点信息 (carla_env.py:635-659)
提取前方12个路点,每个路点包含:
local_x,local_y: 局部坐标yaw_relative: 相对航向角
5. 车道信息 (carla_env.py:661-683)
lane_width: 当前车道宽度lateral_offset: 自车偏离车道中心线的距离
五、模型加载
5.1 模型保存与加载接口
保存模型:
python
model = Diffusion_QL(state_dim=307, action_dim=3, max_action=1.0, ...)
model.save_model('./params_dql', id=200) # 保存为 actor_200.pth, critic_200.pth
加载模型:
python
model = Diffusion_QL(state_dim=307, action_dim=3, max_action=1.0, ...)
model.load_model('./params_dql', id=200) # 加载指定checkpoint
5.2 推理流程 (run_dql_in_carla.py)
python
# 1. 环境初始化
env = gym.make('carla-v0', params=carla_params)
# 2. 模型初始化
model = Diffusion_QL(
state_dim=307,
action_dim=3,
max_action=1.0,
device=device,
discount=0.99,
tau=0.005,
eta=0.01,
beta_schedule='vp',
n_timesteps=5
)
# 3. 加载预训练模型
model.load_model('./params_dql', id=200)
# 4. 推理循环
obs = env.reset()
while not done:
obs_vec = convert_obs_dict_to_vector(obs)
action = model.sample_action(obs_vec)
obs, reward, cost, done, info = env.step(action)
动作采样策略:
python
def sample_action(self, state):
# 重复采样50次
state_rpt = torch.repeat_interleave(state, repeats=50, dim=0)
with torch.no_grad():
action = self.actor.sample(state_rpt)
q_value = self.critic_target.q_min(state_rpt, action).flatten()
idx = torch.multinomial(F.softmax(q_value, dim=0), 1) # 按Q值加权采样
return action[idx].cpu().data.numpy().flatten()
六、CARLA仿真环境
6.1 环境配置参数
python
carla_params = {
'number_of_vehicles': 100, # 周围车辆数量
'number_of_walkers': 0, # 行人数量
'dt': 0.1, # 仿真时间步长(秒)
'ego_vehicle_filter': 'vehicle.tesla.model3', # 自车类型
'surrounding_vehicle_spawned_randomly': True, # 车辆随机生成
'port': 2000, # CARLA服务器端口
'town': 'Town03', # 地图场景
'max_time_episode': 1000, # 每回合最大步数
'max_waypoints': 12, # 路点数量
'visualize_waypoints': True, # 可视化路点
'desired_speed': 8, # 期望速度(m/s)
'max_ego_spawn_times': 200, # 自车生成重试次数
'view_mode': 'top', # 视角模式:'top' 或 'follow'
'traffic': 'off', # 交通灯控制
'lidar_max_range': 50.0, # LiDAR最大感知距离
'max_nearby_vehicles': 5, # 最大检测车辆数
}
6.2 传感器配置
LiDAR传感器:
- 通道数:1(水平扫描)
- 最大距离:50米
- 旋转频率:10Hz
- 点云密度:10000点/秒
- 垂直FOV:0°(仅水平扫描)
碰撞传感器:
- 实时检测碰撞事件
- 记录碰撞强度
- 触发回合终止
6.3 奖励函数设计 (carla_env.py:702-738)
奖励函数由多个分量组成:
| 分量 | 权重 | 说明 |
|---|---|---|
| 正向驾驶奖励 | +1.0×speed | 速度奖励(不超过期望速度) |
| 超速惩罚 | -1.0×(speed-desired) | 超过期望速度时惩罚 |
| 车道偏离惩罚 | -1.0×lateral_offset | 偏离车道中心惩罚 |
| 横向加速度惩罚 | -0.5×|a_lat| | 平滑驾驶约束 |
| 静止惩罚 | -1.0 | 前方无车但静止时惩罚 |
| 碰撞惩罚 | -100.0 | 发生碰撞 |
| 偏离道路惩罚 | -100.0 | 驶离可行驶区域 |
6.4 成本函数设计 (carla_env.py:740-768)
用于安全强化学习的约束成本:
| 分量 | 权重 | 说明 |
|---|---|---|
| 碰撞成本 | +20.0 | 发生碰撞 |
| 偏离道路成本 | +20.0 | 驶离可行驶区域 |
| 超速成本 | (speed-desired)/desired | 超速比例 |
6.5 终止条件 (carla_env.py:770-822)
python
def _terminal(self):
# 1. 碰撞检测
if len(self.collision_hist) > 0:
return True
# 2. 超过最大步数
if self.time_step > self.max_time_episode:
return True
# 3. 驶离可行驶车道
waypoint = self.world.get_map().get_waypoint(...)
if waypoint is None:
return True
# 4. 逆向行驶(航向偏差>90°)
if abs(yaw_diff) > np.pi / 2:
return True
# 5. 偏离车道中心过远
if lateral_offset > lane_width / 2 + 1.0:
return True
return False
七、关键技术要点
7.1 坐标变换
所有传感器数据需转换为自车局部坐标系:
python
# 全局坐标 → 自车局部坐标
local_x = np.cos(-ego_yaw) * global_x - np.sin(-ego_yaw) * global_y
local_y = np.sin(-ego_yaw) * global_x + np.cos(-ego_yaw) * global_y
7.2 同步模式控制
CARLA支持同步和异步两种模式:
- 同步模式:服务器等待客户端指令后才推进仿真,用于精确控制
- 异步模式:服务器自主运行,用于环境重置时清理场景
python
def _set_synchronous_mode(self, synchronous=True):
self.settings.synchronous_mode = synchronous
self.world.apply_settings(self.settings)
7.3 渲染视角
支持两种渲染视角:
| 模式 | 说明 | 适用场景 |
|---|---|---|
top |
鸟瞰视角(40米高空) | 全局观察 |
follow |
第三人称跟随视角 | 细节观察 |
八、使用示例
8.1 基础演示
bash
python easycarla_demo.py
功能:
- 随机选择自动驾驶或手动控制
- 输出每步奖励和成本
- 展示基本Gym接口
8.2 Diffusion Q-Learning 评估
bash
cd example
python run_dql_in_carla.py
功能:
- 加载预训练的Diffusion Q-Learning模型
- 在CARLA中运行评估
- 输出回合总奖励和步数
九、数据集下载
| 来源 | 链接 |
|---|---|
| Hugging Face | https://huggingface.co/datasets/silverwingsbot/easycarla |
| 百度网盘 | 链接(提取码: 2049) |
数据集规格:
- 大小:约2.76 GB
- 格式:HDF5
- 轨迹数:7,000+
- 时间步数:110万+
- 专家/随机比例:8:2
十、预训练模型与数据集关系
10.1 预训练模型来源
example/params_dql/actor_200.pth 和 example/params_dql/critic_200.pth 这两个预训练模型文件确实是通过 easycarla_offline_dataset.hdf5 离线数据集训练得到的。
10.2 模型命名规则
文件名中的 200 表示训练迭代次数:
actor_200.pth→ Actor网络(扩散模型)在第200个训练epoch/迭代保存critic_200.pth→ Critic网络(Double Q-Learning)在第200个训练epoch/迭代保存
10.3 训练算法匹配
使用的 Diffusion Q-Learning 算法支持:
- 行为克隆(Behavior Cloning):从数据集中学习专家行为
- Q学习:优化价值函数
- 损失函数 :
bc_loss + η * q_loss(行为克隆损失 + Q损失)
10.4 数据集格式匹配
数据集包含训练所需的完整数据:
| 数据字段 | 维度 | 用途 |
|---|---|---|
observations |
(N, 307) | 状态输入 |
actions |
(N, 3) | 专家动作标签(油门、转向、刹车) |
rewards |
(N,) | 奖励信号 |
next_observations |
(N, 307) | 下一状态(用于TD目标计算) |
done |
(N,) | 终止标志 |
observations(307维向量)状态输入:
数据集包含完整的自车轨迹信息,由以下字段共同构成:
| 字段 | 维度 | 用途 |
|---|---|---|
observations |
(N, 307) | 当前时刻观测(自车状态+LiDAR+路点+周围车辆) |
actions |
(N, 3) | 专家执行的动作 |
rewards |
(N,) | 奖励信号 |
next_observations |
(N, 307) | 下一时刻观测 |
done |
(N,) | 是否到达轨迹终点 |
info |
dict | 额外信息(is_collision、is_off_road) |
数据集规模:
- 轨迹数:7,000+
- 时间步数:110万+
- 专家/随机比例:8:2
观测向量中的自车状态 (前9维 ego_state):
| 索引 | 状态量 | 说明 |
|---|---|---|
| 0-1 | ego_x, ego_y |
自车全局坐标 |
| 2 | ego_yaw |
自车航向角(弧度) |
| 3 | speed |
自车速度 |
| 4 | angular_velocity.z |
角速度 |
| 5-6 | acceleration.x/y |
加速度分量 |
| 7 | front_vehicle_distance |
前车距离 |
| 8 | relative_speed |
相对前车速度 |
actions动作空间详细说明(3维向量):
| 索引 | 动作类型 | 取值范围 | 说明 |
|---|---|---|---|
[0] |
throttle(油门) | 0.0, 1.0 | 0=无油门,1=全油门 |
[1] |
steer(转向) | -1.0, 1.0 | -1=左转,0=直行,1=右转 |
[2] |
brake(刹车) | 0.0, 1.0 | 0=无刹车,1=急刹 |
python
# 动作空间定义(来自 carla_env.py:43-46)
self.action_space = spaces.Box(
low=np.array([0.0, -1.0, 0.0], dtype=np.float32), # 最小值
high=np.array([1.0, 1.0, 1.0], dtype=np.float32) # 最大值
)
10.5 训练流程
┌──────────────────────────────────────────────────────────────┐
│ 训练流程示意图 │
├──────────────────────────────────────────────────────────────┤
│ easycarla_offline_dataset.hdf5 │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Data_Sampler │ ← 数据采样器 │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Diffusion_QL │ ← 训练算法 │
│ │ (BC + Q-Learning)│ │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ actor_200.pth critic_200.pth │
└──────────────────────────────────────────────────────────────┘
10.6 完整训练流程
10.6.1 训练环境准备
-
安装依赖:
bashpip install -r requirements.txt pip install -e . -
下载数据集:
- 从 Hugging Face 或百度网盘下载
easycarla_offline_dataset.hdf5 - 放置到
example/目录下
- 从 Hugging Face 或百度网盘下载
10.6.2 训练脚本(train_dql.py)
项目提供了完整的训练脚本 example/train_dql.py:
python
import h5py
import torch
from agents.ql_diffusion import Diffusion_QL
from utils.data_sampler import Data_Sampler
# 加载数据集
with h5py.File('easycarla_offline_dataset.hdf5', 'r') as f:
data = {
'observations': f['observations'][:],
'actions': f['actions'][:],
'rewards': f['rewards'][:],
'next_observations': f['next_observations'][:],
'done': f['done'][:]
}
# 创建数据采样器
replay_buffer = Data_Sampler(data, device, reward_tune='normalize')
# 初始化模型
model = Diffusion_QL(
state_dim=307,
action_dim=3,
max_action=1.0,
device=device,
discount=0.99,
tau=0.005,
eta=0.01,
beta_schedule='vp',
n_timesteps=5
)
# 训练循环
for epoch in range(200):
metrics = model.train(replay_buffer, iterations=1000, batch_size=128)
# 保存模型(每50轮或最后一轮)
if epoch % 50 == 0 or epoch == 199:
model.save_model('./params_dql', id=epoch+1)
10.6.3 训练命令
bash
cd example
python train_dql.py
10.6.4 训练算法详解
Diffusion Q-Learning 结合了行为克隆和Q学习:
┌─────────────────────────────────────────────────────────────┐
│ 训练迭代流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 数据采样 → replay_buffer.sample(batch_size) │
│ │ │
│ ▼ │
│ 2. Critic更新 → TD目标计算 → MSE损失优化 │
│ target_q = reward + γ * min(Q1', Q2') │
│ │ │
│ ▼ │
│ 3. Actor更新 → BC Loss + η * Q Loss │
│ bc_loss = actor.loss(action, state) │
│ q_loss = -Q(s, actor(s)) / |Q| │
│ actor_loss = bc_loss + 0.01 * q_loss │
│ │ │
│ ▼ │
│ 4. 目标网络更新 → EMA更新Actor, Polyak更新Critic │
└─────────────────────────────────────────────────────────────┘
关键参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
discount (γ) |
0.99 | 折扣因子 |
tau |
0.005 | Polyak平均系数 |
eta |
0.01 | Q学习损失权重 |
beta_schedule |
'vp' | 扩散过程beta调度 |
n_timesteps |
5 | 扩散步数 |
batch_size |
128 | 批次大小 |
10.6.5 模型保存
训练完成后,模型将保存到 example/params_dql/ 目录:
params_dql/
├── actor_50.pth # 第50轮保存
├── critic_50.pth
├── actor_100.pth # 第100轮保存
├── critic_100.pth
├── actor_150.pth # 第150轮保存
├── critic_150.pth
├── actor_200.pth # 第200轮保存(最终模型)
└── critic_200.pth
10.6.6 训练时间估计
在单GPU(NVIDIA RTX 3090)上:
- 每轮迭代(1000次训练步):约2-3分钟
- 完整200轮训练:约6-10小时
十一、依赖说明
txt
carla==0.9.13
gym==0.26.2
numpy==1.24.3
torch==2.0.1
h5py==3.9.0
十二、训练与测试的奖励函数调用分析
12.1 调用关系对比
训练脚本和测试脚本对 _get_reward 的调用方式完全不同:
| 脚本 | 是否调用 _get_reward |
奖励来源 |
|---|---|---|
train_dql.py |
否 | 从 HDF5 文件读取预计算的奖励 |
run_dql_in_carla.py |
是 | 实时调用 CARLA 环境计算 |
12.2 训练流程
┌─────────────────────────────────────────────────────────────────┐
│ 训练流程 (train_dql.py) │
├─────────────────────────────────────────────────────────────────┤
│ easycarla_offline_dataset.hdf5 │
│ │ │
│ ▼ │
│ 读取 precomputed_rewards ← 采集时已调用 _get_reward() │
│ │ │
│ ▼ │
│ 训练模型 (Diffusion_QL.train()) │
│ │ │
│ ▼ │
│ 保存 actor.pth, critic.pth │
└─────────────────────────────────────────────────────────────────┘
12.3 测试流程
┌─────────────────────────────────────────────────────────────────┐
│ 测试流程 (run_dql_in_carla.py) │
├─────────────────────────────────────────────────────────────────┤
│ 加载 actor.pth, critic.pth │
│ │ │
│ ▼ │
│ env.step(action) │
│ │ │
│ ├─► _get_reward() ← 实时计算奖励 │
│ ├─► _get_cost() │
│ └─► 返回 (obs, reward, cost, done, info) │
│ │ │
│ ▼ │
│ 循环直到 done=True │
└─────────────────────────────────────────────────────────────────┘
12.4 关键区别
训练脚本 train_dql.py:
- 不直接调用
_get_reward - 从
easycarla_offline_dataset.hdf5加载预计算的奖励 - 这些奖励是在数据采集时由 CARLA 环境的
_get_reward预先计算并保存的
测试脚本 run_dql_in_carla.py:
- 每一步都调用
env.step(action) - 内部会实时调用
_get_reward()计算当前步骤的奖励
12.5 潜在问题分析
-
奖励分布不一致:
- 训练时的奖励来自专家数据采集时的预计算值
- 测试时的奖励是实时计算的
- 可能存在分布偏移
-
策略差异:
- 数据采集时的专家策略与测试时模型的策略可能不同
- 导致测试时的状态分布与训练数据不匹配
-
性能影响:
- 模型可能在训练数据上表现良好
- 但在测试环境中泛化性能下降
十三、引用致谢
本项目基于以下开源工作:
- CARLA Simulator - 自动驾驶仿真平台
- gym-carla - CARLA的Gym接口封装
- Diffusion Policies for Offline RL - 扩散模型在离线RL中的应用
十四、数据集说明 (easycarla_offline_dataset.hdf5)
数据集基本信息
| 属性 | 值 |
|---|---|
| 文件名 | easycarla_offline_dataset.hdf5 |
| 样本数量 | 1,114,451 条 |
| 观测维度 | 307 维 |
| 动作维度 | 3 维 (Throttle, Steer, Brake) |
数据集字段
| 字段名 | 形状 | 说明 |
|---|---|---|
observations |
(1114451, 307) | 当前观测向量 |
actions |
(1114451, 3) | 专家动作 (Throttle, Steer, Brake) |
rewards |
(1114451,) | 即时奖励 |
next_observations |
(1114451, 307) | 下一时刻观测 |
done |
(1114451,) | Episode结束标志 |
costs |
(1114451,) | 成本值 |
info |
Group | 信息组 |
info字段详情
info 是一个 HDF5 Group,包含:
| 子字段 | 说明 |
|---|---|
is_collision |
是否发生碰撞 |
is_off_road |
是否偏离道路 |
observations 观测向量结构 (307维)
| 维度范围 | 内容 | 维度 | 说明 |
|---|---|---|---|
| 0-8 | ego_state | 9 | 自车状态(速度、位置等) |
| 9-10 | lane_info | 2 | 车道信息(车道宽度、横向偏移) |
| 11-250 | lidar | 240 | 激光雷达点云数据 |
| 251-270 | nearby_vehicles | 20 | 周围车辆信息(5辆车×4维) |
| 271-306 | waypoints | 36 | 路径点 (12个点×3维: x, y, yaw) |
ego_state (9维)
| 索引 | 内容 | 单位 |
|---|---|---|
| 0-2 | 自车位置 (x, y, z) | 米 |
| 3 | 自车速度 | m/s |
| 4-6 | 自车加速度 (a_x, a_y, a_z) | m/s² |
| 7 | 前方障碍物距离 | 米 |
| 8 | 航向角 | 弧度 |
lidar (240维)
激光雷达点云数据,按距离和角度编码。
nearby_vehicles (20维)
周围5辆车的信息,每辆车4维:
- 相对位置 x, y
- 相对速度 v_x, v_y
数据集使用示例
python
import h5py
with h5py.File('easycarla_offline_dataset.hdf5', 'r') as f:
# 加载观测和动作
observations = f['observations'][:] # (1114451, 307)
actions = f['actions'][:] # (1114451, 3)
# 解析观测结构
ego_state = observations[:, 0:9] # 自车状态
lane_info = observations[:, 9:11] # 车道信息
lidar = observations[:, 11:251] # 激光雷达
nearby_vehicles = observations[:, 251:271] # 周围车辆
waypoints = observations[:, 271:307] # 路径点
训练脚本中的使用
train_offline_bc_planning.py / train_offline_dql_planning.py:
python
state = torch.FloatTensor(self.data['observations'][idx]) # 完整307维
action = torch.FloatTensor(self.data['actions'][idx])
注意事项
- LiDAR和周围车辆数据:虽然数据集中包含这些数据,但部分训练脚本(如BC)并未专门处理这些高维感知数据
- 奖励来自预计算:训练时使用的奖励是数据采集时预计算的,与在线计算可能存在差异
- 轨迹提取:waypoints只有12个点,训练脚本会外推至20个点(点间距2米)