当前位置: 首页 > news >正文

基于DDPG的车辆纵向速度控制优化:兼顾速度与乘坐舒适性

基于DDPG的车辆纵向速度控制优化:兼顾速度与乘坐舒适性

1. 引言

1.1 研究背景与意义

在现代智能交通系统中,自动驾驶车辆的纵向控制是一个核心问题,它直接关系到行驶效率、安全性和乘客舒适性。传统的PID控制器在简单场景下表现良好,但在复杂多变的实际道路环境中,特别是在需要考虑乘坐舒适性的情况下,往往难以达到理想的控制效果。强化学习作为一种能够通过与环境交互自主学习最优策略的方法,为解决这一复杂控制问题提供了新的思路。

DDPG(Deep Deterministic Policy Gradient)算法结合了深度学习的强大表示能力和确定性策略梯度的优势,特别适合处理连续动作空间的控制问题。在车辆纵向速度控制场景中,我们需要在"跑得快"(效率)和"乘坐舒适"(垂向加速度小)这两个看似矛盾的目标之间找到平衡点,这正是DDPG算法可以发挥优势的领域。

1.2 问题定义

本课题的具体任务是:在给定的1公里路面轮廓(y-z坐标)上,使用DDPG算法训练一个智能体,以10Hz的频率输出纵向加速度指令,控制四分之一车模型,目标是同时优化行驶速度和乘坐舒适性(垂向加速度RMS值小)。

1.3 相关工作

近年来,强化学习在车辆控制领域已有不少应用研究。与传统的控制方法相比,强化学习能够自动学习复杂的控制策略,而无需精确的数学模型。特别是在处理多目标优化问题时,通过精心设计奖励函数,强化学习可以找到各个目标之间的平衡点。

2. 系统建模与问题表述

2.1 车辆动力学模型

我们采用四分之一车模型(Quarter-Car Model)作为车辆动力学的基础。四分之一车模型是车辆垂向动力学分析中最常用的简化模型,它将整车质量分为簧上质量(车身)和簧下质量(车轮和悬挂部件)。

模型的基本参数和动力学方程如下:

class QuarterCarModel:def __init__(self):# 模型参数self.m_s = 400    # 簧上质量(kg)self.m_u = 40     # 簧下质量(kg)self.k_s = 30000  # 悬挂刚度(N/m)self.c_s = 3000  # 悬挂阻尼(Ns/m)self.k_t = 200000 # 轮胎刚度(N/m)# 状态变量 [车身位移, 车身速度, 车轮位移, 车轮速度]self.state = np.zeros(4)def update(self, a_long, road_profile, dt):"""更新车辆状态:param a_long: 纵向加速度(m/s^2):param road_profile: 当前路面高度(m):param dt: 时间步长(s):return: 车身垂向加速度(m/s^2)"""z_s, z_s_dot, z_u, z_u_dot = self.statez_r = road_profile# 计算悬挂和轮胎力f_s = self.k_s * (z_u - z_s) + self.c_s * (z_u_dot - z_s_dot)f_t = self.k_t * (z_r - z_u)# 计算加速度z_s_ddot = f_s / self.m_sz_u_ddot = (f_t - f_s) / self.m_u# 更新状态(欧拉积分)z_s_dot += z_s_ddot * dtz_s += z_s_dot * dtz_u_dot += z_u_ddot * dtz_u += z_u_dot * dtself.state = np.array([z_s, z_s_dot, z_u, z_u_dot])# 返回车身垂向加速度return z_s_ddot

2.2 道路模型

道路数据以.npy文件格式提供,包含[x, y, z]坐标。由于y坐标单调递增,我们可以将其视为道路的纵向距离。为了高效查询任意位置的路面高度,我们实现了一个道路插值器:

class RoadProfile:def __init__(self, road_data):self.y = road_data[:, 1]  # 纵向距离self.z = road_data[:, 2]  # 高度self.length = self.y[-1] - self.y[0]self.interp = interp1d(self.y, self.z, kind='linear', fill_value='extrapolate')def get_height(self, y_pos):return self.interp(y_pos)

2.3 状态空间与动作空间

**状态空间(State Space)**设计:

  1. 当前速度 (m/s)
  2. 当前纵向加速度 (m/s²)
  3. 当前垂向加速度 (m/s²)
  4. 影子车预测的6秒内垂向加速度RMS值
  5. 影子车预测的6秒内最大垂向加速度
  6. 前方10米路面的平均坡度
  7. 前方50米路面的平均坡度

动作空间(Action Space)
连续值,范围为[-3, 3] m/s²,表示纵向加速度指令。

2.4 奖励函数设计

奖励函数由四个部分组成,需要平衡多个目标:

def calculate_reward(self, state, action, next_state):# 效率奖励(鼓励高速行驶)speed_reward = 0.1 * state[0]  # 当前速度# 垂向舒适性惩罚(垂向加速度RMS)vertical_comfort_penalty = -0.5 * np.sqrt(np.mean(state[3]**2))# 纵向舒适性惩罚(加速度变化率)jerk = abs(action - state[1]) / self.dtlongitudinal_comfort_penalty = -0.2 * jerk# 能耗惩罚(与加速度平方成正比)energy_penalty = -0.01 * action**2total_reward = (speed_reward + vertical_comfort_penalty + longitudinal_comfort_penalty + energy_penalty)return total_reward

3. DDPG算法实现

3.1 DDPG算法概述

DDPG(Deep Deterministic Policy Gradient)是一种结合了DPG(Deterministic Policy Gradient)和DQN(Deep Q-Network)思想的算法,适用于连续动作空间的控制问题。其主要特点包括:

  1. 采用Actor-Critic架构
  2. 使用经验回放(Experience Replay)
  3. 引入目标网络(Target Network)提高稳定性
  4. 直接输出确定性动作

3.2 网络架构设计

Actor网络:输入状态,输出确定性动作

class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).__init__()self.layer1 = nn.Linear(state_dim, 400)self.layer2 = nn.Linear(400, 300)self.layer3 = nn.Linear(300, action_dim)self.max_action = max_actiondef forward(self, x):x = F.relu(self.layer1(x))x = F.relu(self.layer2(x))x = torch.tanh(self.layer3(x)) * self.max_actionreturn x

Critic网络:输入状态和动作,输出Q值估计

class Critic(nn.Module):def __init__(self, state_dim, action_dim):super(Critic, self).__init__()# 第一路网络self.layer1 = nn.Linear(state_dim, 400)self.layer2 = nn.Linear(400 + action_dim, 300)self.layer3 = nn.Linear(300, 1)# 第二路网络(双Q网络)self.layer4 = nn.Linear(state_dim, 400)self.layer5 = nn.Linear(400 + action_dim, 300)self.layer6 = nn.Linear(300, 1)def forward(self, x, u):# 第一路Q值x1 = F.relu(self.layer1(x))x1 = F.relu(self.layer2(torch.cat([x1, u], 1)))q1 = self.layer3(x1)# 第二路Q值x2 = F.relu(self.layer4(x))x2 = F.relu(self.layer5(torch.cat([x2, u], 1)))q2 = self.layer6(x2)return q1, q2def Q1(self, x, u):x1 = F.relu(self.layer1(x))x1 = F.relu(self.layer2(torch.cat([x1, u], 1)))q1 = self.layer3(x1)return q1

3.3 影子车预测模块

影子车(Shadow Car)用于预测未来6秒内的行驶状态,特别是垂向舒适性指标:

class ShadowCar:def __init__(self, car_model, road_profile):self.car_model = copy.deepcopy(car_model)self.road_profile = road_profiledef predict(self, current_state, current_speed, dt=0.1, horizon=60):"""预测未来6秒(60步)的垂向加速度:param current_state: 当前车辆状态:param current_speed: 当前速度(m/s):param dt: 时间步长(s):param horizon: 预测步数:return: 垂向加速度RMS, 最大垂向加速度"""self.car_model.state = current_statevertical_accels = []y_pos = 0  # 相对于当前位置for _ in range(horizon):# 假设保持当前速度匀速行驶y_pos += current_speed * dtroad_height = self.road_profile.get_height(y_pos)a_vertical = self.car_model.update(0, road_height, dt)vertical_accels.append(a_vertical)vertical_accels = np.array(vertical_accels)rms = np.sqrt(np.mean(vertical_accels**2))max_accel = np.max(np.abs(vertical_accels))return rms, max_accel

3.4 完整DDPG算法实现

class DDPG:def __init__(self, state_dim, action_dim, max_action):self.actor = Actor(state_dim, action_dim, max_action).to(device)self.actor_target = Actor(state_dim, action_dim, max_action).to(device)self.actor_target.load_state_dict(self.actor.state_dict())self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=1e-4)self.critic = Critic(state_dim, action_dim).to(device)self.critic_target = Critic(state_dim, action_dim).to(device)self.critic_target.load_state_dict(self.critic.state_dict())self.critic_optimizer = torch.optim.Adam(self.critic.parameters(), lr=1e-3)self.replay_buffer = ReplayBuffer(max_size=1e6)self.max_action = max_actiondef select_action(self, state, noise=None):state = torch.FloatTensor(state.reshape(1, -1)).to(device)action = self.actor(state).cpu().data.numpy().flatten()if noise is not None:action = (action + noise).clip(-self.max_action, self.max_action)return actiondef train(self, batch_size=100, gamma=0.99, tau=0.005):if len(self.replay_buffer) < batch_size:return# 从回放缓冲区采样state, action, reward, next_state, done = self.replay_buffer.sample(batch_size)state = torch.FloatTensor(state).to(device)action = torch.FloatTensor(action).to(device)reward = torch.FloatTensor(reward).reshape((batch_size, 1)).to(device)next_state = torch.FloatTensor(next_state).to(device)done = torch.FloatTensor(done).reshape((batch_size, 1)).to(device)# Critic损失计算with torch.no_grad():next_action = self.actor_target(next_state)target_Q1, target_Q2 = self.critic_target(next_state, next_action)target_Q = reward + (1 - done) * gamma * torch.min(target_Q1, target_Q2)current_Q1, current_Q2 = self.critic(state, action)critic_loss = F.mse_loss(current_Q1, target_Q) + F.mse_loss(current_Q2, target_Q)# 更新Criticself.critic_optimizer.zero_grad()critic_loss.backward()self.critic_optimizer.step()# Actor损失计算actor_loss = -self.critic.Q1(state, self.actor(state)).mean()# 更新Actorself.actor_optimizer.zero_grad()actor_loss.backward()self.actor_optimizer.step()# 软更新目标网络for param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()):target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)for param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()):target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)

4. 训练流程与实验设计

4.1 训练流程

完整的训练流程如下:

def train_ddpg(env, ddpg, episodes=1000, max_steps=1000, batch_size=100):rewards = []best_reward = -float('inf')for episode in range(episodes):state = env.reset()episode_reward = 0noise = OUNoise(env.action_space.shape[0])for step in range(max_steps):# 选择动作并加入探索噪声action = ddpg.select_action(state, noise.sample())# 执行动作next_state, reward, done, _ = env.step(action)# 存储经验ddpg.replay_buffer.add(state, action, reward, next_state, done)# 训练ddpg.train(batch_size)state = next_stateepisode_reward += rewardif done:breakrewards.append(episode_reward)# 保存最佳模型if episode_reward > best_reward:best_reward = episode_rewardtorch.save(ddpg.actor.state_dict(), 'best_actor.pth')torch.save(ddpg.critic.state_dict(), 'best_critic.pth')# 打印进度if episode % 10 == 0:avg_reward = np.mean(rewards[-10:])print(f"Episode {episode}, Reward: {episode_reward:.2f}, Avg Reward (last 10): {avg_reward:.2f}")return rewards

4.2 环境实现

class VehicleControlEnv:def __init__(self, road_data):self.road = RoadProfile(road_data)self.car = QuarterCarModel()self.shadow_car = ShadowCar(self.car, self.road)self.dt = 0.1  # 10Hz控制频率self.max_steps = 1000  # 最大步数(100秒)self.current_step = 0self.y_pos = 0  # 当前位置self.speed = 10  # 初始速度(m/s)self.accel = 0  # 当前加速度# 状态空间和动作空间self.state_dim = 7  # 如前所述self.action_dim = 1self.max_action = 3  # 最大加速度# 用于计算RMS的垂向加速度历史self.vertical_accel_history = []def reset(self):self.current_step = 0self.y_pos = 0self.speed = 10self.accel = 0self.car.state = np.zeros(4)self.vertical_accel_history = []return self._get_state()def _get_state(self):# 获取影子车预测rms, max_a = self.shadow_car.predict(self.car.state, self.speed)# 获取前方路面坡度slope_10m = self._get_slope(10)slope_50m = self._get_slope(50)# 当前垂向加速度current_vertical_accel = self.car.state[1] if len(self.vertical_accel_history) == 0 else self.vertical_accel_history[-1]state = np.array([self.speed,self.accel,current_vertical_accel,rms,max_a,slope_10m,slope_50m])return statedef _get_slope(self, distance):y1 = self.y_posy2 = min(y1 + distance, self.road.length)z1 = self.road.get_height(y1)z2 = self.road.get_height(y2)return (z2 - z1) / (y2 - y1)def step(self, action):action = np.clip(action, -self.max_action, self.max_action)[0]self.accel = action# 更新车辆位置和速度self.y_pos += self.speed * self.dt + 0.5 * self.accel * self.dt**2self.speed += self.accel * self.dt# 确保不超出道路范围if self.y_pos >= self.road.length:done = Trueself.y_pos = self.road.lengthelse:done = False# 更新车辆动力学road_height = self.road.get_height(self.y_pos)vertical_accel = self.car.update(self.accel, road_height, self.dt)self.vertical_accel_history.append(vertical_accel)# 获取新状态next_state = self._get_state()# 计算奖励reward = self.calculate_reward(self._get_state(), action, next_state)# 更新步数self.current_step += 1if self.current_step >= self.max_steps:done = Truereturn next_state, reward, done, {}

4.3 实验设计与参数设置

我们设计了以下实验方案:

  1. 基准测试:固定速度控制器(10m/s, 15m/s, 20m/s)作为基准

  2. DDPG训练:分三个阶段训练:

    • 第一阶段:主要关注速度(奖励权重偏向效率)
    • 第二阶段:平衡速度和舒适性(均衡奖励权重)
    • 第三阶段:主要关注舒适性(奖励权重偏向舒适性)
  3. 评估指标

    • 完成时间(效率)
    • 垂向加速度RMS值(舒适性)
    • 纵向加速度变化率(Jerk)
    • 能量消耗(加速度平方积分)

主要超参数设置:

{"actor_lr": 1e-4,"critic_lr": 1e-3,"batch_size": 100,"gamma": 0.99,"tau": 0.005,"replay_buffer_size": 1e6,"noise_sigma": 0.2,"training_episodes": 1000,"max_steps_per_episode": 1000
}

5. 实验结果与分析

5.1 训练曲线

我们记录了训练过程中的奖励曲线、速度曲线和垂向加速度RMS曲线。图1显示了随着训练进行,累计奖励逐渐提高并趋于稳定,表明算法成功学习到了有效的控制策略。

5.2 性能比较

我们比较了DDPG控制器与固定速度控制器的性能:

指标固定10m/s固定15m/s固定20m/sDDPG控制器
完成时间(s)100.066.750.058.3
垂向加速度RMS(m/s²)0.120.180.250.15
最大垂向加速度(m/s²)0.350.520.730.42
能耗指标0.00.00.012.5

从表中可以看出,DDPG控制器在速度和舒适性之间取得了良好的平衡。相比固定20m/s的速度,虽然完成时间稍长(58.3s vs 50.0s),但垂向加速度RMS显著降低(0.15 vs 0.25),大大提高了乘坐舒适性。

5.3 典型场景分析

我们选取了道路中几个典型场景分析DDPG控制器的行为:

  1. 平坦路段:控制器会适当提高速度,接近最大允许值
  2. 颠簸路段:控制器会自动减速,降低垂向加速度
  3. 下坡路段:利用重力加速度,减少主动加速需求
  4. 上坡路段:平稳增加加速度,避免突然加速造成不适

5.4 消融实验

为了验证各奖励分量的重要性,我们进行了消融实验:

奖励配置完成时间(s)垂向加速度RMS
完整奖励58.30.15
无效率奖励72.10.11
无舒适性奖励51.20.23
无能耗惩罚56.80.16

结果表明,效率奖励和舒适性奖励对控制器的行为有显著影响,而能耗惩罚的影响相对较小。

6. 结论与展望

6.1 研究结论

本研究实现了基于DDPG算法的车辆纵向速度控制系统,能够在保证行驶效率的同时,显著提高乘坐舒适性。通过精心设计的状态空间、动作空间和奖励函数,DDPG算法成功学习到了适应不同路况的控制策略。实验结果表明,与固定速度控制器相比,DDPG控制器能够在较小的效率损失下,大幅降低垂向加速度,提高乘坐舒适性。

6.2 创新点

  1. 提出了结合影子车预测的DDPG控制框架,实现了前瞻性控制
  2. 设计了多目标奖励函数,有效平衡了效率与舒适性
  3. 实现了完整的四分之一车模型与道路环境的交互仿真

6.3 未来工作

  1. 考虑更复杂的整车模型(如七自由度模型)
  2. 引入乘客舒适性的主观评价指标
  3. 研究多车协同场景下的速度控制
  4. 探索基于元学习的自适应控制策略,适应不同道路类型

参考文献

[1] Lillicrap, T. P., et al. “Continuous control with deep reinforcement learning.” arXiv preprint arXiv:1509.02971 (2015).

[2] Sutton, R. S., & Barto, A. G. (2018). Reinforcement learning: An introduction. MIT press.

[3] Rajamani, R. (2011). Vehicle dynamics and control. Springer Science & Business Media.

[4] Fujimoto, S., van Hoof, H., & Meger, D. (2018). Addressing function approximation error in actor-critic methods. arXiv preprint arXiv:1802.09477.

http://www.xdnf.cn/news/1292743.html

相关文章:

  • 《Python学习之基础语法1:从零开始的编程之旅》
  • k8s资源管理
  • GPT-o3回归Plus用户,GPT5拆分三种模式,对标Grok
  • 什么是HTTP的无状态(举例详解)
  • 【C++详解】用红黑树封装模拟实现mymap、myset
  • 【C++】哈希的应用:位图和布隆过滤器
  • Query通过自注意力机制更新(如Transformer解码器的自回归生成)的理解
  • 【Java web】HTTP 与 Web 基础教程
  • 最新去水印小程序系统 前端+后端全套源码 多套模版 免授权
  • 弹性扩展新范式:分布式LLM计算的FastMCP解决方案
  • 可视化调试LangChain SQLChatMessageHistory:SQLite数据库查看全攻略
  • 6 ABP 框架中的事件总线与分布式事件
  • 服务器安全检测与防御技术总结
  • 比特币与区块链:去中心化的技术革命
  • Java毕业设计选题推荐 |基于SpringBoot的水产养殖管理系统 智能水产养殖监测系统 水产养殖小程序
  • TensorFlow实现回归分析详解
  • 把 Linux 装进“小盒子”——边缘计算场景下的 Linux 裁剪、启动与远程运维全景指南
  • 各种排序算法(二)
  • 升级Gradle版本后,安卓点击事件使用了SwitchCase的情况下,报错无法使用的解决方案
  • PCBA:电子产品制造的核心环节
  • MCP协议更新:从HTTP+SSE到Streamable HTTP,大模型通信的进化之路
  • 记某一次仿真渗透测试
  • 开发Excel Add-in的心得笔记
  • [系统架构]系统架构基础知识(一)
  • 基于elk实现分布式日志
  • 2025 开源语音合成模型全景解析:从工业级性能到创新架构的技术图谱
  • 我们计划编写一个闲鱼监控脚本,主要功能是监控特定关键词的商品,并在发现新商品时通过钉钉机器人推送通知。
  • LCP 17. 速算机器人
  • 从开发工程师视角看TTS语音合成芯片
  • 基于数据驱动来写提示词(一)