@@ -119,48 +119,58 @@ def bode_plot(syslist, omega=None, omega_num=None, dB=None, Hz=None, deg=None,
119119 # If argument was a singleton, turn it into a list
120120 if (not getattr (syslist , '__iter__' , False )):
121121 syslist = (syslist ,)
122-
123- mags , phases , omegas = [], [], []
122+
123+ if omega is None :
124+ # Select a default range if none is provided
125+ omega = default_frequency_range (syslist )
126+ elif (isinstance (omega , tuple ) or isinstance (omega , list )) and len (omega ) == 2 :
127+ if omega_num :
128+ omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), num = omega_num , endpoint = False )
129+ else :
130+ omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), endpoint = False )
131+
132+ mags , phases , omegas , nyquistfrqs = [], [], [], []
124133 for sys in syslist :
125134 if (sys .inputs > 1 or sys .outputs > 1 ):
126135 #TODO: Add MIMO bode plots.
127136 raise NotImplementedError ("Bode is currently only implemented for SISO systems." )
128137 else :
129- if omega is None :
130- # Select a default range if none is provided
131- omega = default_frequency_range (syslist )
132- elif (isinstance (omega , tuple ) or isinstance (omega , list )) and len (omega ) == 2 :
133- if omega_num :
134- omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), num = omega_num , endpoint = False )
135- else :
136- omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), endpoint = False )
137-
138+ omega_sys = np .array (omega )
139+ if sys .isdtime (True ):
140+ nyquistfrq = 2. * np .pi * 1. / sys .dt / 2.
141+ omega_sys = omega_sys [omega_sys < nyquistfrq ]
142+ else :
143+ nyquistfrq = None
138144 # Get the magnitude and phase of the system
139- omega = np .array (omega )
140- mag_tmp , phase_tmp , omega_sys = sys .freqresp (omega )
145+ mag_tmp , phase_tmp , omega_sys = sys .freqresp (omega_sys )
141146 mag = np .atleast_1d (np .squeeze (mag_tmp ))
142147 phase = np .atleast_1d (np .squeeze (phase_tmp ))
143148 phase = unwrap (phase )
149+ nyquistfrq_plot = None
144150 if Hz :
145151 omega_plot = omega_sys / (2. * np .pi )
152+ if nyquistfrq :
153+ nyquistfrq_plot = nyquistfrq / (2. * np .pi )
146154 else :
147155 omega_plot = omega_sys
148156
149157 mags .append (mag )
150158 phases .append (phase )
151159 omegas .append (omega_sys )
160+ nyquistfrqs .append (nyquistfrq )
152161 # Get the dimensions of the current axis, which we will divide up
153162 #! TODO: Not current implemented; just use subplot for now
154163
155164 if (Plot ):
156165 # Magnitude plot
157166 ax_mag = plt .subplot (211 );
158167 if dB :
159- plt .semilogx (omega_plot , 20 * np .log10 (mag ), * args , ** kwargs )
168+ pltline = plt .semilogx (omega_plot , 20 * np .log10 (mag ), * args , ** kwargs )
160169 else :
161- plt .loglog (omega_plot , mag , * args , ** kwargs )
170+ pltline = plt .loglog (omega_plot , mag , * args , ** kwargs )
162171 plt .hold (True );
163-
172+ if nyquistfrq_plot :
173+ plt .axvline (nyquistfrq_plot , color = pltline [0 ].get_color ())
164174 # Add a grid to the plot + labeling
165175 plt .grid (True )
166176 plt .grid (True , which = 'minor' )
@@ -174,7 +184,8 @@ def bode_plot(syslist, omega=None, omega_num=None, dB=None, Hz=None, deg=None,
174184 phase_plot = phase
175185 plt .semilogx (omega_plot , phase_plot , * args , ** kwargs )
176186 plt .hold (True );
177-
187+ if nyquistfrq_plot :
188+ plt .axvline (nyquistfrq_plot , color = pltline [0 ].get_color ())
178189 # Add a grid to the plot + labeling
179190 plt .grid (True )
180191 plt .grid (True , which = 'minor' )
@@ -270,7 +281,7 @@ def nyquist_plot(syslist, omega=None, Plot=True, color='b',
270281 # result to the range [-8, 8].
271282 pow1000 = max (min (get_pow1000 (f ),8 ),- 8 )
272283
273- # Get the SI prefix.
284+ # Get the SI prefix.
274285 prefix = gen_prefix (pow1000 )
275286
276287 # Apply the text. (Use a space before the text to
@@ -381,6 +392,7 @@ def default_frequency_range(syslist, number_of_samples=None):
381392
382393 # Find the list of all poles and zeros in the systems
383394 features = np .array (())
395+ freq_interesting = []
384396
385397 # detect if single sys passed by checking if it is sequence-like
386398 if (not getattr (syslist , '__iter__' , False )):
@@ -389,8 +401,15 @@ def default_frequency_range(syslist, number_of_samples=None):
389401 for sys in syslist :
390402 try :
391403 # Add new features to the list
392- features = np .concatenate ((features , np .abs (sys .pole ())))
393- features = np .concatenate ((features , np .abs (sys .zero ())))
404+ if sys .isctime ():
405+ features = np .concatenate ((features , np .abs (sys .pole ())))
406+ features = np .concatenate ((features , np .abs (sys .zero ())))
407+ elif sys .isdtime (strict = True ):
408+ freq_interesting .append (np .pi * 1. / sys .dt )
409+ # TODO: how to determine lowest interesting frequency?
410+ else :
411+ pass
412+ # TODO:
394413 except :
395414 pass
396415
@@ -401,17 +420,21 @@ def default_frequency_range(syslist, number_of_samples=None):
401420 if (features .shape [0 ] == 0 ): features = [1 ];
402421
403422 # Take the log of the features
423+ # TODO: in case of Hz==True: wouldn't it make more sense to to set the limits to decades in Hz instead of rad/s?
404424 features = np .log10 (features )
425+ lsp_min = np .floor (np .min (features ))- 1
426+ lsp_max = np .ceil (np .max (features ))+ 1
427+ if freq_interesting :
428+ lsp_min = min (lsp_min , np .log10 (min (freq_interesting )))
429+ lsp_max = max (lsp_max , np .log10 (max (freq_interesting )))
405430
406431 #! TODO: Add a check in discrete case to make sure we don't get aliasing
407432
408433 # Set the range to be an order of magnitude beyond any features
409434 if number_of_samples :
410- omega = sp .logspace (np .floor (np .min (features ))- 1 ,
411- np .ceil (np .max (features ))+ 1 , num = number_of_samples )
435+ omega = sp .logspace (lsp_min , lsp_max , num = number_of_samples , endpoint = False )
412436 else :
413- omega = sp .logspace (np .floor (np .min (features ))- 1 ,
414- np .ceil (np .max (features ))+ 1 )
437+ omega = sp .logspace (lsp_min , lsp_max , endpoint = False )
415438
416439
417440
0 commit comments