4646import matplotlib .patches as mpatches
4747
4848from data_extractor import *
49- from pid_design import computePidGmvc , gainsToNumDen , computePidDahlin
49+ from pid_design import computePidGmvc
5050from system_identification import SystemIdentification
5151import control as ctrl
5252from scipy .signal import resample , detrend
@@ -520,7 +520,6 @@ def computeController(self):
520520 self .ki /= 5.0
521521 static_gain = sum (self .num ) / sum (self .den )
522522 self .kff = 1 / static_gain
523- # (self.kc, self.ki, self.kd) = computePidDahlin(self.num, self.den, self.dt, sigma)
524523
525524 self .updateKIDSliders ()
526525 self .updateClosedLoop ()
@@ -542,24 +541,37 @@ def updateClosedLoop(self):
542541 ki = self .ki
543542 kd = self .kd
544543 kff = self .kff
545- Gd = ctrl .TransferFunction ([1 ], np .append ([1 ], np .zeros (self .sys_id_delays )), dt )
546- Gz2 = ctrl .TransferFunction (num , den , dt )
547- Gi = ctrl .TransferFunction ([ki * dt , ki * dt ], [2 , - 2 ], dt )
548-
549- if True :
550- # PI controller without zero
551- Gcp = ctrl .feedback (kc * Gz2 , [1 ])
552- Gcl = ctrl .feedback (ctrl .series (Gi , Gcp ), [1 ])
553- else :
554- # Standard PI controller
555- pi = ctrl .series (kc , ctrl .parallel ([1 ], Gi ))
556- Gcl = ctrl .feedback (ctrl .series (pi , Gz2 ), [1 ])
557544
558- t_out ,y_out = ctrl .step_response (Gcl , T = np .arange (0 ,1 ,dt ))
545+ delays = ctrl .TransferFunction ([1 ], np .append ([1 ], np .zeros (self .sys_id_delays )), dt , inputs = 'r' , outputs = 'rd' )
546+ plant = ctrl .TransferFunction (num , den , dt , inputs = 'u' , outputs = 'plant_out' )
547+ sampler = ctrl .TransferFunction ([1 ], [1 , 0 ], dt , inputs = 'plant_out' , outputs = 'y' )
548+ sum_feedback = ctrl .summing_junction (inputs = ['rd' , '-y' ], output = 'e' )
549+
550+ # Default is standard PID
551+ feedforward = ctrl .TransferFunction ([kff ], [1 ], dt , inputs = 'rd' , outputs = 'ff_out' )
552+ p_control = ctrl .TransferFunction ([kc ], [1 ], dt , inputs = 'e' , outputs = 'p_out' )
553+ i_control = ctrl .TransferFunction ([kc * ki * dt , kc * ki * dt ], [2 , - 2 ], dt , inputs = 'e' , outputs = 'i_out' ) # Integrator discretized using bilinear transform
554+ d_control = ctrl .TransferFunction ([2 * kc * kd , - 2 * kc * kd ], [dt , dt ], dt , inputs = 'e' , outputs = 'd_out' )
555+ sum_control = ctrl .summing_junction (inputs = ['ff_out' , 'p_out' , 'i_out' , 'd_out' ], output = 'u' )
556+
557+ remove_zero = False
558+ no_derivative_kick = True
559+
560+ if remove_zero :
561+ # P on feedback only to remove zero (3-loop autopilot style)
562+ p_control = ctrl .TransferFunction ([- kc ], [1 ], dt , inputs = 'y' , outputs = 'p_out' )
563+
564+ if no_derivative_kick :
565+ # Derivative on feedback only to remove the "derivative kick"
566+ d_control = ctrl .TransferFunction ([- 2 * kc * kd , 2 * kc * kd ], [dt , dt ], dt , inputs = 'y' , outputs = 'd_out' )
567+
568+ closed_loop = ctrl .interconnect ([delays , sampler , sum_feedback , feedforward , sum_control , p_control , i_control , d_control , plant ], inputs = 'r' , outputs = 'y' )
569+
570+ t_out ,y_out = ctrl .step_response (closed_loop , T = np .arange (0 ,1 ,dt ))
559571 self .plotClosedLoop (t_out , y_out )
560572 w = np .logspace (- 1 , 3 , 40 ).tolist ()
561- mag , phase , omega = ctrl .bode (Gz2 , omega = np .asarray (w ), plot = False )
562- mag_cl , phase_cl , omega_cl = ctrl .bode (Gcl , omega = np .asarray (w ), plot = False )
573+ mag , phase , omega = ctrl .bode (plant , omega = np .asarray (w ), plot = False )
574+ mag_cl , phase_cl , omega_cl = ctrl .bode (closed_loop , omega = np .asarray (w ), plot = False )
563575 self .plotBode (omega , mag , omega_cl , mag_cl )
564576
565577 def plotClosedLoop (self , t , y ):
0 commit comments