4444import matplotlib .pyplot as plt
4545import scipy as sp
4646import numpy as np
47+ from warnings import warn
4748from ctrlutil import unwrap
4849from bdalg import feedback
49- from lti import isdtime
50+ from lti import isdtime , timebaseEqual
5051
5152#
5253# Main plotting functions
@@ -90,9 +91,14 @@ def bode_plot(syslist, omega=None, dB=False, Hz=False, deg=True,
9091
9192 Notes
9293 -----
93- 1. Alternatively, you may use the lower-level method
94- (mag, phase, freq) = sys.freqresp(freq) to generate the frequency
95- response for a system, but it returns a MIMO response.
94+ 1. Alternatively, you may use the lower-level method (mag, phase, freq)
95+ = sys.freqresp(freq) to generate the frequency response for a system,
96+ but it returns a MIMO response.
97+
98+ 2. If a discrete time model is given, the frequency response is plotted
99+ along the upper branch of the unit circle, using the mapping z = exp(j
100+ \omega dt) where omega ranges from 0 to pi/dt and dt is the discrete
101+ time base. If not timebase is specified (dt = True), dt is set to 1.
96102
97103 Examples
98104 --------
@@ -105,16 +111,12 @@ def bode_plot(syslist, omega=None, dB=False, Hz=False, deg=True,
105111
106112 mags , phases , omegas = [], [], []
107113 for sys in syslist :
108- # TODO: implement for discrete time systems
109- if (isdtime (sys , strict = True )):
110- raise (NotImplementedError ("Function not implemented in discrete time" ))
111-
112114 if (sys .inputs > 1 or sys .outputs > 1 ):
113115 #TODO: Add MIMO bode plots.
114116 raise NotImplementedError ("Bode is currently only implemented for SISO systems." )
115117 else :
116- # Select a default range if none is provided
117118 if (omega == None ):
119+ # Select a default range if none is provided
118120 omega = default_frequency_range (syslist )
119121
120122 # Get the magnitude and phase of the system
@@ -204,6 +206,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
204206
205207 # Select a default range if none is provided
206208 if (omega == None ):
209+ #! TODO: think about doing something smarter for discrete
207210 omega = default_frequency_range (syslist )
208211
209212 # Interpolate between wmin and wmax if a tuple or list are provided
@@ -214,10 +217,6 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
214217 omega = np .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]),
215218 num = 50 , endpoint = True , base = 10.0 )
216219 for sys in syslist :
217- # TODO: implement for discrete time systems
218- if (isdtime (sys , strict = True )):
219- raise (NotImplementedError ("Function not implemented in discrete time" ))
220-
221220 if (sys .inputs > 1 or sys .outputs > 1 ):
222221 #TODO: Add MIMO nyquist plots.
223222 raise NotImplementedError ("Nyquist is currently only implemented for SISO systems." )
@@ -281,10 +280,6 @@ def gangof4_plot(P, C, omega=None):
281280 -------
282281 None
283282 """
284- # TODO: implement for discrete time systems
285- if (isdtime (P , strict = True ) or isdtime (C , strict = True )):
286- raise (NotImplementedError ("Function not implemented in discrete time" ))
287-
288283 if (P .inputs > 1 or P .outputs > 1 or C .inputs > 1 or C .outputs > 1 ):
289284 #TODO: Add MIMO go4 plots.
290285 raise NotImplementedError ("Gang of four is currently only implemented for SISO systems." )
@@ -365,11 +360,8 @@ def default_frequency_range(syslist):
365360 # detect if single sys passed by checking if it is sequence-like
366361 if (not getattr (syslist , '__iter__' , False )):
367362 syslist = (syslist ,)
368- for sys in syslist :
369- # TODO: implement for discrete time systems
370- if (isdtime (sys , strict = True )):
371- raise (NotImplementedError ("Function not implemented in discrete time" ))
372363
364+ for sys in syslist :
373365 # Add new features to the list
374366 features = np .concatenate ((features , np .abs (sys .pole ())))
375367 features = np .concatenate ((features , np .abs (sys .zero ())))
@@ -383,10 +375,12 @@ def default_frequency_range(syslist):
383375 # Take the log of the features
384376 features = np .log10 (features )
385377
378+ #! TODO: Add a check in discrete case to make sure we don't get aliasing
379+
386380 # Set the range to be an order of magnitude beyond any features
387381 omega = sp .logspace (np .floor (np .min (features ))- 1 ,
388382 np .ceil (np .max (features ))+ 1 )
389-
383+
390384 return omega
391385
392386#
0 commit comments