智能控制实验报告
姓名:
学院:
专业:自动化 班级:
学号:
指导教师:
成绩:
2019 年 12 月 25 日
实验一
模糊控制在角度随动系统中的应用 一、实验目的与意义 学习 Matlab 中建立模糊控制器的方法;了解模糊控制在角度随动系统中的
应用。
二、实验内容 在 Matlab 中建立模糊控制器,将生成的模糊规则表插入程序代码中,交叉
编译代码,下载到目标版中进行测试。
1 、Matlab 文本模式建立模糊控制器(必做)
2 、利用 Matlab 模糊逻辑工具箱建立模糊控制器(选做)
3 、模糊控制器 Simulink 仿真(必做)
4 、嵌入式程序交叉编译(选做)
三、实验结果 1 、matlab 文本模式建立模糊控制器 %Fuzzy Controller Design clear all;
close all;
%新建 FIS a=newfis("myfuzzy");
%输入 e,范围[-48,48],7 个模糊语言,NB,NM,NS,Z,PS,PM,PB a=addvar(a,"input","e",[-48 48]);
%Parameter e a=addmf(a,"input",1,"NB","trimf",[-48 -36 -24]); a=addmf(a,"input",1,"NM","trimf",[-36 -24 -12]); a=addmf(a,"input",1,"NS","trimf",[-24 -12 0]); a=addmf(a,"input",1,"Z","trimf",[-12 0 12]); a=addmf(a,"input",1,"PS","trimf",[0 12 24]); a=addmf(a,"input",1,"PM","trimf",[12 24 36]);
a=addmf(a,"input",1,"PB","trimf",[24 36 48]);
%输入 ec,范围[-64,64],7 个模糊语言,NB,NM,NS,Z,PS,PM,PB a=addvar(a,"input","ec",[-64 64]);
%Parameter ec a=addmf(a,"input",2,"NB","trimf",[-64 -48 -32]); a=addmf(a,"input",2,"NM","trimf",[-48 -32 -16]); a=addmf(a,"input",2,"NS","trimf",[-32 -16 0]); a=addmf(a,"input",2,"Z","trimf",[-16 0 16]); a=addmf(a,"input",2,"PS","trimf",[0 16 32]); a=addmf(a,"input",2,"PM","trimf",[16 32 48]); a=addmf(a,"input",2,"PB","trimf",[32 48 64]);
%输出 u,范围[-90,90],7 个模糊语言,NB,NM,NS,Z,PS,PM,PB a=addvar(a,"output","u",[-90 90]);
%Parameter u a=addmf(a,"output",1,"NB","trimf",[-90 -67.5 -45]); a=addmf(a,"output",1,"NM","trimf",[-67.5 -45 -22.5]); a=addmf(a,"output",1,"NS","trimf",[-45 -22.5 0]); a=addmf(a,"output",1,"Z","trimf",[-22.5 0 22.5]); a=addmf(a,"output",1,"PS","trimf",[0 22.5 45]); a=addmf(a,"output",1,"PM","trimf",[22.5 45 67.5]); a=addmf(a,"output",1,"PB","trimf",[45 67.5 90]);
%模糊规则表,7*7 = 49 行,5 列 rulelist=[1 1 1 1 1;
1 2 1 1 1;
1 3 1 1 1;
1 4 2 1 1;
1 5 2 1 1;
1 6 3 1 1;
1 7 4 1 1;
2 1 1 1 1;
2 2 1 1 1;
2 3 1 1 1;
2 4 2 1 1;
2 5 2 1 1;
2 6 3 1 1;
2 7 4 1 1;
3 1 1 1 1;
3 2 2 1 1;
3 3 2 1 1;
3 4 3 1 1;
3 5 4 1 1;
3 6 5 1 1;
3 7 6 1 1;
4 1 1 1 1;
4 2 3 1 1;
4 3 3 1 1;
4 4 4 1 1;
4 5 5 1 1;
4 6 6 1 1;
4 7 7 1 1;
5 1 2 1 1;
5 2 3 1 1;
5 3 4 1 1;
5 4 5 1 1;
5 5 6 1 1;
5 6 7 1 1;
5 7 7 1 1;
6 1 3 1 1;
6 2 4 1 1;
6 3 5 1 1;
6 4 6 1 1;
6 5 7 1 1;
6 6 7 1 1;
6 7 7 1 1;
7 1 4 1 1;
7 2 5 1 1;
7 3 6 1 1;
7 4 6 1 1;
7 5 7 1 1;
7 6 7 1 1;
7 7 7 1 1;
];
a=addrule(a,rulelist); %showrule(a)
% Show fuzzy rule base
a1=setfis(a,"DefuzzMethod","centroid");
% Defuzzy writefis(a1,"fuzzf");
% save to fuzzy file "fuzz.fis" which can be
% simulated with fuzzy tool a2=readfis("fuzzf"); disp("-------------------------------------------------------"); disp("
fuzzy controller table:e=[-48,+48],ec=[-64,+64]
"); disp("-------------------------------------------------------");
Ulist=zeros(7,7);
for i=1:7
for j=1:7
e(i)=-4+i;
ec(j)=-4+j;
Ulist(i,j)=evalfis([e(i),ec(j)],a2);
end end
Ulist=ceil(Ulist)
figure(1); plotfis(a2); figure(2); plotmf(a,"input",1); figure(3); plotmf(a,"input",2); figure(4); plotmf(a,"output",1);
运行结果:
>> ksk -------------------------------------------------------
fuzzy controller table:e=[-48,+48],ec=[-64,+64]
-------------------------------------------------------
Ulist =
-13
-11
-8
-6
-4
-2
-1
-11
-9
-7
-4
-2
-1
1
-8
-7
-5
-2
0
2
3
-5
-3
-1
0
2
4
6
-2
-1
1
3
6
8
9
0
2
3
5
8
10
12
2
3
5
7
9
12
14
2、 、 利用 Matlab 模糊逻辑工具箱建立模糊控制器步骤
3、 、 模糊控制器 Simulink 仿真
4、 、 嵌入式程序交叉编译 y Fuzzy 源代码:
#define PMAX
100 #define PMIN
-100 #define DMAX
100 #define DMIN
-100 #define FMAX
100 /*语言值的满幅值 */ /*输入量 P 语言值特征点*/ int PFF[4] = { 0, 12, 24, 48 };
/*输入量 D 语言值特征点*/ int DFF[4] = { 0, 16, 32, 64 };
/*输出量 U 语言值特征点*/ int UFF[7] = { 0, 15, 30, 45, 60, 75, 90 };
/*采用了调整因子的规则表,大误差时偏重误差,小误差时偏重误差变化*/ /*a0=0.3,a1=0.55,a2=0.74,a3=0.89
*/ /* int rule[7][7] = {
//误差变化率 -3,-2,-1, 0, 1, 2, 3
// 误差
{-13,-11,-8,-6,-4,-2,-1}, //
-3 {-11,-9,-7,-4,-2,-1,1}, //
-2 {-8,-7,-5,-2,0,2,3}, //
-1 {-5,-3,-1,0,2,4,6}, //
0 {-2,-1,1,3,6,8,9}, //
1 {0,2,3,5,8,10,12}, //
2
{2,3,5,7,9,2,14} };*/
int rule[7][7] = {
//误差变化率 -3,-2,-1, 0, 1, 2, 3
// 误差
{ -13,
-11,
-8,
-6,
-4,
-2,
-1},
{ -11,
-9,
-7,
-4,
-2,
-1,
1},
{ -8,
-7,
-5,
-2,
0,
2,
3 },
{ -5,
-3,
-1,
0,
2,
4,
6 },
{ -2,
-1,
1,
3,
6,
8,
9 },
{
0,
2,
3,
5,
8,
10,
12 },
{
2,
3,
5,
7,
9,
12,
14 }, }; /**********************************************************/ int Fuzzy(int P, int D) { /*模糊运算引擎 */ int U; /*偏差,偏差微分以及输出值的精确量 */ unsigned int PF[2], DF[2], UF[4]; /*偏差,偏差微分以及输出值的隶属度 */ int Pn, Dn, Un[4]; long temp1, temp2; /*隶属度的确定 */ /*根据 PD 的指定语言值获得有效隶属度 */ if (P > -PFF[3] && P < PFF[3]) { if (P <= -PFF[2]) { Pn = -2; PF[0] = FMAX * ((float) (-PFF[2] - P) / (PFF[3] - PFF[2])); } else if (P <= -PFF[1]) { Pn = -1; PF[0] = FMAX * ((float) (-PFF[1] - P) / (PFF[2] - PFF[1])); } else if (P <= PFF[0]) { Pn = 0; PF[0] = FMAX * ((float) (-PFF[0] - P) / (PFF[1] - PFF[0])); } else if (P <= PFF[1]) { Pn = 1; PF[0] = FMAX * ((float) (PFF[1] - P) / (PFF[1] - PFF[0])); } else if (P <= PFF[2]) { Pn = 2; PF[0] = FMAX * ((float) (PFF[2] - P) / (PFF[2] - PFF[1])); } else if (P <= PFF[3]) { Pn = 3; PF[0] = FMAX * ((float) (PFF[3] - P) / (PFF[3] - PFF[2])); } } else if (P <= -PFF[3]) {
Pn = -2; PF[0] = FMAX; } else if (P >= PFF[3]) { Pn = 3; PF[0] = 0; } PF[1] = FMAX - PF[0]; if (D > -DFF[3] && D < DFF[3]) { if (D <= -DFF[2]) { Dn = -2; DF[0] = FMAX * ((float) (-DFF[2] - D) / (DFF[3] - DFF[2])); } else if (D <= -DFF[1]) { Dn = -1; DF[0] = FMAX * ((float) (-DFF[1] - D) / (DFF[2] - DFF[1])); } else if (D <= DFF[0]) { Dn = 0; DF[0] = FMAX * ((float) (-DFF[0] - D) / (DFF[1] - DFF[0])); } else if (D <= DFF[1]) { Dn = 1; DF[0] = FMAX * ((float) (DFF[1] - D) / (DFF[1] - DFF[0])); } else if (D <= DFF[2]) { Dn = 2; DF[0] = FMAX * ((float) (DFF[2] - D) / (DFF[2] - DFF[1])); } else if (D <= DFF[3]) { Dn = 3; DF[0] = FMAX * ((float) (DFF[3] - D) / (DFF[3] - DFF[2])); } } else if (D <= -DFF[3]) { Dn = -2; DF[0] = FMAX; } else if (D >= DFF[3]) { Dn = 3; DF[0] = 0; } DF[1] = FMAX - DF[0]; /*使用误差范围优化后的规则表 rule[7][7] */ /*输出值使用 13 个隶属函数,中心值由 UFF[7]指定 */ /*一般都是四个规则有效 */ Un[0] = rule[Pn - 1 + 3][Dn - 1 + 3]; Un[1] = rule[Pn + 3][Dn - 1 + 3]; Un[2] = rule[Pn - 1 + 3][Dn + 3]; Un[3] = rule[Pn + 3][Dn + 3]; if (PF[0] <= DF[0]) UF[0] = PF[0];
else UF[0] = DF[0]; if (PF[1] <= DF[0]) UF[1] = PF[1]; else UF[1] = DF[0]; if (PF[0] <= DF[1]) UF[2] = PF[0]; else UF[2] = DF[1]; if (PF[1] <= DF[1]) UF[3] = PF[1]; else UF[3] = DF[1]; /*同隶属函数输出语言值求大 */
if (Un[0] == Un[1]) { if (UF[0] > UF[1]) UF[1] = 0; else UF[0] = 0; } if (Un[0] == Un[2]) { if (UF[0] > UF[2]) UF[2] = 0; else UF[0] = 0; } if (Un[0] == Un[3]) { if (UF[0] > UF[3]) UF[3] = 0; else UF[0] = 0; } if (Un[1] == Un[2]) { if (UF[1] > UF[2]) UF[2] = 0; else UF[1] = 0; } if (Un[1] == Un[3]) { if (UF[1] > UF[3]) UF[3] = 0; else
UF[1] = 0; } if (Un[2] == Un[3]) { if (UF[2] > UF[3]) UF[3] = 0; else UF[2] = 0; } /*重心法反模糊 */ /*Un[]原值为输出隶属函数标号,转换为隶属函数值 */ if (Un[0] >= 0) Un[0] = UFF[Un[0]]; else Un[0] = -UFF[-Un[0]]; if (Un[1] >= 0) Un[1] = UFF[Un[1]]; else Un[1] = -UFF[-Un[1]]; if (Un[2] >= 0) Un[2] = UFF[Un[2]]; else Un[2] = -UFF[-Un[2]]; if (Un[3] >= 0) Un[3] = UFF[Un[3]]; else Un[3] = -UFF[-Un[3]]; temp1 = UF[0] * Un[0] + UF[1] * Un[1] + UF[2] * Un[2] + UF[3] * Un[3]; temp2 = UF[0] + UF[1] + UF[2] + UF[3]; U = temp1 / temp2; return U; }
实验二
神经网络在角度随动系统中的应用 一、实验目的与意义 学习 Matlab 中建立 单神经元自适应神经网络控制器的方法;了解神经网络在角度随动系统中的应用。
二、实验内容 1. 根据直流伺服电机的传递函数求出差分方程 2. 在 在 Matlab 中建立单神经元自适应控制器 3. K 得到较好的控制效果(方波、正弦波)
*4. 编写单神经元自适应控制器的 C 程序, 编译并在角度随动系统中验证
三、实验原理 1. 直流伺服电机传递函数
2. 传递函数求差分方程步骤:
以传递函数 为例:
A. 使用 tf 函数建立传递函数
sys=tf(1000,[1,50,2000])
B. 设置采样时间
ts = 0.001
C. 使用 c2d 函数进行 Z 变换,其中
dsys=c2d(sys,ts,"z")
D. 交叉相乘得到
E. 对 U(Z) 和 Y(Z) 进行
z 逆变换得到差分方程
3 、单神经元自适应控制算法 —— 方波 单神经元自适应控制的结构如下图所示。
单神经元自适应控制器是通过对加权系数的调整来实现自适应、自组织功能,控制算法为
如果权系数的调整按有监督的 Hebb 学习规则实现,在学习算法中加入监督项 z(k) ,则神经网络权值学习算法为
为学习速率, K 为神经元的比例系数, K 0, (0,1) 。
K 值得选择非常重要。K 越大,则快速性越好,但超调量大,甚至可能使系统不稳定。当被控对象时延增大时,K 值必须减小,以保证系统稳定。K 值选择过小,会使系统快速性变差。
被控对象为 y(k) (为 Matlab 中建立的直流伺服电机的差分方程),输入指令为一正弦信号:
r(k) 2sin(4 k ts) ,采样时间 ts0.001s ,采用有监督的Hebb 学习规则实现权值的学习,初始权值取 W [w 1 w 2 w 3 ] [0.10.1 0.1] , 0.1 ,K 0.01 。以此为条件在 Matlab 中建立单神经元自适应控制器。
4. 单神经元自适应控制算法—— 正弦波 被控对象为 y(k) (为在 Matlab 中建立的直流伺服电机的差分方程),输入指令为一方波信号:
r(k) 20sin(4 k ts) ,采样时间 ts0.001s ,采用有监督的 Hebb 学习规则实现权值的学习,初始权值取 W [w 1 w 2 w 3 ] [0.10.1 0.1] , 0.1 , K 0.01 。以此为条件在 Matlab 中建立单神经元自适应控制器。
三、实验结果 1. 单神经元自适应控制算法 —— 方波
源代码:
%单神经元自适应控制器 clear all; close all;
x=[0,0,0]"; %x1,x2,x3 的初始值 xite=0.1;
%学习速率 K=0.01;
%神经元比例系数 ts=0.001;
%采样时间
w1_1=0.10;%学习权值的初始值,w1_1 代表 w1(k-1)的值 w2_1=0.10; w3_1=0.10;
e_1=0;%误差的初始值 e_2=0;
y_1=0;y_2=0;%被控对象差分方程的输出值 u_1=0;u_2=0;% for k=1:1:1000 %循环迭代
time(k)=k*ts;
% r(k)=2*sin(4*pi*k*ts);%输入指令为一正弦信号
r(k)=0.5*sign(sin(4*pi*k*ts));%输入指令为一方波信号
y(k)=0.8464*y_1 + 32.01*u_1+0.1064*u_2;
%y(k)=0.8464*y_1 +0.01*u_1+0.1064*u_2; %直流伺服电机的传递函数得到的差分方程
e(k)=r(k)-y(k);%误差
%有监督的 Hebb 学习规则实现权值的调整
e(k)=r(k)-y(k);
z(k)=e(k);
x1(k)=e(k)-e_1;
x2(k)=e(k);
x3(k)=e(k)-2*e_1+e_2;
w1(k)=w1_1+xite*0.07*z(k)*u_1*x1(k);
w2(k)=w2_1+xite*0.005*z(k)*u_1*x2(k);
w3(k)=w3_1+xite*0.02*z(k)*u_1*x3(k);
w1p(k) = w1(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
w2p(k) = w2(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
w3p(k) = w3(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
u(k)=u_1+K*(w1p(k)*x1(k)+w2p(k)*x2(k)+w3p(k)*x3(k));
y_2=y_1;
y_1=y(k);
e_2=e_1;
e_1=e(k);
w1_1=w1(k);
w2_1=w2(k);
w3_1=w3(k);
u_2=u_1;
u_1=u(k);
end figure(1); plot(time,r,"b",time,y,"r"); xlabel("time(s)");ylabel("Position tracking"); figure(2); plot(time,e,"r"); xlabel("time(s)");ylabel("error"); figure(3); plot(time,w1,"r"); xlabel("time(s)");ylabel("w1"); figure(4); plot(time,w2,"r"); xlabel("time(s)");ylabel("w2"); figure(5); plot(time,w3,"r"); xlabel("time(s)");ylabel("w3");
运行结果:
2. 单神经元自适应控制算法—— 正弦波 源代码:
%单神经元自适应控制器 clear all; close all;
x=[0,0,0]"; %x1,x2,x3 的初始值 xite=0.1;
%学习速率 K=0.01;
%神经元比例系数 ts=0.001;
%采样时间
w1_1=0.10;%学习权值的初始值,w1_1 代表 w1(k-1)的值 w2_1=0.10; w3_1=0.10;
e_1=0;%误差的初始值 e_2=0;
y_1=0;y_2=0;%被控对象差分方程的输出值 u_1=0;u_2=0;% for k=1:1:1000 %循环迭代
time(k)=k*ts;
% r(k)=2*sin(4*pi*k*ts);%输入指令为一正弦信号
r(k) = 20*sin(4*pi*k*ts); ;%输入指令为一方波信号
y(k)=0.8464*y_1 + 32.01*u_1+0.1064*u_2;
%y(k)=0.8464*y_1 +0.01*u_1+0.1064*u_2; ;%直流伺服电机的传递函数得到的差分方程
e(k)=r(k)-y(k);%误差
%有监督的 Hebb 学习规则实现权值的调整
e(k)=r(k)-y(k);
z(k)=e(k);
x1(k)=e(k)-e_1;
x2(k)=e(k);
x3(k)=e(k)-2*e_1+e_2;
w1(k)=w1_1+xite*0.07*z(k)*u_1*x1(k);
w2(k)=w2_1+xite*0.005*z(k)*u_1*x2(k);
w3(k)=w3_1+xite*0.02*z(k)*u_1*x3(k);
w1p(k) = w1(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
w2p(k) = w2(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
w3p(k) = w3(k)/(abs(w1(k)) + abs(w2(k)) + abs(w3(k)));
u(k)=u_1+K*(w1p(k)*x1(k)+w2p(k)*x2(k)+w3p(k)*x3(k));
y_2=y_1;
y_1=y(k);
e_2=e_1;
e_1=e(k);
w1_1=w1(k);
w2_1=w2(k);
w3_1=w3(k);
u_2=u_1;
u_1=u(k);
end figure(1); plot(time,r,"b",time,y,"r"); xlabel("time(s)");ylabel("Position tracking"); figure(2); plot(time,e,"r"); xlabel("time(s)");ylabel("error"); figure(3); plot(time,w1,"r"); xlabel("time(s)");ylabel("w1"); figure(4); plot(time,w2,"r"); xlabel("time(s)");ylabel("w2"); figure(5); plot(time,w3,"r"); xlabel("time(s)");ylabel("w3");
运行结果:
4. 交叉编译步骤 Neural 源代码:
#include <stdio.h> #include <math.h> #include <stdlib.h> #include "neural.h"
/****************************************/ float neural_input_data[3] = {0, 0, 0}; //神经网络输入值初始值为零 float xite = 0.010;
//学习率 float w1_1 = 0.10;
//k-1 时刻的初始权值 float w2_1 = 0.10;
//k-1 时刻的初始权值 float w3_1 = 0.10;
//k-1 时刻的初始权值 float e_1 = 0;
//e(k-1) float e_2 = 0;
//e(k-2) float y_1 = 0, y_2 = 0; //y(k-1)和 y(k-2)初始值为零 float u_1 = 0, u_2 = 0; //u(k-1)和 u(k-2)初始值为零
/*****************************************/ //单神经元自适应控制程序 //输入:
control_sys_y -- 被控对象的角度 // control_sys_r -- 实际电机的角度 //输出:
output --
电机角度
float neural_adaptive_control(float control_sys_y, float control_sys_r) {
float control_sys_e = 0;
//k 时刻的系统误差
float control_sys_u = 0;
//k 时刻的系统控制量 float w1=0;
//k 时刻的神经元的第一个输入量的权值 float w2=0;
//k 时刻的神经元的第二个输入量的权值 float w3=0;
//k 时刻的神经元的第三个输入量的权值 float K =0.5;
//单神经元自适应控制器的 K 增益 float z;
control_sys_e = control_sys_r - control_sys_y;//k 时刻的误差
printf("r is:%5.2f
y is %5.2f\n", control_sys_r, control_sys_y);
printf("e is: %7.2f\n", control_sys_e);
z = control_sys_e; neural_input_data[1] = control_sys_e;
//误差的位置量
neural_input_data[0] = control_sys_e - e_1;
//误差的速度量 neural_input_data[2] = control_sys_e - 2 * e_1 + e_2;
//误差的加速度量
printf("w1_1:
%7.2f, xite: %7.2f, z: %7.2f, u_1: %7.2f, data0: %7.2f\n", w1_1, xite, z,u_1, neural_input_data[0]);
w1 = w1_1 + xite*z*0.07*u_1*neural_input_data[0];
w2 = w2_1 + xite*z*0.005*u_1*neural_input_data[1];
w3 = w3_1 + xite*z*0.02*u_1*neural_input_data[2];
if (w1 < WMIN || w1 > WMAX) { w1 = 0; } if (w2 < WMIN || w2 > WMAX) { w2 = 0; } if (w3 < WMIN || w3 > WMAX) { w3 = 0; }
printf("w1: %7.2f, w2: %7.2f, w3: %7.2f\n", w1, w2, w3);
float w1p = w1/(fabs(w1) + fabs(w2) + fabs(w3));
float w2p = w2/(fabs(w1) + fabs(w2) + fabs(w3));
float w3p = w3/(fabs(w1) + fabs(w2) + fabs(w3));
control_sys_u = u_1 + K*(w1p*neural_input_data[0] + w2p*neural_input_data[1] + w3p*neural_input_data[2]);
//Control law
printf("u is %7.2f\n\n", control_sys_u);
if (control_sys_u > 10000 || control_sys_u < -10000) { control_sys_u
= 0; } float output;
//output = 1.969*y_1 - 0.9731*y_2 + 0.01679*u_1 + 0.01663*u_2;
//直流伺服电机的传递函数得到的差分方程 output = 1.014*y_1 - 0.01721*y_2+0.2322*u_1+0.8889*u_2;
printf("y1:%7.2f
y2:%7.2f
u1:%7.2f
u2:%7.2f\n", y_1, y_2, u_1, u_2); printf("output is %7.2f\n\n", output);
//保存参数
w1_1 = w1; w2_1 = w2; w3_1= w3;
u_2 = u_1; u_1 = control_sys_u;
e_2 = e_1; e_1 = control_sys_e;
y_2 = y_1; y_1 = control_sys_y;
return(output); }
实验三
遗传算法在角度随动系统中的应用 一、实验目的与意义 学习基于二进制编码遗传算法的 PID 整定方法;了解遗传算法在角度随动系统中的应用。
二、实验内容 1. 了解数字 PID 控制原理; 2. 了解基于二进制编码遗传算法的 PID 整定的方法、步骤; 3. 在 在 Matlab 中建立基于二进制编码遗传算法的 PID 整定仿真程序; *4. 自己设计一种适应度函数,并进行仿真实验。
*5. 在角度随动系统中验证得到的 PID 参数。
三、实验原理 1. 数字 PID 控制 计算机控制是一种采样控制,它只能根据采样时刻的偏差值计算控制量。因
此,连续 PID 控制算法不能直接使用,需要采用离散化方法。在计算机 PID 控制中,使用的是数字 PID 控制器。
按模拟 PID 控制算法,以一系列的采样时刻点 kT 代表连续时间 t,以矩形法数值计算近似代替积分,以一阶后向差分近似代替微分,即
可得离散 PID
p
位置式 PID 控制系统如下图所示。
2. 基于遗传算法的 PID 整定原理 A.参数的确定及表示
首先确定参数范围,该范围一般由用户给定,对其进行编码。选取二进制字
串来表示每一个参数,并建立于参数间的关系。再把二进制串连接起来就组成一
个长的二进制字串,该字串为遗传算法可以操作的对象。
B.选取初始种群
因为需要编程来实现各过程,所以采用计算机随机产生初始种群。针对二进
制编码而言,先产生 0~1 之间均匀分布的随机数,然后规定产生的随机数 0~0.5
之间带来表 0,0.5~1 之间代表 1。此外,考虑到计算的复杂程度来规定种群的大小。
C.适配函数的确定
一般的寻优方法在约束条件下可以求得满足条件的一组参数,在设计中是从
该组参数中寻找一个最好的。衡量一个控制系统的指标有三个方面,即稳定性、
准确性和快速性。而上升时间反映了系统的快速性,上升时间越短,控制进行得
就越快,系统品质也就越好。
如果单纯追求系统的动态特性,得到的参数很可能使控制信号过大,在实际
应用中会因系统中固有的饱和特性而导致系统不稳定,为了防止控制能量过大,
在实际应用中加入控制量。因此为了使控制效果更好,我们给出了控制量、误差
和上升时间作为约束条件。因为适应函数同目标函数相关,所以目标函数确定后,
直接将其作为适配函数进行参数寻优。最优的控制参数也就是在满足约束条件下
使 f(x)最大时,x 所对应的控制器参数。
D.遗传算法的操作
首先利用适应度比例法进行复制。即通过适配函数求得适配值,进而求每个
串对应的复制概率。复制概率与每代字串的个数的乘积为该串在下一代中应复制
的个数。复制概率大的在下一代中将有较多的子孙,相反则会被淘汰。
其次进行单点交叉,交叉概率为 P C 。从复制后的成员里以 P C 的概率选取字串组成
匹配池,而后对匹配池的成员随机匹配,交叉的位置也是随机确定的。
最后以概率 P m 进行变异。假如每代有 15 个字串,每个字串 12 位,则共有 15*12=180 个串位,期望的变异串位数为 180*0.01=2(位),即每代中有两个串位要由 1 变为 0 或由 0 变为 1。
初始种群通过复制、交叉及变异得到了新一代种群,该代种群经解码后代入
适配函数,观察是否满足结束条件,若不满足,则重复以上操作直到满足为止。
结束条件由具体问题所定,只要各目标参数在规定范围内,则终止计算。
以上操作过程可以通过下图来表示
3. 遗传算法 MATLAB 仿真实验流程 A.在遗传算法的 MATLAB 仿真实验中应注意以下四个运行参数的设定与调节。
(1) S:群体大小,即群体中所含个体的数量,一般取为 20-100.
(2) G:遗传算法的终止进化代数,一般取为 100-500.
(3) Pc:交叉概率,一般取为 0.4-0.99.
(4) Pm:变异概率,一般取为 0.0001-0.1.
B.遗传算法的 MATLAB 仿真程序设计
在本次实验中,主要涉及 ga_pid.m 以及 ga_function.m 两个文件的内容填写。
(1) 在 ga_pid.m 中对遗传算法的遗传代数、种群规模、编码长度以及 PID 初始值进行设置。
(2) 对 PID 三个参数进行编解码操作。
(3) 在理解最优指标设计以及选择与复制操作后,进行交叉步骤的编写。主
要设计交叉概率与交叉操作两部分。
(4) 进行变异步骤的编写。主要设计变异概率与变异操作两部分。
(5) 在 ga_function.m 中填写采样时间以及电机传递函数。
(6) 运行仿真程序,可以获得输出仿真图像与最优指标图像如下图所示。
四、实验结果 ga_pid.m 源代码:
%基于遗传算法的 PID 整定 clear all; close all; global yd y timef
G=100;
%遗传代数? Size=100;
%种群大小? CodeL=8;
%编码位数?
MinX(1)=zeros(1);
%kp 取值范围下限为 0 MaxX(1)=20*ones(1); %kp 取值范围上限为 20 MinX(2)=zeros(1);
%ki 取值范围下限为 0 MaxX(2)=1.0*ones(1);%ki 取值范围上限为 1 MinX(3)=zeros(1);
%kd 取值范围下限为 0 MaxX(3)=1.0*ones(1);%kd 取值范围下限为 1
%************
参数编解码 ***********
E=round(rand(Size,3*CodeL));
%Initial Code! 先由 rand 函数生成 30X30 的矩阵,然后对矩阵元素进行四舍五入,即初始种群
BsJ=1;
%所期望的最优指标为 0,即 J->0. BsJ 是 best J 的缩写
for kg=1:1:G
%100 代进化的主循环体
time(kg)=kg;
%time 变量为代数,从 1 到 100
for s=1:1:Size
%对每一代的种群中的 30 个样本(个体)进行循环
m=E(s,:);
%取 E30X30 矩阵的第 S 行,将其赋值给 m,m 的维度是 1X30,m 为当代种群中的某个个体
y1=0;y2=0;y3=0;
m1=m(1:1:CodeL);
%P 值编解码%取 m(1X30)的前 10 位
for i=1:1:CodeL
y1=y1+m1(i)*2^(i-1);%将前 10 位二进制编码转化为 10 进制
end
Kpid(s,1)=(MaxX(1)-MinX(1))*y1/1023+MinX(1);%对kp的染色体编码进行解码
m2=m(CodeL+1:1:2*CodeL);
%I 值编解码%取 m(1X30)的中间 10 位
for i=1:1:CodeL
y2=y2+m2(i)*2^(i-1);
%将中间 10 位二进制编码转化为 10 进制
end
Kpid(s,2)=(MaxX(2)-MinX(2))*y2/1023+MinX(2);
%对ki的染色体编码进行解码
m3=m(2*CodeL+1:1:end);
%D 值编解码%取 m(1X30)的最后 10 位
for i=1:1:CodeL
y3=y3+m3(i)*2^(i-1);
%将最后 10 位二进制编码转化为 10 进制
end
Kpid(s,3)=(MaxX(3)-MinX(3))*y3/1023+MinX(3);
%即对kd的染色体编码进行解码
%****** Step 1 : Evaluate BestJ ******
Kpidi=Kpid(s,:);%取 Kpid 的第 s 行赋值给 Kpidi
[Kpidi,BsJ]=ga_function(Kpidi,BsJ);%计算适应度
BsJi(s)=BsJ;
end
[OderJi,IndexJi]=sort(BsJi);%对 BsJi 数组升序排序
BestJ(kg)=OderJi(1);
BJ=BestJ(kg);
Ji=BsJi+1e-10;%避免分母为 0,即避免奇异
fi=1./Ji;
%Oderfi 为数值,Indexfi 为原序号,用 sort 函数对 fi 数组升序排序
[Oderfi,Indexfi]=sort(fi);
%Arranging fi small to bigger
Bestfi=Oderfi(Size);
% Let Bestfi=max(fi),即 Bestfi 为最大的值
BestS=E(Indexfi(Size),:);
% Let BestS=E(m), m is the Indexfi belong to max(fi)
kg
BJ
BestS;
%****** Step 2 : 选择与复制操作 Select and Reproduct Operation******
fi_sum=sum(fi);%对 fi 数组求和
fi_Size=(Oderfi/fi_sum)*Size;
fi_S=floor(fi_Size);
%Selecting Bigger fi value,向下取整,即 f_s为不大于且最接近 fi_size 的整数
r=Size-sum(fi_S);
Rest=fi_Size-fi_S;
%残差
[RestValue,Index]=sort(Rest);%对 Rest 升序排序
for i=Size:-1:Size-r+1
fi_S(Index(i))=fi_S(Index(i))+1;
% Adding rest to equal Size
end
kk=1;
for i=1:1:Size
for j=1:1:fi_S(i)
%Select and Reproduce
TempE(kk,:)=E(Indexfi(i),:);
kk=kk+1;
%kk is used to reproduce
end
end
E=TempE;
%************ Step 3 : 交叉操作 Crossover Operation ************
pc=0.63;%交叉概率建议 0.4~0.99
n=ceil(20*rand);%n 为随机交叉点,使用 ceil 函数向离它最近的大整数取整
for i=1:2:(Size-1)
temp=rand;
%设定交叉点
if pc>temp
%Crossover Condition,以 pc 的概率进行交叉操作
for j=n:1:20
%以下为交叉操作,在 n 到 20 之间的染色体基因位进行交叉
TempE(i,j)=E(i+1,j);
%?
TempE(i+1,j)=E(i,j);
%?
end
end
end
TempE(Size,:)=BestS;
E=TempE;
%************ Step 4:变异操作 Mutation Operation **************
pm=0.002; %变异概率, 建议 0.0001~0.1
for i=1:1:Size
for j=1:1:3*CodeL
temp=rand;
if pm>temp
%Mutation Condition,变异操作
if TempE(i,j)==0
TempE(i,j)=1;
else
TempE(i,j)=0;
end
end
end
end
%Guarantee TempE(Size,:) belong to the best individual
TempE(Size,:)=BestS;
E=TempE; %******************************************************* end
Bestfi BestS
Kpidi Best_J=BestJ(G) figure(1); plot(time,BestJ,"r","linewidth",2); xlabel("Times");ylabel("Best J"); figure(2); plot(timef,yd,"r",timef,y,"b:","linewidth",2); xlabel("Time(s)");ylabel("yd,y"); legend("Ideal position signal","Position signal tracking");
运行结果:
Kpidi =
0
0
0.2483
Best_J =
20.3517
ga_function 源代码:
function [Kpidi,BsJ]=ga_function(Kpidi,BsJ) global yd y timef
ts=0.001;
%采样时间 %sys=tf(400,[1,50,1]);
%传递函数举例 sys=tf(209.06,[2.16*10^-8,0.006,1]);
%电机传递函数
dsys=c2d(sys,ts,"z"); [num,den]=tfdata(dsys,"v");
u_1=0.0;u_2=0.0; y_1=0.0;y_2=0.0; x=[0,0,0]"; B=0; error_1=0; tu=1; s=0; P=150;
for k=1:1:P
timef(k)=k*ts;
yd(k)=1.0;
u(k)=Kpidi(1)*x(1)+Kpidi(2)*x(2)+Kpidi(3)*x(3);
if u(k)>=10
u(k)=10;
end
if u(k)<=-10
u(k)=-10;
end
y(k)=-den(2)*y_1-den(3)*y_2+num(2)*u_1+num(3)*u_2;
error(k)=yd(k)-y(k);
%------------ Return of PID parameters -------------
u_2=u_1;u_1=u(k);
y_2=y_1;y_1=y(k);
x(1)=error(k);
% Calculating P
x(2)=(error(k)-error_1)/ts;
% Calculating D
x(3)=x(3)+error(k)*ts;
% Calculating I
error_2=error_1;
error_1=error(k);
if s==0
if y(k)>0.95&y(k)<1.05
tu=timef(k);
s=1;
end
end end
for i=1:1:P
Ji(i)=0.999*abs(error(i))+0.01*u(i)^2*0.1;
B=B+Ji(i);
if i>1
erry(i)=y(i)-y(i-1);
if erry(i)<0
B=B+100*abs(erry(i));
%误差惩罚
end
end end BsJ=B+0.2*tu*10;
运行结果:
>> ga_function(Kpidi,Best_J)
ans =
0
0
0.2317
角度随动系统实验:
#include <string.h> #include <stdio.h> #include "ga_pid.h" /*=========================================================
PID Function
The PID (比例、积分、微分) function is used in mainly
control applications. PIDCalc performs one iteration of the PID
algorithm.
While the PID function works, main is just a dummy program showing
a typical usage. ======================================================*/
/*===================================================================
Initialize PID Structure ======================================================*/
void PIDInit (PID *pp) {
memset ( pp, 0, sizeof(PID)); }
//right_angle 期望值, left_angle 反馈值
//left_angle --- 左边电机 被控电机角度 //right_angle --- 右边电机 理想电机角度 float ga_pid(PID * sPID, float left_angle, float right_angle) {
//PIDInit ( &sPID );
//
Initialize Structure
sPID->Proportion = 0.000015779;
//
PID 参数
sPID->Derivative = -0.0013;
sPID->Integral
= 0.0192;
float
dError, Error; float u;
Error = right_angle - left_angle;
// 偏差
printf("left_angle = %7.2f, right_angle = %7.2f, e = %7.2f\n", left_angle, right_angle, Error);
sPID->SumError += Error;
// 积分
dError = sPID->LastError - sPID->PrevError;
// 当前微分
sPID->PrevError = sPID->LastError;
sPID->LastError = Error;
printf("err = %7.2f, sum = %7.2f, derr = %7.2f\n", Error, sPID->SumError, dError);
u = sPID->Proportion * Error
// 比例项
+
sPID->Integral * sPID->SumError
// 积分项
+
sPID->Derivative * dError;
// 微分项
if (u > 10) u = 10;
if (u < -10) u = -10;
printf("u = %7.2f\n", u);
return u; }
版权所有:格斯文档网 2010-2024 未经授权禁止复制或建立镜像[格斯文档网]所有资源完全免费共享
Powered by 格斯文档网 © All Rights Reserved.。浙ICP备19042928号