From e59096aed9e3648512848244eee36c3aeba7f101 Mon Sep 17 00:00:00 2001 From: Nikhil Nair Date: Sat, 15 Jan 2022 10:20:23 +0530 Subject: [PATCH] Updated Code --- RBF.py | 6 +- README.md | 5 - nonlinearsystem_with_adaptive_pid.py | 33 +++++-- nonlinearsystem_with_pid.py | 51 +++++++++-- singlearea.py | 74 +++++++++++++++ singlearea_with_adaptive_pid.py | 131 +++++++++++++++++++++++++++ 6 files changed, 278 insertions(+), 22 deletions(-) delete mode 100644 README.md create mode 100644 singlearea.py create mode 100644 singlearea_with_adaptive_pid.py diff --git a/RBF.py b/RBF.py index 1370e5a..7b39ef9 100644 --- a/RBF.py +++ b/RBF.py @@ -1,11 +1,10 @@ import numpy as np -from numpy.lib.function_base import average class RBF: def __init__(self , aw , av , au , asig , gamma ,h = 3 ): - # TODO : Initialize all parameters + # Initialize all parameters self.X = np.zeros((3,1)) self.h = h @@ -19,6 +18,7 @@ class RBF: self.w = np.zeros( (3, h) ) self.v = np.zeros( (1, h) ) self.output = np.zeros( (h,1) ) + # Learning Rates self.aw = aw @@ -80,7 +80,7 @@ class RBF: self.sigma[0][i] = self.sigma[0][i] + self.asig*del_TD*del_TD*v_prev[0][i]*self.output[i]*( np.linalg.norm(self.X- self.sigma[0][i]) )/self.sigma[0][i]**3 - print(self.K) + # print(self.K) diff --git a/README.md b/README.md deleted file mode 100644 index 1caa196..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Adaptive-PID-controller - - -Code implementation of an adaptive PID controller for Non-linear Systems - diff --git a/nonlinearsystem_with_adaptive_pid.py b/nonlinearsystem_with_adaptive_pid.py index 9457b44..57144b6 100644 --- a/nonlinearsystem_with_adaptive_pid.py +++ b/nonlinearsystem_with_adaptive_pid.py @@ -10,10 +10,24 @@ def y(yd): rbf = RBF.RBF(0.13,0.21,0.25,0.9,0.98) t = 1 - yt_1 = 0.9 - yt_2 = 1.1 - yt_3 = 1.1 - dt = 1/800 + # Initial State 1 + # yt_1 = 1.1 + # yt_2 = 1.1 + # yt_3 = 1.1 + + # Initial State 2 + # yt_1 = 3.23 + # yt_2 = 0.32 + # yt_3 = 0.23 + + # Initial State 3 + yt_1 = 0.4 + yt_2 = 0.46 + yt_3 = 0.42 + + initial_states = [ yt_1, yt_2 , yt_3] + + dt = 1/400 Ki = -0.07709546 Kd = 0.58844546 @@ -51,7 +65,7 @@ def y(yd): y.append(yt_1) x.append(i*dt) - return y,x + return y,x,initial_states if __name__=="__main__": @@ -59,18 +73,21 @@ if __name__=="__main__": yd = [2.1 for i in range(100) ] + [3.5 for i in range(100) ] + [2 for i in range(100) ] + [3 for i in range(100) ] - yd+=yd - ## Generate Reference array here - y,x = y(yd) + y,x,i = y(yd) plt.plot(x,yd, label="Reference Signal") plt.plot(x,y,label ="Output") + plt.title( " Initial States y(t-1) , y(t-2) and y(t-3) are " + str(i[0]) + ", " + str(i[1]) +" and "+ str(i[2]) ) + plt.legend() + plt.ylabel(" Output from System ") + plt.xlabel("Time (s)") + plt.show() diff --git a/nonlinearsystem_with_pid.py b/nonlinearsystem_with_pid.py index 9ae2c84..8c63729 100644 --- a/nonlinearsystem_with_pid.py +++ b/nonlinearsystem_with_pid.py @@ -4,55 +4,94 @@ import numpy as np def y(yd): + + # Initial Conditions t = 1 - yt_1 = 0.9 + + # Initial State 1 + # yt_1 = 1.1 + # yt_2 = 1.1 + # yt_3 = 1.1 + + # Initial State 2 + # yt_1 = 3.23 + # yt_2 = 0.32 + # yt_3 = 0.23 + + # Initial State 3 + yt_1 = 2.3 yt_2 = 1.1 yt_3 = 1.1 + + + + initial_states = [ yt_1, yt_2 , yt_3] + + # Defining dt for 400 steps dt = 1/400 + # PID controller Parameters Ki = 0.8 - Kd = 0.001 - Kp = 0.61 + Kd = 0.34 + Kp = 0.01 + + + # Initial Control Signal ut_1 = 0 y=[] x=[] - + et =[] for i in range(0, int(t/dt) ): + # State Equations e_t = yd[i] - yt_1 del_y = yt_1 - yt_2 del2_y = yt_1 - 2*yt_2 + yt_3 + et.append(e_t) + # Control Signal + ut_1 = ut_1 + Ki*e_t - Kp*del_y - Kd*del2_y + # Passing Signal to Non-linear system + yt_1,yt_2,yt_3 = yt_1*yt_2*(yt_1 + 2.5) / ( 1 + yt_1**2 + yt_2**2 )+ ut_1 +np.random.normal(0,0.01) , yt_1 , yt_2 y.append(yt_1) x.append(i*dt) - return y,x + return y,x,et,initial_states if __name__=="__main__": + # Reference Signal yd = [2.5 for i in range(100) ] + [3.5 for i in range(100) ] + [1 for i in range(100) ] + [3 for i in range(100) ] ## Generate Reference array here - y,x = y(yd) + y,x,et,i = y(yd) plt.plot(x,yd, label="Reference Signal") plt.plot(x,y,label ="Output") + for j in et: + print(j) + + plt.title( " Initial States y(t-1) , y(t-2) and y(t-3) are " + str(i[0]) + ", " + str(i[1]) +" and "+ str(i[2]) ) + plt.legend() + plt.ylabel(" Output from System ") + plt.xlabel("Time (s)") + plt.show() diff --git a/singlearea.py b/singlearea.py new file mode 100644 index 0000000..56d1e92 --- /dev/null +++ b/singlearea.py @@ -0,0 +1,74 @@ +import numpy as np +from numpy.core.numeric import NaN +from scipy.linalg import expm +import math + +class SingleArea: + + def __init__(self,Tg,Tt,M,D,R,T,yt_1,yt_2,yt_3): + + self.yt_1 = yt_1 + self.yt_2 = yt_2 + self.yt_3 = yt_3 + + self.Xprev = np.zeros( (3,1) ) + self.Y = np.zeros( (1,1) ) + + self.Tg = Tg + self.Tt = Tt + self.M = M + self.D = D + self.R = R + + self.T = T + + self.CalcDiscreteCoef() + + def CalcDiscreteCoef(self): + + # Calculating Continous coef + + self.A = np.array( [ [-self.D/self.M , 1/self.M , 0] , [ 0 , -1/self.Tt , 1/self.Tt ] , [-1/( self.Tg*self.R ) , 0 , -1/self.Tg ] ] ) + + self.B = np.array( [ [0 , -1/self.M ] , [ 0 , 0 ] , [ 1/self.Tg , 0 ] ]) + + self.C = np.array( [[1 , 0 , 0]] ) + + # Calculating Discrete Coefs + + self.Ad = expm(self.A*self.T) + + # Add check later + + self.Bd = np.dot( np.dot(np.linalg.inv(self.A),(self.Ad - np.eye(3) )), self.B ) + + def Output(self,Ut): + + self.yt_1 , self.yt_2 , self.yt_3 = self.Y[0,0] , self.yt_1, self.yt_2 + + self.X = np.dot( self.Ad, self.Xprev ) + np.dot( self.Bd, Ut ) + + self.Y = np.dot( self.C, self.Xprev) + + # print("Chooth :" , self.Y) + + self.Xprev = self.X + + if (math.isnan(self.Y[0,0])): + + return True + + return False + + + + + + + + + + + + + diff --git a/singlearea_with_adaptive_pid.py b/singlearea_with_adaptive_pid.py new file mode 100644 index 0000000..d47a6b2 --- /dev/null +++ b/singlearea_with_adaptive_pid.py @@ -0,0 +1,131 @@ +import matplotlib.pyplot as plt +import numpy as np +from numpy.lib.function_base import append + +from singlearea import * + +import RBF + + +def y(yd): + + rbf = RBF.RBF( aw = 0.0003, av = 0.021, au = 0.025 , asig = 0.01, gamma = 0.9) + + Tg = 0.08 + Tt = 0.3 + M = 0.2 + D = 0.01 + R = 2 + T = dt = 1/400 + + yt_1 = 0 + yt_2 = 0 + yt_3 = 0 + + System = SingleArea( Tg , Tt , M , D , R , T , yt_1 , yt_2 , yt_3 ) + + + + initial_states = [ yt_1, yt_2 , yt_3] + + plot_data = {"ut":[] , "pl" : [] , "delF":[] , 'KI' : [], 'KP' : [] , 'KD' : [] , "time" : []} + + + Ki = 0 + Kd = 0 + Kp = 0 + + ut_1 = 0 + + t = 10 + + y=[] + x=[] + + + for i in range(0, int(t/dt) ): + + # print(System.yt_1) + e_t = 0 - System.yt_1 + del_y = System.yt_1 - System.yt_2 + del2_y = System.yt_1 - 2*System.yt_2 + System.yt_3 + + rbf.X[:,0] = [ e_t , -del_y , -del2_y] + rbf.HiddenLayer() + rbf.OutputLayer() + + + # ut_1 = ut_1 + 0.00043*e_t - 0.01*del_y - 0*del2_y + ut_1 = ut_1 + rbf.K[1]*e_t - rbf.K[0]*del_y - rbf.K[2]*del2_y + + plot_data["ut"].append(ut_1) + + + + PL = 0.2 if( i*dt >= 0.2 ) else 0 + plot_data["pl"].append(PL) + + Ut = [ [ut_1] , [ PL] ] + + System.Output(Ut) + + print(rbf.K) + + rbf.Update(0 ,System.Y[0,0] ,System.yt_1 , System.yt_2, System.yt_3 ) + + plot_data["delF"].append(System.Y[0,0]) + plot_data["time"].append(i*dt) + plot_data["KI"].append(rbf.K[1]) + plot_data["KP"].append(rbf.K[0]) + plot_data["KD"].append(rbf.K[2]) + + return plot_data,initial_states + + +if __name__=="__main__": + + + yd = [0 for i in range(10*400) ] + + + ## Generate Reference array here + + plot_data,i = y(yd) + + + plt.subplot(2,2,1) + plt.plot(plot_data["time"],plot_data["pl"], label="Reference Signal") + plt.title( "Load vs Time") + plt.ylabel(" Output from System ") + plt.xlabel("Time (s)") + + plt.subplot(2,2,2) + plt.plot(plot_data["time"],plot_data["KI"], label="KI") + plt.plot(plot_data["time"],plot_data["KP"], label="KP") + plt.plot(plot_data["time"],plot_data["KD"], label="KD") + plt.title( "KI, KP, KD vs Time") + plt.ylabel("KI, KP, KD") + plt.xlabel("Time (s)") + plt.legend() + + plt.subplot(2,2,3) + plt.plot(plot_data["time"],plot_data["ut"], label="Reference Signal") + plt.title( "Control Signal vs Time") + plt.ylabel("Control Signal") + plt.xlabel("Time (s)") + + plt.subplot(2,2,4) + plt.plot(plot_data["time"],yd, label="Reference Signal") + plt.plot(plot_data["time"],plot_data["delF"],label ="Output") + + + plt.title( " Initial States y(t-1) , y(t-2) and y(t-3) are " + str(i[0]) + ", " + str(i[1]) +" and "+ str(i[2]) ) + + plt.legend() + + plt.ylabel(" Output from System ") + plt.xlabel("Time (s)") + + + plt.show() +