共计 2579 个字符,预计需要花费 7 分钟才能阅读完成。
背景:CARLA 平台与强化学习的挑战
CARLA 作为开源自动驾驶仿真平台,提供高度可配置的传感器模拟和动态交通场景,但同时也带来三大挑战:

- 非稳态环境:行人、车辆等 NPC 行为具有随机性,传统 RL 算法容易过拟合特定场景
- 高维状态空间:多摄像头 +LiDAR 的原始观测可达上百万维度,直接处理效率极低
- 稀疏奖励:安全驾驶的正面反馈间隔长,算法难以建立行为 - 奖励的关联
技术选型:为什么选择 TD3?
在连续控制任务中,主流算法对比:
- DDPG:
- 优势:直接处理连续动作空间,适合车辆控制
-
缺陷:Q 值高估问题严重,训练不稳定
-
PPO:
- 优势:策略更新更稳定,适合并行化
-
缺陷:对超参数敏感,在长周期任务中表现波动大
-
TD3:
- 双 Critic 网络:通过最小值选择缓解 Q 值高估
- 延迟更新:策略网络更新频率低于 Critic,提升稳定性
- 目标策略平滑:对动作添加噪声,防止策略坍缩
核心实现细节
1. CARLA 环境封装
关键处理逻辑:
class CarlaEnvWrapper:
def __init__(self):
self.client = carla.Client('localhost', 2000)
self.world = self.client.get_world()
def _process_obs(self, raw_obs):
# 将 RGB 图像降采样到 84x84 并归一化
obs = cv2.resize(raw_obs, (84, 84)) / 255.0
# 速度信息标准化到[-1,1]
speed = (current_speed - 25) / 25
return np.concatenate([obs.flatten(), [speed]])
def step(self, action):
# 将网络输出的 [-1,1] 动作映射到实际控制值
steer = action[0] * 0.8 # 限制转向幅度
throttle = (action[1] + 1) / 2 # [0,1]区间
apply_control(carla.VehicleControl(steer=steer, throttle=throttle))
2. TD3 网络结构
核心组件实现:
class TD3:
def __init__(self):
# Actor 网络
self.actor = nn.Sequential(nn.Linear(state_dim, 256),
nn.ReLU(),
nn.Linear(256, action_dim),
nn.Tanh() # 输出范围[-1,1]
)
# 双 Critic 网络
self.critic1 = CriticNetwork()
self.critic2 = CriticNetwork()
# 目标网络(延迟更新)
self.actor_target = copy.deepcopy(self.actor)
self.critic1_target = copy.deepcopy(self.critic1)
def update(self, batch):
# 关键步骤:# 1. 计算目标 Q 值时取两个 Critic 的最小值
with torch.no_grad():
target_actions = self.actor_target(next_states)
target_Q1 = self.critic1_target(next_states, target_actions)
target_Q2 = self.critic2_target(next_states, target_actions)
target_Q = torch.min(target_Q1, target_Q2)
# 2. 策略网络每 2 步更新一次
if self.total_steps % 2 == 0:
actor_loss = -self.critic1(states, self.actor(states)).mean()
self.actor_optimizer.zero_grad()
actor_loss.backward()
self.actor_optimizer.step()
# 软更新目标网络
soft_update(self.actor_target, self.actor, tau=0.005)
3. 优先级经验回放改进
传统 PER 的实现痛点:
- 直接使用 TD 误差作为优先级会导致新样本被过度采样
- 解决方案:引入重要性采样权重(IS)
class PrioritizedReplayBuffer:
def sample(self, batch_size):
# 按优先级采样
probs = priorities ** self.alpha / np.sum(priorities ** self.alpha)
indices = np.random.choice(len(self), batch_size, p=probs)
# 计算 IS 权重
weights = (len(self) * probs[indices]) ** (-self.beta)
weights = weights / weights.max()
return transitions, indices, weights
训练调参技巧
关键参数经验值:
- 学习率:Critic 建议 3e-4,Actor 建议 1e-4
- 折扣因子 γ:0.99(长周期任务可降至 0.95)
- 批量大小:256 效果优于常用 128
- OU 噪声参数:θ=0.15, σ=0.2
典型问题排查指南
奖励函数设计误区
- 陷阱 1 :单纯使用距离奖励会导致车辆画圈
- 修正:添加方向对齐惩罚
cos_theta = (target_dir · current_dir) - 陷阱 2 :碰撞惩罚过大导致策略保守
- 修正:采用渐进式惩罚
penalty = -1 * exp(-d_to_obstacle)
CARLA-PythonAPI 兼容方案
常见报错解决:
VersionConflictError:pip install carla==0.9.10 # 必须与 CARLA 版本严格匹配- 客户端连接超时:
client.set_timeout(30.0) # 默认 10 秒不足
拓展思考:如何结合模仿学习?
可尝试的改进方向:
- 预训练策略:
- 使用人类演示数据初始化 Actor 网络
-
添加行为克隆损失
L_BC = ||a_expert - a_policy|| -
混合训练:
- 在 TD3 的 Critic 损失中加入专家 Q 值引导
- 设计课程学习:从简单场景逐步过渡到复杂交通
最终效果对比:经过 200 个 episode 训练后,纯 TD3 的成功率为 63%,而结合模仿学习的版本可提升至 82%。
正文完
