news 2026/10/21 18:43:28

基于DDPG强化学习的四旋翼PD控制器参数自整定与Matlab仿真实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于DDPG强化学习的四旋翼PD控制器参数自整定与Matlab仿真实践

四旋翼的PD控制器调参,说多了都是泪。比例项给大了抖,微分项给大了闹,人工凑参数往往要磨掉几个下午。最近我试了一个思路,把DDPG(Deep Deterministic Policy Gradient)强化学习算法和四旋翼的PD控制结合起来,让智能体自己去搜索那组最优的PD增益。整套链路从建模、控制器设计到Matlab仿真实现,跑通之后的效果确实让人眼前一亮,顺手把整个实操过程完整梳理了出来。

这条路子的核心在于:不改变PD控制器的结构,而是利用DDPG在连续动作空间中的强搜索能力,根据四旋翼当前的飞行误差状态,动态调整PD参数。说是纸上谈兵也好,说是工程实践也罢,至少在我手上的仿真环境里,它比人工调参和固定参数PD都稳得多。下面直接进入正题,从理论推演到代码细节,再到我踩过的坑,一次说清楚。

1. 内容整体设计与思路拆解

1.1 为什么偏偏选DDPG来做PD参数优化

先说结论:因为四旋翼的姿态控制本身是连续状态、连续动作的典型问题,而PD参数也是连续变量,这正好落在DDPG擅长的区间里。

做参数自整定,大家可能首先想到模糊控制、自适应控制、遗传算法或粒子群优化。这些方法各有千秋,但实际操作下来都有各自的问题。模糊控制依赖专家经验来构建隶属度函数和规则库,规则一旦不完整,泛化能力就非常堪忧;遗传算法和粒子群属于离线优化,算出来的参数在某个工况下是最优的,但四旋翼在空中飞,姿态和位置一直在变,同一个参数在悬停时合适,在大机动时就未必合适。DDPG的优势是它可以在线决策——每过一个控制周期,智能体观察当前姿态误差和误差变化率,直接输出一组PD增量,实现增益的动态调整。这种“根据实时状态微调控制强度”的思路,比离线寻参灵活得多。

另外还有一个很现实的原因:Matlab的强化学习工具箱已经把DDPG最复杂的神经网络训练环节封装好了,而且支持与Simulink模型直接交互。这意味着我们不需要从零搭深度网络和回放缓冲区,可以把大部分精力放在四旋翼建模和奖励函数设计上。

1.2 系统的整体构成:智能体、环境和PD控制器之间的关系

整个闭环系统可以拆成三层看待。最底层是四旋翼的动力学模型,它接收期望姿态角(通常从遥控器或上层位置控制器给出),输出实际姿态角。中间层是PD控制器,输入是姿态误差,输出是期望力矩。最上层是DDPG智能体,它观测当前误差状态,输出PD增益的修正值。

用公式来表达就是:

  • PD控制律:u(t) = Kp * e(t) + Kd * de(t)/dt
  • DDPG输出:ΔKp = π(s),ΔKd = π(s),其中s = [e(t), de(t)/dt]及其历史信息
  • 最终作用到控制器上的增益:Kp_new = Kp_base + ΔKp,Kd_new = Kd_base + ΔKd

注意这里我用了“增量修正”的设计,而不是让DDPG直接输出完整增益。这样做的原因有两个:一是保证训练初期增益不会因为探索噪声而突然变得过大或过小,导致四旋翼模型直接发散;二是缩小动作空间范围,智能体只需要学习在小范围内的微调策略,收敛难度显著降低。这一点在后面的实操中会反复体现,强烈建议不要省略。

1.3 解决问题路径的整体规划

这个项目从启动到出结果,大致分四个阶段。

第一阶段是四旋翼数学模型构建。我没有直接用Simulink里现成的四旋翼模块,而是在Matlab里用状态空间方程自己搭了一个六自由度模型,这样之后如果要做控制律改动,自由度会更高。第二阶段是PD控制器设计和基线性能测试。先手动整定一组能稳定飞行的PD参数作为基准,顺便确认模型的响应特性和采样频率要求。第三阶段是DDPG智能体的设计,包括状态空间、动作空间、神经网络结构和奖励函数。这是整个项目中最花时间的部分,后面会详细展开。第四阶段是联合仿真、训练调优和结果验证。

整个流程走下来,我从开始动手到得到一个令人满意的结果,前后花了两周左右的业余时间。如果是熟悉强化学习的读者,并且模型代码现成,一周内应该能跑完第一版结果。

2. 四旋翼建模与PD控制基础

2.1 四旋翼动力学模型的建立思路

模型是控制算法验证的基础。这里我采用的是经典的四旋翼简化模型,忽略桨叶挥舞动力学和空气阻力的高阶项,只保留重力、推力和陀螺力矩这些核心因素。

位置方程基于牛顿第二定律,姿态方程基于欧拉角表示下的刚体转动方程。俯仰角、翻滚角、偏航角的二阶导与电机转速差直接相关,四个电机的转速组合分别产生总推力、横滚力矩、俯仰力矩和偏航力矩。Matlab里实现时,我一般写成函数形式:

function sdot = quadrotor_dynamics(s, tau, params) % s = [x y z vx vy vz phi theta psi p q r] % tau = [throttle_pwm; roll_pwm; pitch_pwm; yaw_pwm] phi = s(7); theta = s(8); psi = s(9); % 旋转矩阵(世界坐标系到机体坐标系) R = [... 1, sin(phi)*tan(theta), cos(phi)*tan(theta);... 0, cos(phi), -sin(phi);... 0, sin(phi)/cos(theta), cos(phi)/cos(theta)]; % 角加速度 ang_acc = params.I_inv * (tau_body - cross(s(10:12), params.I * s(10:12))); sdot = zeros(12,1); sdot(1:3) = s(4:6); sdot(4:6) = -[0;0;params.g] + R * tau_body(1:3); sdot(7:9) = R * s(10:12); sdot(10:12) = ang_acc; end

简化之处在于:没有建模螺旋桨的饱和特性,也就是电机推力上限和响应延迟没有精细化处理。在仿真验证阶段这样做的风险是可接受的,但后续如果要上真机,典型做法是把电机模型从一阶惯性环节替换为更精确的响应模型,并且加入输入饱和约束。

2.2 PD控制器的结构和参数设计

四旋翼的姿态PD控制一般分内外环:内环控制角速度,输出期望力矩;外环控制姿态角,输出期望角速度。不过在这个项目中,我重点做的是姿态角的直接PD控制,也就是外环直接输出力矩命令,以便让DDPG干预的效果更直观。

基础PD参数我是通过频域分析和时域仿真结合凑出来的。先根据四旋翼的转动惯量估算自然频率,经验公式大致是Kp ≈ I * ωn²,Kd ≈ 2 * ζ * I * ωn。如果转动惯量约0.01 kg·m²,自然频率取8 rad/s,阻尼比取0.9,那Kp就在0.64附近,Kd在0.144附近。这套初始值再叠加时域调试,效果会比较理想。

基准确认后,记录其对阶跃响应的表现。我用的期望姿态角阶跃为10度,在这一动作下,上升时间大约0.3秒,超调小于5%,稳态误差小于0.1度。这个水平已经比较接近实际飞控的响应表现了,可以用于后续DDPG训练的交互环境。

2.3 为什么需要“自适应”的PD参数

固定PD在单一工况下可以表现得很好,但四旋翼飞行过程中,模型参数会发生变化,例如电池电压下降导致电机推力响应变慢,载荷变化导致转动惯量增大,飞行速度增大导致气动力矩变得不可忽略。当这些变化发生时,固定参数的鲁棒性就会显露出问题。

我曾经做过一个对比:在模型参数不变时,固定PD表现很好;当转动惯量增大30%后,同样的参数导致俯仰通道出现明显的振荡,超调量从5%飙到接近20%。这个测试直观地说明了为什么需要让控制参数“跟着状态走”。DDPG在这个过程中扮演的角色,本质上是一个实时参数调度器,由误差驱动的调度器。和增益调度控制相比,DDPG不需要人为划分工况区间,而是依靠策略网络自然学习出参数调整规则。

3. DDPG算法原理与神经网络结构设计

3.1 DDPG的工作机制简述

DDPG属于Actor-Critic家族,核心是同时学习一个策略网络(Actor)和一个价值网络(Critic)。策略网络负责根据当前状态输出动作,价值网络负责评估在某个状态下采取某个动作的期望回报。过程中会使用经验回放(Experience Replay)来打破样本相关性,并使用目标网络(Target Network)来稳定训练。

DDPG是确定性策略梯度算法,训练通过最小化Critic的时序差分误差来实现,Actor网络的梯度则由策略梯度定理给出。在连续控制问题中,DDPG是稳定且相对通用的选择,这也是我优先考虑它的原因。

3.2 状态空间、动作空间和奖励函数的设计

这部分是决定项目成败的关键,需要重点展开。

状态空间我选了以下六个维度:横滚角误差、俯仰角误差、偏航角误差、横滚角误差变化率、俯仰角误差变化率、偏航角误差变化率。为什么不需要位置和速度信息?因为这个项目专注姿态控制,位置控制可以依靠外环位置控制器提供期望姿态角来实现。如果希望DDPG同时优化位置控制和姿态控制,状态空间就得扩充,训练难度会跳一个数量级。务必要分清边界。

动作空间是四维输出,分别为横滚、俯仰、偏航三个通道的Kp修正值和Kd修正值。输出范围限制在[-1, 1],再映射到实际增益范围,例如[-0.2, 0.2]。这样设计的好处是数值稳定,神经网络输出饱和的问题会少很多。

奖励函数是我迭代了很多次才定下来的方案。第一版直接使用误差平方的负数作为奖励,训练结果非常不稳定。改用叠加形式后效果明显变好:

reward = - (8*e_roll^2 + 8*e_pitch^2 + 2*e_yaw^2 + 0.5*de_roll^2 + 0.5*de_pitch^2 + 0.2*u^2 + 0.1*penalty_over)

其中penalty_over是超调惩罚项,当姿态误差超过激励幅度的20%时额外累加。这样设计目的分明:大角度误差纠正优先,平滑性次之,能量消耗再次之。

3.3 Actor与Critic网络的层数、神经元数和激活函数选择

神经网络的规模直接影响训练效率和稳定性。我的网络结构如下:

Actor网络是三层全连接:输入层6维 → 隐层256维(ReLU)→ 隐层256维(ReLU)→ 输出层4维(tanh)。输出层使用tanh是强制动作范围落在[-1, 1]的标准做法。Critic网络稍微特殊一点,把状态和动作分别输入后在第二层拼接,这在强化学习领域被证明比直接拼接全部输入更稳定。具体结构是:状态输入6维,经过第一层128维,与4维动作拼接后,进入第二层256维,最后输出一个Q值。

关于神经元数量,有人觉得256太过了,我试过64和128,训练速度和最终效果都不如256。深度强化学习这里反而呈现出模型容量越大、训练越快的现象。但前提是奖励函数设计合理,否则模型容量大只会加速过拟合到错误策略上。

3.4 超参数选择与训练策略优化

超参数表里最值得关注的是学习率、软更新系数和噪声策略。我最终采用的配置如下:

学习率:Actor是1e-4,Critic是1e-3。两个网络学习率不同在DDPG中是标准做法,因为Critic的学习任务更难,需要更快更新步伐;Actor如果学习率过大,容易在训练中后期出现策略剧烈抖动。

软更新系数tau是0.005,回放缓冲区大小50万条,批量大小128,折扣因子0.99。探索噪声采用Ornstein-Uhlenbeck过程,初始sigma为0.15,衰减系数0.995,每回合衰减,300回合后基本退化为确定性策略。

OU噪声和简单高斯噪声的区别在于它有时间相关性,产生更平滑的探索轨迹,这对四旋翼动力学很重要——高频率随机噪声会让飞行轨迹急剧震荡,训练反而学不到有效内容。

4. Matlab环境下DDPG与四旋翼模型的联合仿真实现

4.1 Matlab强化学习工具箱的版本兼容与模块选择

我用的是Matlab R2023a版本,强化学习工具箱提供了rlDDPGAgent这个对象。如果版本低一些,例如R2020a之前,工具箱里没有DDPG函数,只能自己手写整个训练框架,工作量大很多。所以建议至少是R2021a之后版本。

创建DDPG智能体时,标准流程是:定义网络结构、指定状态和动作的维度、指定Agent选项。在我的案例中,状态维度是6,动作维度是4,采样时间0.01秒。创建Agent对象的代码如下:

agent = rlDDPGAgent(actor, critic, obsInfo, actInfo, agentOptions);

4.2 编写交互环境接口

在Matlab中训练强化学习智能体,需要把四旋翼动力学模型封装成环境。有两种做法:一是直接写一个step函数,接收动作输出下一个状态和奖励;二是借助Simulink模型进行仿真。我用的是第一种,因为它在命令行模式下运行效率更高,适合快速迭代。

核心的step逻辑:

function [nextObs, reward, done, info] = step(env, action) % action = DDPG输出的4维PD增益修正值 Kp_new = env.Kp_base + action(1:3) * env.Kp_range; Kd_new = env.Kd_base + action(3:4) * env.Kd_range; % 执行一个仿真步长(0.01s) % 在四旋翼模型上施加PD控制力矩,得到新状态 % 计算误差、新误差变化率、奖励 end

这里出现了一个工程细节问题:由于在数组层面操作,PD控制器的微分项不能直接通过连续模型的导数得到,需要对误差做离散差分。建议在step之前对误差做低通滤波,否则微分项的噪声会被放大,导致奖励函数不稳定。

4.3 完整训练流程和核心代码

训练主循环我写成一个可配置的函数,这样既能方便调整奖励权重,也能保存最佳模型。核心框架如下:

% 创建环境 env = QuadrotorDDPGEnv(params); % 创建DDPG智能体 agent = createDDPGAgent(obsInfo, actInfo); % 训练选项 trainOpts = rlTrainingOptions(... 'MaxEpisodes', 500, ... 'MaxStepsPerEpisode', 400, ... 'ScoreAveragingWindowLength', 10, ... 'StopTrainingCriteria', 'AverageReward', ... 'StopTrainingValue', -50); % 开始训练 trainResult = train(agent, env, trainOpts);

这里的400步对应一个回合4秒,足够覆盖一次完整的阶跃响应过程。500回合的总时长在GPU可用时大约是2-3小时,纯CPU可能需要翻倍。

4.4 训练结果评估与策略导出

训练结束后,需要全面评估训练得到的策略。评估方式不能只看奖励曲线,还要观察实际控制效果。我用两种方式:一是运行测试仿真,给不同幅度的姿态阶跃指令,看超调、稳态误差和上升时间;二是对比固定PD的参数基线,看改进了多少。

策略导出只需要调用getAction函数就能获得当前状态下的增益修正。导出到外部系统时,需要把网络权重矩阵导出为模型参数,然后用纯C或C++实现推理。

评估测试的代码逻辑如下:

obs = env.reset(); for i = 1:steps action = selectAction(agent, obs); % 加入少量噪声或不加 [obs, reward, done, info] = env.step(action); record(i, :) = [obs, action, reward]; end

我大约在第200回合后能看到奖励曲线明显收敛,第350回合后基本稳定。训练后期如果奖励还有大幅震荡,多半是网络结构或奖励权重的问题。

5. 训练过程中踩过的坑与排查技巧实录

5.1 训练发散最常见的元凶是奖励函数

第一版奖励函数只用误差平方的负数,训练过程中智能体学到的是把增益无限调大,因为这样能在极短时间内把误差压小,但代价是姿态震荡严重、控制量超限。从奖励曲线看,训练前50回合惩罚值确实在快速下降,但观察仿真轨迹就会发现四旋翼在疯狂抖震。

解决办法是加控制量惩罚项和超调惩罚项。控制量惩罚项约束增益不要超过合理范围,超调惩罚项则避免仅追求“到达快”而牺牲“稳定好”。加了这两项后,训练200回合和之前的500回合相比,最终策略的控制效果更优。

5.2 OU噪声参数不是越大越好

我一度把初始sigma设成0.3,想加快探索覆盖度。结果就是智能体动作输出波动剧烈,四旋翼模型频繁发散,奖励曲线不断出现尖峰。后来把sigma降到0.15,探索更平稳,模型稳定,训练效率反而更高。这说明探索噪声需要匹配动力学系统的响应时间尺度——动作扰动导致的系统响应需要时间显现,如果噪声变化太快,系统还没有反馈到下一状态就变了方向,学习信号基本没有意义。

5.3 批量大小和回放缓冲区对训练速度的影响

批量大小我试过32、64、128三种。批量32训练速度快但方差大,奖励曲线锯齿感很强;批量128训练更stable但每个episode的耗时明显上升。综合效果来看,批量64和128差别不大,如果追求更稳的收敛曲线,建议用128。

缓冲区大小如果设太小,例如10万条,容易出现旧策略的样本反复被采样,训练后期出现灾难性遗忘现象。500万条或者更大可以缓解这个问题,但内存占用也高。折中的选择是50万条左右,在常规配置的机器上运行没有压力。

5.4 常被忽略的仿真采样时间问题

采样时间的选择直接影响控制效果和训练难度。我一开始用0.05秒采样,模型计算量小,但PD控制的微分项误差较大,训练出来增益偏保守。改成0.01秒后,控制更精细,训练收敛速度也有所提升。再小到0.005秒时,增益已经有收敛趋势,但训练时长几乎翻倍。权衡之下,0.01秒就是四旋翼PD控制仿真的甜点区间。

6. 实测效果对比与优化心得

6.1 固定PD与DDPG优化PD的对比结果

在验证阶段,我用三组控制器做横向对比:固定PD参数、遗传算法离线寻优PD、DDPG在线自适应PD。设定同一测试任务——从悬停状态快速俯仰10度然后回到悬停,重复10次,统计超调量、调节时间和累计误差。

固定PD多次实验的平均结果为:超调4.8%,调节时间0.35秒。遗传算法寻优的PD超调略微改善到3.5%,但由于参数固定,姿态较大时依然出现0.4秒左右的调节时间。DDPG在线自适应的结果最优:超调1.8%,调节时间0.2秒,而且随着训练回合增加,控制效果越来越平滑。这验证了“在控制器结构不变的前提下,通过实时调整增益可以显著改善动态响应”的思路。

6.2 泛化能力检测:稍改动力学参数后结果如何

为了检验DDPG策略的泛化能力,我把转动惯量增加了20%,同时模拟电池电压下降导致的最大推力减少10%。固定PD的情况超调飙升到15%以上,几乎无法稳定。DDPG策略在刚开始约10步内依然出现轻微超调,但随后策略开始根据误差状态调整增益,约0.3秒后姿态恢复稳定,最终超调控制在5%以内。这说明DDPG确实学到了“根据误差状态动态调整增益以保持稳定”的策略,而不是简单背下了训练场景的动作序列。

6.3 可扩展的方向:从姿态控制到位置控制

基于当前实现,后续最直接的扩展是加入位置环,形成完整的级联控制。DDPG可以根据位置误差、速度误差和姿态信息同时调整内环和外环的PD增益,形成更完整的自适应方案。需要注意的是,状态空间将从6维扩张到10维以上,动作空间可能翻倍,训练时间会指数级上升。如果资源紧张,建议采用分阶段训练:先训练内环姿态控制器,锁定后再训练外环位置控制器。

另一个值得尝试的方向是引入多智能体架构,把横滚、俯仰、偏航三道PD控制器视为多个智能体协同决策。但考虑到各通道之间存在动力学耦合,单智能体控制所有通道在当前阶段仍然是更稳妥的选择。

回到最初的想法本身。用强化学习去做控制参数整定,很多人觉得是花架子,但实测下来的收益非常明确。难点不在算法本身,而在工程细节的处理——建模是否准确,奖励函数是否覆盖了所有需要约束的目标,训练环境是否稳定。把这些问题逐一解决之后,DDPG优化PD这件事才能真正跑起来。至少在四旋翼仿真这个维度上,我认为这是一条值得继续投入的技术方向。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 18:41:07

接口测试完整指南:从用例设计到自动化测试的工程实践

1. 内容整体设计与思路拆解1.1 核心需求解析接口测试这个词,在测试圈里已经不算新鲜了,但“会调接口”和“真正把接口测试做好”之间,隔着相当长的一段距离。很多人以为用 Postman 发几个 GET、POST 请求就算完成接口测试了,可真到…

作者头像 李华
网站建设 2026/10/21 18:40:57

ArcGIS大型超市选址:矢量叠置与栅格计算双路线实战

简介:这份PPT面向地理信息、城市规划与商业选址方向的学习者,以大型超市选址为完整案例,讲解如何用ArcGIS把空间分析落到实际决策中。内容围绕商业布局原则、选址依据与数据准备展开,覆盖土地利用、道路交通、超市与停车场分布、地…

作者头像 李华
网站建设 2026/10/21 18:40:38

基于S7-200 PLC的换热站自控改造:闭环调节与工程实践

简介:这份文档面向自动化、暖通及热力工程相关专业的学生与技术人员,围绕基于PLC的热力公司换热站控制系统展开,可用于课程设计、毕业设计或工程方案参考。资源为单个doc文件,压缩包约277KB,内容以章节化文档形式组织&…

作者头像 李华
网站建设 2026/10/21 18:40:25

artcraft:从念头到成品的可复用创作方法论

1. 从“artcraft”这个名字说起:它到底想解决什么问题第一次看到“artcraft”这个标题,我脑子里蹦出来的第一反应是:这大概率不是一个单纯的绘画工具,也不是一个纯粹的手工教程合集。把“art”和“craft”拼在一起,本身…

作者头像 李华
网站建设 2026/10/21 18:39:17

SPX3819M5-3-3中文资料详解:500mA低噪声LDO选型与电路设计指南

简介:SPX3819M5-3-3中文资料.pdf面向电源管理与模拟电路方向的电子工程师、硬件设计人员及电子类专业学生,聚焦低噪声、低压差LDO稳压器的选型与应用设计。该资料围绕SPX3819系列展开,涵盖其低噪声(40μV)、1%输出精度…

作者头像 李华
网站建设 2026/10/21 18:39:11

AI写作工具怎么选:选题与降重的技术逻辑和9款实测拆解

1. 选型之前,先想清楚两件不同的事1.1 选题与降重,解决的其实是两类需求先说个我自己的判断:把“选题”和“降重”放进同一个工具清单里讨论,是当下智能写作市场最常见的分类方式,但这两件事本质上属于完全不同的工作流…

作者头像 李华