PID控制、BP-PID控制、PSO-BP-PID控制的Simulink仿真。 代码清晰、易懂,代码质量极高,便于新手学习和理解。
搞过自动控制的同学对PID肯定不陌生,但今天咱们玩点有意思的——用Simulink把传统PID、带神经网络的BP-PID、还有用粒子群优化的PSO-BP-PID都跑一遍。先来个经典PID镇楼,直接上模型:
![PID Simulink模型示意图]
% PID参数设置脚本 Kp = 1.2; Ki = 0.5; Kd = 0.1;这个三兄弟(P、I、D)配合得好的时候确实稳如老狗,但遇到复杂系统就有点力不从心。这时候就该BP神经网络出场了——这货能自己在线调参。在Simulink里拖个MATLAB Function模块,塞进去这个:
function [Kp,Ki,Kd] = BP_PID(error, d_error) % 隐含层激活函数 hidden = @(x) 1./(1+exp(-x)); % 网络权值初始化(实际用BP算法在线更新) persistent w1 w2; if isempty(w1) w1 = rand(3,5)-0.5; w2 = rand(5,3)-0.5; end % 前向传播 input = [error; d_error; 1]; % 带偏置 h = hidden(w1'*input); output = w2'*[h;1]; % 输出层线性激活 Kp = output(1); Ki = output(2); Kd = output(3); end这段代码的精髓在于把PID参数变成了神经网络的输出,误差和误差变化率作为输入。注意这里用了persistent变量保存权值,相当于实现了在线学习的功能。不过初始权值随便设的,这时候就需要PSO来优化了。
说到粒子群优化(PSO),咱们得先给BP网络找个好初始值。在MATLAB里写个优化脚本:
% PSO参数 particle_num = 20; max_iter = 50; c1 = 1.5; c2 = 1.5; % 初始化粒子群 particles = struct('position', cell(1,particle_num), 'velocity', [], 'pbest', []); for i=1:particle_num % 权值矩阵展开成向量(3x5 +5x3 = 30个参数) particles(i).position = rand(30,1)*2-1; particles(i).velocity = zeros(30,1); particles(i).pbest = inf; end % 优化循环 for iter=1:max_iter for i=1:particle_num % 仿真获取性能指标(ITAE) cost = sim('PSO_BP_PID_model'); % 更新个体最优 if cost < particles(i).pbest particles(i).pbest = cost; particles(i).best_pos = particles(i).position; end % 速度更新(省略全局最优计算部分) particles(i).velocity = c1*rand*(particles(i).best_pos - ... particles(i).position) + c2*rand*(global_best - particles(i).position); particles(i).position = particles(i).position + particles(i).velocity; end end这个PSO脚本和Simulink模型联动,通过不断试错找到最优的初始权值组合。注意看第14行的sim函数调用,这里会把当前粒子的权值传入模型进行仿真,返回控制性能指标(比如ITAE)。
最后把这三个版本放一起对比,响应曲线会说话:普通PID超调明显,BP-PID收敛快但有抖动,PSO优化过的版本既稳又准。想要完整模型文件的同学可以私我,记得仿真前把求解器改成ode45,步长别超过0.001秒,不然神经网络更新跟不上节奏。
新手常掉坑的地方:BP学习率设太大容易发散,PSO的粒子数别超过50个否则跑得太慢。下次咱们可以试试用遗传算法来整活,或者上强化学习搞个更智能的控制器。