智能控制實驗報告
姓名:
學院:
專業:自動化 班級:
學號:
指導教師:
成績:
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) ,采樣時間 ts??0.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) ,采樣時間 ts??0.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; }
推薦訪問: 智能控制 實驗 報告上一篇:Linux實驗報告,,
下一篇:黑盒測試實驗報告
同志們:今天這個大會,是市委全面落實黨要管黨、從嚴治黨要求的一項重大舉措,也是對縣市區委書記履行基層黨建工作第一責任人情況的一次集中檢閱,同時是對全市基層黨建工作的一次再部署、再落實的會議。前面,**
***年,我認真履行領班子、帶隊伍、抓黨員、保穩定的基層黨建工作思路,以學習貫徹習近平新時代中國特色社會主義思想和黨的十九大歷次全會精神為主線,以市局基層黨建工作考核細則為落腳點,落實全面從嚴治黨主體
根據會議安排,現將2022年履行抓基層黨建工作職責情況報告如下:一、履職工作特色和亮點1 突出政治建設,著力在思想認識上提高。牢固樹立抓黨建就是抓政績的理念,以“黨建工作抓引領、社區治理求突破,為民服
2022年以來,在**黨委的正確領導下,堅持以習近平新時代中國特色社會主義思想為指導,深入學習宣傳貫徹黨的二十大精神,以黨建工作為統領,扎實開展夯實“三個基本”活動,以“四化四力”行動為抓手,聚力創建
各位領導,同志們:根據會議安排,現就2022年度抓基層黨建工作情況匯報如下:一、主要做法及成效(一)強化政治引領。一是不斷強化理論武裝。堅持通過黨組會、中心組學習會和“三會一課”,第一時間、第一議題學
2022年度抓基層黨建工作述職報告按照黨委工作部署,現將本人2022年度抓基層黨建工作情況報告如下:一、2022年度抓基層黨建工作情況(一)旗幟鮮明講政治將旗幟鮮明講政治放在全局發展首要位置,積極開展
2022年,是我在數計系黨總支書記這個新崗位上度過的第一個完整的工作年度?;厥滓荒陙碓谛|h委的正確領導下,與數計系領導班子和全體師生共同走過的日子,艱辛歷歷在目,收獲溫潤心田。作為黨總支書記,我始終牢
按照考核要求,現將本人一年來,作為統戰部長履行職責、廉潔自律等方面情況報告如下:一、著眼增強政治素質,不斷深化理論學習堅持把旗幟鮮明講政治作為履職從政的第一位要求,帶領統戰系統干部堅決擁護“兩個確立”
**年,緊緊圍繞黨工委、管委會的決策部署,全體人員團結協作、凝心聚力,緊扣黨工委“**”基本工作思路,全力開拓進取,認真履職盡責,圓滿完成各項工作任務。一、個人思想政治狀況檸檬文苑www bgzjy
按照縣委關于開展抓基層黨建述職評議會議的有關要求,經請示縣委組織部同意,今天,我們在此召開2022年度基層黨組織書記抓基層黨建述職評議會議。1 首先,請**黨委書記,**同志述職。**黨委能夠主動研究