ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于强化学习的自适应机器人控制算法:MATLAB/Simulink训练链路详解

基于强化学习的自适应机器人控制算法:MATLAB/Simulink训练链路详解 简介这是一份基于强化学习与自适应控制理论学习和策略更新源码包面向机器人控制、自动化与人工智能方向的研究者和工程师用于在未知或变化环境中训练机器人自主调整行为策略。压缩包共127个文件以106个MATLAB脚本为主体覆盖学习算法、经验回放、仿真启停等关键模块另有jpg、png、gif图片、fig模型图以及说明文档方便查看训练状态、理解模块结构整体大小336KB体量轻、便于使用。目前已有853人浏览学习。项目将经验回放与在线学习机制融入Simulink仿真环境结合自适应控制思想帮助机器人应对环境不确定性整体代码结构划分清晰启动与清理脚本齐备随附的图片可辅助核对算法流程与状态变化适合二次开发、教学演示或课程设计参考。1. 基于强化学习的自适应机器人控制算法到底在解决什么难题机械臂抓一个 20kg 的工件和抓一个空抓手动态特性差了好几倍。传统控制器的做法是提前把模型算准负载一变就得重新调 PID 增益或重新辨识参数而“基于强化学习的自适应机器人控制算法”把这件事变成了训练问题——让控制策略在奖励函数和域随机化的作用下自己学会对不同负载、摩擦甚至模型误差输出合适的力矩。它适合那些模型不精确、环境会变、又不愿意每个工况都重新写控制器的场景比如协作机械臂末端负载变化、移动机器人车轮打滑、管道机器人通过变径管段时的驱动力再分配。但这里要先泼一盆冷水它不是什么魔法。训练时间不短奖励函数要反复调仿真里学好的策略搬到真实机械臂上还得再做一轮安全验证。这篇文章我把在 MATLAB/Simulink 里从零搭一条训练链路的完整步骤拆开从环境模型怎么建、状态与奖励怎么设计到 DDPG/TD3/SAC 怎么选、部署时有哪些坑尽量写到你能照着复现的程度。2. 搭建最小可训环境MATLAB工具箱、Simulink模型与一次能跑通的训练链路自适应控制依赖环境的动态模型强化学习训练更需要一个“能被打断、能重置、能注入随机参数”的仿真环境。这套东西在 Simulink 里实现是最顺手的因为模型本身就是 Simulink 的Agent 通过一个 RL Agent 块挂在模型里状态和动作通过端口交互。2.1 工具箱与版本核对别让版本差异浪费一整天先把依赖说清楚。你要跑通这一篇文章里的流程至少需要这些组件MATLAB 本体、Simulink、Deep Learning Toolbox、Reinforcement Learning Toolbox。如果想做后续的实时验证和代码生成再往上加 Simulink Coder 和 Simulink Desktop Real-Time如果只想验证算法研究结论前面四个足够。版本上我吃过亏。Reinforcement Learning Toolbox 从 R2019a 之后才比较稳定地支持 rlNumericSpec、rlSimulinkEnv 这一套 APIR2022a 之后 SAC、TD3 的实现才比较完整。你如果拿到一个“算法实现.zip”第一步一定是在 MATLAB 里看版本再用ver确认工具箱有没有装齐而不是双击模型就点运行。常见做法是先把命令行里这几句跑一遍ver(reinforcement) ver(simulink) ver(deep)这三行的作用是确认核心工具箱是否可用。如果有 1 个工具箱缺失后面的 train 函数会直接报 undefined function而且报错信息经常不直接提示缺工具箱而是说“无法解析函数或变量”很容易误判成模型错误。这里面最容易漏的是 Deep Learning ToolboxRL Toolbox 的 actor 和 critic 都建立在深度神经网络上深度学习工具箱没了它连网络创建都过不去。2.2 在 Simulink 里搭出机器人被控对象的三种模型层次训练用模型可以分成三个递进层次单关节刚性模型、双连杆机械臂模型、带柔性关节和接触力的高保真模型。做算法验证我建议从单关节开始不是说高保真模型不好而是强化学习训练第一轮实验大概率要改环境接口模型越复杂排查链路越长。单关节模型的运动方程是典型的二阶系统J * theta_ddot tau - b * theta_dot - m * g * l * sin(theta)在 Simulink 里搭这个模型只需要四个基础模块两个 Integrator 串联得到角速度和角度一个 Gain 放惯量倒数一个 Sin 模块算重力项。我用普通仿真Normal Mode时会把求解器设为固定步长离散步长 0.01s。模型层放一个 Constant 表示负载质量 m这样后面 ResetFcn 可以随机改它。双连杆机械臂模型则要加上科里奥利力和耦合惯量项运动方程会变成 M(q)q_ddot C(q, q_dot)q_dot G(q) tau。这一层适合验证算法在高耦合非线性下的表现但训练时间大约是单关节模型的 3 到 5 倍。如果目标是产品落地前验证自适应控制方案我一般会在单关节模型上把 Agent、奖励、观测设计全部调通再整体平移到双连杆模型上重新训练。模型层次Simulink 建模要点适合验证什么训练成本单关节刚性两个积分器 重力项 摩擦项算法链路、负载自适应低双连杆平面臂M(q)/C(q)/G(q) 矩阵运算耦合非线性、轨迹跟踪中带接触力机械臂Simscape Multibody 刚体建模柔顺控制、打磨/装配类任务高2.3 用 rlSimulinkEnv 把 Agent 接到模型环境创建代码与参数说明模型搭好后接下来要做的不是直接放点训练而是先创建强化学习环境对象。这一步相当于告诉 RL Toolbox“Simulink 模型里哪个块是 Agent、状态有几维、动作有几维、范围多大。”% 定义观测空间6 维分别对应角度、角速度、角度误差、角速度误差、目标角度、负载估计 obsInfo rlNumericSpec([6 1], ... LowerLimit, -inf * ones(6,1), ... UpperLimit, inf * ones(6,1)); obsInfo.Name joint_obs; % 定义动作空间1 维连续力矩单位 N*m actInfo rlNumericSpec([1 1], ... LowerLimit, -20, ... UpperLimit, 20); actInfo.Name joint_tau; % 关联 Simulink 模型与环境 env rlSimulinkEnv(rl_single_joint, rl_single_joint/RL Agent, obsInfo, actInfo); % 每次 episode 开始前重置模型参数 env.ResetFcn (in) localResetFcn(in);这里重点说三个参数。第一obsInfo 的维度一旦定了Simulink 模型里 RL Agent 块的输入端口宽度就必须是 6输出端口宽度是 1两边不匹配会在仿真开头报维度错。第二actInfo 的上限不是越大越好力矩上限和机械臂物理约束要匹配设成 20 意味着策略最大输出 20N·m超过真实关节可承受范围训练出的策略部署时必炸。第三env.ResetFcn 是自适应能力的关键——它允许每次 episode 开始时随机改变模型里的质量、摩擦、初始角度。function in localResetFcn(in) blk rl_single_joint/mass; in setBlockParameter(in, blk, Value, num2str(0.5 2 * rand)); blk0 rl_single_joint/theta0; in setBlockParameter(in, blk0, Value, num2str(-pi 2 * pi * rand)); end这个 ResetFcn 体现了强化学习和传统自适应控制打法上最大的差异传统方法靠在线辨识去估计质量参数RL 方法靠训练时把质量放在随机范围里反复采样让策略见过足够多“负载不同但目标相同”的局面从而学会在控制过程中自动补偿。你这套方案里如果没有 ResetFcn策略学到的只是在固定质量下的一个普通反馈控制器根本谈不上自适应。2.4 第一次训练选项先定义“什么算学会”环境创建完就可以先放一个最简单的 Agent 上去跑。这里我用 DDPG 做首次链路验证因为它结构最简单出了问题好查。initOpts rlOptimizerOptions(LearnRate, 1e-3, GradientThreshold, 1); agentOpts rlDDPGAgentOptions(... SampleTime, 0.01, ... MiniBatchSize, 128, ... ExperienceBufferLength, 1e6, ... AgentOptimizerOptions, initOpts); agent rlDDPGAgent(obsInfo, actInfo, agentOpts); trainOpts rlTrainingOptions(... MaxEpisodes, 500, ... MaxStepsPerEpisode, 300, ... ScoreAveragingWindowLength, 10, ... StopTrainingCriteria, AverageReward, ... StopTrainingValue, -2, ... Plots, training-progress, ... Verbose, true); stats train(agent, env, trainOpts);几个参数的取舍值得单独说。SampleTime 也就是 RL Agent 的采样周期Simulink 里被控对象仿真步长如果是 0.01sSampleTime 通常也设 0.01如果对象的动力学变化更快比如关节刚度很大采样周期要缩到 0.001~0.005。StopTrainingCriteria 是训练提前结束的条件不要一开始就把数值设太理想先看一眼训练曲线的走势再修正。我一般第一次训练用 500 个 episode看 AverageReward 是否还在上涨如果 500 个 episode 曲线还没有平稳迹象就加到 1500 再跑一次。提示如果遇到“Error: Invalid input signal type”这类报错先检查动力学模型输出是不是 double 类型、有没有把 boolean 信号传进 RL Agent这类问题比算法本身更频繁。3. 状态、动作与奖励设计自适应能力的来源全在这三个定义里很多人以为强化学习最难的是算法选型实际在机器人控制场景里状态、动作、奖励设计占到整个调试工作量的七成。策略本质上是在拟合“观测到状态-输出动作”的映射状态里没有的信息它无论如何也学不出来奖励函数里表达不清楚的目标它就会想办法钻空子。3.1 状态空间设计把负载信息显式送进网络单关节模型里最基本的状态是角度和角速度。如果只看这两个量策略最多能学成一个固定参数下的反馈控制器。要让控制具备自适应能力状态里必须包含能反映系统变化的信息常见做法有三个方向。第一个方向是把目标信号做进状态角度误差和角速度误差同时进网络这比只给绝对角度好训练因为策略不需要对每个目标角度单独记一套映射。第二个方向是把负载估计或与负载相关的信息送进去可以是外力矩估计、电流信号折算的负载质量也可以是摩擦系数的在线估计值。第三个方向是“把因果信息直接铺开”把目标角度、当前角度、当前角速度、误差、误差变化率、负载估计六维打包成一个向量这有点类似于因果强化学习 CRL 的思路——不要让网络从相关关系里自己反推因果直接把原因变量摆在输入里学起来快得多。我验证过的状态向量是obs [theta; theta_dot; theta - theta_ref; theta_dot - theta_ref_dot; theta_ref; m_hat]theta_ref 是目标轨迹位置m_hat 是负载质量或它的粗估计值。仿真里可以直接把真实质量接进去真机部署时如果估计不准训练时要把 m_hat 叠加噪声。这里有一个很多人会忽略的细节状态量的物理单位差别很大角度是零点几弧度角速度可能是几负载质量可能是几十原始值直接喂网络会让梯度被大数值量纲主导必须在模型出口做归一化。3.2 动作空间设计输出力矩还是输出目标角速度连续动作空间的配置直接决定控制器的底层行为。两种常用方案差异很大。第一种方案动作是关节力矩RL Agent 直接取代整个控制回路。优点是没有中间层策略自由度最大缺点也很明显策略学到的力矩可能有高频抖动部署到真实关节上冲击很大。第二种方案动作是目标角速度或目标角度下层再挂一个 PD 控制器去跟踪RL 只负责生成参考轨迹。这种分层结构的优点是动作平滑性好、安全性高代价是控制性能受下层 PD 影响RL 的自适应能力被部分遮盖了。我一般在 Simulink 验证阶段用第一种方案因为要看算法本身能不能处理模型不确定性真机部署前切到第二种在 RL Agent 块后面串联一个饱和限制和一个低通滤波。即使这样做会损失一点精度也值得因为真实执行器受不了训练策略里那种剧烈抖动力矩。% 在 Simulink 的 RL Agent 块之后加一个饱和模块 % Saturation 上限: 15 N*m下限: -15 N*m % 然后再串联一个 Transfer Fcn: 1/(0.02s1) 做力矩平滑这个串联结构看起来打破了“强化学习直接输出最终指令”的纯粹性但它换来的是部署安全性。饱和限制同时也保护了训练过程如果力矩输出超过物理极限仿真模型会出现积分发散奖励曲线瞬间崩掉而且这种崩溃看起来很像算法不收敛实际是环境数值爆了。3.3 奖励函数设计量纲配平与四类常见“走捷径”行为自适应控制的奖励函数至少包含三项跟踪误差、控制能量、控制变化率。跟踪误差用二次型让策略对偏差敏感控制能量项防止策略用大额力矩硬顶控制变化率项抑制抖动。一个可以稳定跑通的奖励函数示例像这样function reward tracking_reward(theta, theta_dot, theta_ref, tau, tau_prev) err theta - theta_ref; err_dot theta_dot - theta_ref_dot; reward -(err^2 0.1 * err_dot^2 0.001 * tau^2 0.005 * (tau - tau_prev)^2); end这个函数写成 Simulink 里的 MATLAB Function 块输入直接接状态和动作信号。参数配比的经验是先让误差项的量级在 0.01~1 之间能量项和抖动项分别压到误差项的 1/10 和 1/100 左右。如果力矩值本身就在 10N·m 量级0.001 的系数乘出来是 0.1和误差项同一量级这时候策略就会在“减少误差”和“节省力矩”之间找到平衡而不是被能量项主导到不敢出力。奖励设计里常见的“走捷径”现象有三个。第一个是策略把关节停在目标角度附近靠重力抵消误差而不是真正跟踪轨迹表现为误差不大但速度始终为零解决办法是在误差项之外再加一个与速度相关的跟踪项。第二个是策略学会在每个 episode 开始时故意让初始状态更有利如果 ResetFcn 在 episode 开始后才改变目标位置策略可能通过“先不动、等目标过来”的方式刷奖励解决办法是确保目标角度在 episode 开始时已固定。第三个是奖励项之间互相打架能量项过大会导致策略“躺平”干脆输出零力矩奖励虽低但稳定训练曲线直接收敛到一个次优值。3.4 域随机化自适应训练的临门一脚域随机化是自适应控制里最值得投入时间的设计技巧。它的思想非常简单训练时不只用一组固定的物理参数而是在每个 episode 开始前随机采样。上一章的 ResetFcn 已经把负载质量随机到 0.5~2.5kg这里可以再做三件事随机化摩擦系数、随机化初始角度、随机化目标轨迹幅值。function in localResetFcn(in) blk rl_single_joint/friction; in setBlockParameter(in, blk, Value, num2str(0.05 0.3 * rand)); blk_init rl_single_joint/theta0; in setBlockParameter(in, blk_init, Value, num2str(-1.2 2.4 * rand)); blk_target rl_single_joint/theta_ref; in setBlockParameter(in, blk_target, Value, num2str(0.6 1.2 * rand)); end这里的参数要说明白随机范围不是越大越好。范围太大训练难度剧增可能 5000 个 episode 都学不到一个能用的策略范围太小测试时超出训练分布策略立刻失效。我通常的做法是“先扫后扩”先用小范围验证链路能收敛再把范围逐步扩大到想覆盖的工况。这也能从训练曲线看出来——如果平均奖励曲线的波动幅度突然变大说明随机范围已经超出了当前网络容量的学习上限。提示域随机化后的训练收敛时间通常是固定参数训练的 2 到 4 倍。如果你在论文里对比算法效果这个成本必须提前算进实验周期否则很容易在半途就开始怀疑算法实现有问题然后白调两周参数。4. 算法选型与超参数配置DDPG、TD3、SAC该怎么选状态动作奖励都定好以后下一步是选深度强化学习算法。很多初学者的习惯是最新什么火用什么但机器人连续控制场景里合适的意思是“能让训练在可接受时间内收敛且部署策略不会乱抖”。DDPG 是链路验证的首选TD3 是默认主力SAC 是在探索性任务上的加强选项。4.1 为什么连续动作控制不能用 DQNDQN 的核心动作选择是 argmax 一个 Q 表或 Q 网络输出它天然适合离散动作空间比如向左、向右、抓取、放下的逻辑决策。机器人关节力矩是连续变量如果把力矩离散成 200 个档位Q 网络的输出头会变成 200 维每个动作都要采样估计样本利用率极低更麻烦的是离散化会让控制动作出现台阶式跳变机械臂的加速度曲线会非常不平滑。这就引出了 actor-critic 架构的必要性actor 网络直接输连续动作向量critic 网络评估这个动作的 Q 值两者交替训练。MATLAB RL Toolbox 里的 DDPG、TD3、SAC 都是这类结构。DDPG 是最简单的一种适合作为第一版跑通链路但训练稳定性不如 TD3TD3 在 DDPG 上加了三个改动是机器人连续控制里的稳妥选择SAC 用最大熵框架让策略保持随机性探索能力强但训练更慢超参更敏感。4.2 TD3 的三个改进点与对应参数配置TD3 对 DDPG 的改进是有明确工程对应关系的。第一它用了两个 critic 网络Q 值取两者最小值压制 Q 值高估问题这在机器人场景里表现为训练后期策略不会突然震荡。第二策略网络采用延迟更新actor 更新频率低于 critic实践中用 TargetUpdateFrequency 控制。第三目标策略平滑在计算目标 Q 值时给动作叠加一个小噪声防止策略对尖锐的 Q 函数过度拟合这也是部署后策略输出平滑度较好的原因。agentOpts rlTD3AgentOptions; agentOpts.SampleTime 0.01; agentOpts.TargetUpdateFrequency 2; agentOpts.MiniBatchSize 256; agentOpts.ExplorationModel.StandardDeviation 0.1; agentOpts.TargetPolicySmoothModel.StandardDeviation 0.1; agentOpts.TargetPolicySmoothModel.Variance 0.005; agentOpts.ActorOptimizerOptions.LearnRate 1e-4; agentOpts.CriticOptimizerOptions.LearnRate 1e-3; agentOpts.CriticOptimizerOptions.GradientThreshold 1;这些参数我解释一下。TargetUpdateFrequency 设置为 2 表示 critic 每更新 2 次actor 才更新 1 次延迟更新有效避免了 actor 被还没稳定的 critic 带偏。ExplorationModel 的 StandardDeviation 是训练期间叠加在动作上的探索噪声标准差0.1N·m 的噪声对力矩控制来说已经不小噪声太大会让机械臂模型剧烈抖动。TargetPolicySmoothModel 的两个参数是目标策略平滑项Variance 控制噪声方差StandardDeviation 控制加到目标动作上的扰动上限。注意不同 MATLAB 版本里 rlTD3AgentOptions 的属性名略有差异。建议训练前先运行get(agentOpts)查看当前版本支持的字段如果属性名对不上以get输出的为准来改而不是硬套网上旧教程的写法。4.3 SAC 的熵权重与训练稳定性权衡SAC 相比 TD3 的最大区别是引入了熵正则项策略在训练时不仅最大化累积奖励还最大化动作分布的熵。通俗地说它不会很快锁定到一个确定性策略而是保持一定随机性继续探索。对自适应控制来说这种探索能力有助于找到更鲁棒的策略尤其当负载变化范围很大时SAC 学到的策略面更宽。但代价也很直接。SAC 需要训练一个额外的熵权重系数Soft Actor-Critic 里这个系数可以自动调节MATLAB 里对应 EntropyWeightOptions。如果熵权重初始值设得太大策略会长时间停留在随机探索状态训练曲线涨得很慢设得太小SAC 就退化成接近 TD3 的行为。机器人控制任务里我一般用 TD3 先找到一套可行的状态动作设计再用 SAC 做第二轮“探索增强”训练这样能最大程度减少 SAC 调参带来的时间损失。指标DDPGTD3SAC训练稳定中高中高样本效率中中高低探索能力低中高超参数量少中多适合场景链路验证默认主力大范围随机化/难探索任务4.4 超参配置的一组保守起点给一组可以直接用的起步参数前提是模型步长 0.01s、单关节模型、负载随机范围 0.5~2.5kg。MiniBatchSize 用 128 或 256太小的 batch 让梯度估计噪声变大ExperienceBufferLength 设成 1e6确保经验池能覆盖足够多“不同负载不同初始角度”的组合如果经验池太小域随机化的效果会被严重稀释。Actor 学习率 1e-4Critic 学习率 1e-3Critic 学习率比 Actor 高一个数量级是常规做法。MaxEpisodes 和 MaxStepsPerEpisode 的关系需要一起考虑。如果每个 episode 是 3 秒仿真、步长 0.01sMaxStepsPerEpisode 就是 300如果目标轨迹变长这个值要同步加大否则策略还没走完一个完整轨迹就被强制结束它永远学不会长时间跟踪。我习惯先跑 300 个 episode 观察 reward 曲线的波动范围再决定是加 episode 数还是改奖励系数而不是一口气跑到 5000 回合才发现奖励设计有问题。5. 避坑清单五次训练翻车之后整理出的排障顺序这段算是我在机器人强化学习控制项目里被耽误最久的五个问题。每个问题都是真真切切发生过的现象、根因、解决方式一条条对清楚能帮你省下至少一周的排查时间。5.1 仿真步长与 RL 采样时间不匹配曲线在涨控制器其实没学到东西现象训练曲线一路上涨看起来学得不错但把训练好的策略拿去做验证仿真发现输出轨迹完全跟不上目标甚至在目标点附近来回振荡。更迷惑的是把奖励曲线和动作曲线放在一起看动作输出的变化非常缓慢像是在“慢动作”控制。原因Simulink 求解器固定步长设了 0.0001s而 RL Agent 的 SampleTime 设成了 0.1s。策略每个控制周期之间相隔 1000 个仿真步它看到的状态是 0.1s 前的旧状态动作输出后系统早就跑远了。训练曲线上涨只是因为策略学会了“在旧状态上做平均补偿”并没有学到真正的动态响应。解决把 Simulink 求解器设为固定步长离散步长 0.01s同时把 rlTD3AgentOptions 里的 SampleTime 也设为 0.01两者严格一致。如果系统动态太快必须用更小步长就把 Simulink 步长设 0.001sRL SampleTime 设为 0.01s此时需要在 Agent 输入端加一个 Rate Transition 模块明确信号语义否则 Simulink 会报采样率不匹配的警告。5.2 奖励项量纲差太大误差项被力矩惩罚项淹没现象训练刚开始几轮奖励就掉到 -10 以下之后一直徘徊不上来。看训练统计里每一步的平均动作输出几乎为零策略“罢工”。原因奖励函数里误差项是 (theta - theta_ref)^2量级约为 0.01而力矩惩罚项 1.0 * tau^2 在力矩输出 3N·m 时就产生 9 的负奖励。误差项提供的学习信号完全被能量项淹没策略快速发现“最安全的行为是零输出”。解决把每一项都做量纲分析后重新配权。我的配法是先记录一个随机策略下的平均误差、平均力矩、平均力矩变化率然后让三项的权重分别乘以这些平均值后量级相近。比如随机策略下平均误差平方是 0.05平均力矩平方是 25那么能量项系数就设成 0.002 左右保证三项对奖励的贡献在同一水平线上。% 先跑 50 个 episode 收集量级信息 % 记录 avg_err_sq, avg_tau_sq, avg_dtau_sq % 然后设置权重使三者贡献接近 w_err 1.0; w_tau w_err * avg_err_sq / avg_tau_sq; w_dtau w_err * avg_err_sq / avg_dtau_sq;5.3 观测不归一化换一个初始位置策略立刻翻车现象训练时目标角度固定在 0.5rad 附近模型测试时改成 1.2rad策略输出的力矩明显偏小跟踪动作变形。把状态值打印出来发现角度 1.2 和训练时见过的 0.5 差距太大actor 网络对这个输入范围内的处理完全是外推。原因神经网络对输入数值范围很敏感。角度、角速度、负载质量这几个观测的物理单位不同数值范围差异又大如果不归一化网络在训练时只见过角速度 0~2、角度 -1~1 这个范围测试时一旦超出就失去插值能力。解决在 Simulink 模型里对观测信号做归一化。角度除以 pi角速度除以最大角速度误差除以允许最大误差负载质量除以它的量程上限。让所有观测落在 [-1, 1] 之间。同时 ResetFcn 里初始角度随机范围要覆盖测试可能出现的范围不能只在 0.5rad 附近随机。% 在 MATLAB Function 块里对 obs 做归一化 function obs_norm normalize_obs(theta, theta_dot, err, m_hat) obs_norm zeros(6, 1); obs_norm(1) theta / pi; obs_norm(2) theta_dot / 5.0; obs_norm(3) err / pi; obs_norm(4) err_dot / 5.0; obs_norm(5) theta_ref / pi; obs_norm(6) m_hat / 5.0; end5.4 观测向量维度错位Simulink 里“看不见”的 [1x6] 和 [6x1]现象训练点击开始后立刻报错错误信息大致是“Error in port widths or dimensions. Output port 1 of ‘model/MATLAB Function’ is a [1 6] signal.”但看 Simulink 模型里端口标注明明显示连接是正确的。原因MATLAB Function 块里如果写obs [theta; theta_dot; ...]生成的是 6x1 列向量但如果某个信号本身是从 Bus 或 Mux 里解出来的行向量最终拼接结果可能变成 1x6。RL Agent 块要求观测输入是列向量维度严格匹配Simulink 的端口宽度检查不像普通信号线那样给出直观提示经常会漏过去。解决在所有产出观测向量的 MATLAB Function 块末尾加一行obs obs(:);强制转为列向量同时在 RL Agent 块的输入端口右键“Display Signal Dimensions”把信号维度显示出来核对。动作输出端也是一样如果动作向量经过 Mux 或 Selector 再进执行器用tau tau(:)保证形状正确。5.5 训练噪声没有递减验证时策略看起来“没学会”现象训练曲线已经收敛AverageReward 保持稳定但同样一个 Agent 拿到独立验证环境里跑输出动作不停左右跳变关节力矩曲线像是白噪声。录像下来看机械臂在原地颤抖根本没法用。原因训练时叠加的探索噪声在验证阶段仍然存在。DDPG/TD3 在 Simulink 部署时如果直接复用训练 Agent 对象它可能继续从 Explorer 中采样随机动作而不是使用确定性策略。MATLAB 的 getPolicy 函数可以抽出确定性策略这行代码很多人会漏掉。解决从训练好的 agent 里抽取确定性策略再部署验证。policy getPolicy(agent); env_deploy rlSimulinkEnv(rl_single_joint_deploy, rl_single_joint_deploy/RL Agent, obsInfo, actInfo); % 在 Simulink 里把 RL Agent 块的 Agent 属性替换为 policy注意如果在真实机器人或者高保真模型上验证部署策略前还要对动作输出做限幅并且准备一个急停逻辑。训练时策略可以探索边界动作验证时你不希望它真的把关节打到机械限位。6. 训练完怎么验证自适应能力外部模式测试、负载扫描与导出习惯训练收敛了不等于项目结束。自适应控制算法最关键的验收环节是测试“当系统参数在训练范围内变化时策略是否仍然能保持性能”。我一般用三个递进步骤负载扫描、Simulink 外部模式实时仿真、最后才是生成代码部署到物理机器人。6.1 用负载和摩擦系数扫描测试自适应边界我习惯在训练结束后写一个负载扫描脚本把质量从训练范围的最小值扫到最大值每个质量点跑一次 Simulink 仿真记录稳态跟踪误差。loads [0.5 1.0 1.5 2.0 2.5]; for i 1:numel(loads) set_param(rl_single_joint/mass, Value, num2str(loads(i))); simOut sim(rl_single_joint, StopTime, 10); y simOut.yout; % 记录跟踪误差信号 err_signal y.getElement(track_err).Values.Data; steady_err(i) max(abs(err_signal(end-100:end))); end plot(loads, steady_err, o-);这组代码的作用是量化策略的自适应边界。如果稳态误差在负载变化时基本保持在一个量级说明策略确实学到了自适应补偿如果误差随负载增大明显上升说明训练时的负载随机范围还不够覆盖或者观测里的负载信息没有被网络充分利用。这个表格可以作为验收标准测试点负载摩擦系数验收标准边界低值0.5kg0.05稳态误差 0.02rad典型中值1.5kg0.15稳态误差 0.02rad边界高值2.5kg0.30稳态误差 0.03rad训练外推3.0kg0.40策略不崩溃允许误差放宽训练外推那一行特别说明一下如果测试负载超出训练时的随机范围策略性能下降是正常的关键是看它是否“有界”。只要不出现发散震荡说明策略对未见过参数仍有一定泛化能力这已经是自适应控制可以接受的边界。6.2 用 Simulink 外部模式跑实时仿真普通仿真验证的是数学模型闭环外部模式则能让模型跑在实时内核上执行步长更稳定也更接近部署环境。Simulink 工具栏把仿真模式从 Normal 切到 External选择 Desktop Real-Time 目标设置固定步长和硬件执行参数然后重新下载模型运行。外部模式在我工作里的实际用途不是代替真机而是验证“策略计算时间是否满足控制周期”。强化学习策略是一个神经网络前向推理时间会和网络层数、输入维度相关。如果计算时间超过 10ms 的控制周期策略在普通仿真里照样能跑但真实控制器上就会丢步。外部模式下打开信号监视看关节力矩的刷新率是否和控制周期一致这一步建议至少跑 10 分钟连续仿真中间手动改变模型里的 Stiffness 参数观察响应确认稳定。6.3 生成代码与部署线路选择如果你要部署到真实机器人常见的路线是把训练好的策略导出成 Simulink 模型或 MATLAB Function再通过 Simulink Coder 生成 C/C 代码。生成的代码只包含神经网络的前向推理和必要的信号处理不依赖完整的 MATLAB 运行环境可以集成到 ROS2 机器人开发框架里作为一个控制器节点订阅关节状态话题推理输出力矩话题。如果你的真实机器人不能提供足够的安全保护强烈建议先用离线强化学习路线再过渡。离线强化学习里 IQL 这类方法可以只利用仿真生成的固定数据集训练策略避免在线强化学习在真机上探索时可能造成的危险动作。这个做法虽然不是必须的但对我这种要对手腕和关节负责的工程师来说是值得多花两周时间的安全投入。我的一个习惯是训练结束当天一定会做三件事保存训练曲线图、保存带完整参数注释的 agent 创建脚本、保存 ResetFcn 里所有随机范围的记录。以前我嫌麻烦省略过半个月后回看实验记录想不起来某个奖励系数是怎么配出来的那感觉比训练不收敛还糟糕。还有一个习惯是任何 Agent 部署到外部模式之前先在仿真里把动作信号的频率谱画出来如果高频分量过多就先加一层平滑滤波再考虑生成代码。这套流程走下来训练出来的策略至少能保证在仿真里是可信的希望对你在自己的机械臂项目上少踩几次坑。本文还有配套的精品资源点击获取
返回列表