4444import matplotlib .pyplot as plt
4545import scipy as sp
4646import numpy as np
47- from warnings import warn
47+ # from warnings import warn
4848from .ctrlutil import unwrap
4949from .bdalg import feedback
50- from .lti import isdtime , timebaseEqual
50+ # from .lti import isdtime, timebaseEqual
5151
5252__all__ = ['bode_plot' , 'nyquist_plot' , 'gangof4_plot' ,
5353 'bode' , 'nyquist' , 'gangof4' ]
@@ -122,12 +122,12 @@ def bode_plot(syslist, omega=None, omega_num=None, dB=None, Hz=None, deg=None,
122122
123123 if omega is None :
124124 # Select a default range if none is provided
125- omega = default_frequency_range (syslist )
125+ omega = default_frequency_range (syslist , Hz = Hz )
126126 elif (isinstance (omega , tuple ) or isinstance (omega , list )) and len (omega ) == 2 :
127127 if omega_num :
128- omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), num = omega_num , endpoint = False )
128+ omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), num = omega_num , endpoint = True )
129129 else :
130- omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), endpoint = False )
130+ omega = sp .logspace (np .log10 (omega [0 ]), np .log10 (omega [1 ]), endpoint = True )
131131
132132 mags , phases , omegas , nyquistfrqs = [], [], [], []
133133 for sys in syslist :
@@ -138,7 +138,8 @@ def bode_plot(syslist, omega=None, omega_num=None, dB=None, Hz=None, deg=None,
138138 omega_sys = np .array (omega )
139139 if sys .isdtime (True ):
140140 nyquistfrq = 2. * np .pi * 1. / sys .dt / 2.
141- omega_sys = omega_sys [omega_sys < nyquistfrq ]
141+ nyquistfrq_limit = nyquistfrq - (omega_sys [- 1 ] - omega_sys [- 2 ]) / 2. # floating point!
142+ omega_sys = omega_sys [omega_sys < nyquistfrq_limit ]
142143 else :
143144 nyquistfrq = None
144145 # Get the magnitude and phase of the system
@@ -153,6 +154,8 @@ def bode_plot(syslist, omega=None, omega_num=None, dB=None, Hz=None, deg=None,
153154 nyquistfrq_plot = nyquistfrq / (2. * np .pi )
154155 else :
155156 omega_plot = omega_sys
157+ if nyquistfrq :
158+ nyquistfrq_plot = nyquistfrq
156159
157160 mags .append (mag )
158161 phases .append (phase )
@@ -359,7 +362,7 @@ def gangof4_plot(P, C, omega=None):
359362#
360363
361364# Compute reasonable defaults for axes
362- def default_frequency_range (syslist , number_of_samples = None ):
365+ def default_frequency_range (syslist , Hz = None , number_of_samples = None , feature_periphery_decade = None ):
363366 """Compute a reasonable default frequency range for frequency
364367 domain plots.
365368
@@ -390,6 +393,13 @@ def default_frequency_range(syslist, number_of_samples=None):
390393 # integer. It excludes poles and zeros at the origin. If no features
391394 # are found, it turns logspace(-1, 1)
392395
396+ # Set default values for options
397+ from . import config
398+ if (number_of_samples is None ):
399+ number_of_samples = config .bode_number_of_samples
400+ if (feature_periphery_decade is None ):
401+ feature_periphery_decade = config .bode_feature_periphery_decade
402+
393403 # Find the list of all poles and zeros in the systems
394404 features = np .array (())
395405 freq_interesting = []
@@ -402,42 +412,54 @@ def default_frequency_range(syslist, number_of_samples=None):
402412 try :
403413 # Add new features to the list
404414 if sys .isctime ():
405- features = np .concatenate ((features , np .abs (sys .pole ())))
406- features = np .concatenate ((features , np .abs (sys .zero ())))
415+ features_ = np .abs (sys .pole ())
416+ features_ = np .concatenate ((features_ , np .abs (sys .zero ())))
417+ # Get rid of poles and zeros at the origin
418+ features_ = features_ [features_ != 0.0 ];
419+ features = np .concatenate ((features , features_ ))
407420 elif sys .isdtime (strict = True ):
408421 freq_interesting .append (np .pi * 1. / sys .dt )
409- # TODO: how to determine lowest interesting frequency?
422+ p = sys .pole ()
423+ p = p [p != - 1. ]
424+ features = np .concatenate ((features , np .abs (np .log (p )/ sys .dt )))
425+ z = sys .zero ()
426+ z = z [(z .imag != 0.0 )]
427+ #z = z[(z.imag != 0.0) | (z.real > 0.0)]
428+ features = np .concatenate ((features , np .abs (np .log (z )/ sys .dt )))
410429 else :
411430 pass
412431 # TODO:
413432 except :
414433 pass
415434
416- # Get rid of poles and zeros at the origin
417- features = features [features != 0 ];
418435
419436 # Make sure there is at least one point in the range
420- if (features .shape [0 ] == 0 ): features = [1 ];
421-
437+ if (features .shape [0 ] == 0 ):
438+ features = [1 ];
439+
440+ if Hz :
441+ features /= 2. * np .pi
442+ features = np .log10 (features )
443+ lsp_min = np .floor (np .min (features )) - feature_periphery_decade
444+ lsp_max = np .ceil (np .max (features )) + feature_periphery_decade
445+ lsp_min += np .log10 (2. * np .pi )
446+ lsp_max += np .log10 (2. * np .pi )
447+ else :
422448 # 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?
424- features = np .log10 (features )
425- lsp_min = np .floor (np .min (features ))- 1
426- lsp_max = np .ceil (np .max (features ))+ 1
449+ features = np .log10 (features )
450+ lsp_min = np .floor (np .min (features )) - feature_periphery_decade
451+ lsp_max = np .ceil (np .max (features )) + feature_periphery_decade
427452 if freq_interesting :
428453 lsp_min = min (lsp_min , np .log10 (min (freq_interesting )))
429454 lsp_max = max (lsp_max , np .log10 (max (freq_interesting )))
430455
431- #! TODO: Add a check in discrete case to make sure we don't get aliasing
456+ #! TODO: Add a check in discrete case to make sure we don't get aliasing (Attention: there is a list of system but only one omega vector)
432457
433458 # Set the range to be an order of magnitude beyond any features
434459 if number_of_samples :
435- omega = sp .logspace (lsp_min , lsp_max , num = number_of_samples , endpoint = False )
460+ omega = sp .logspace (lsp_min , lsp_max , num = number_of_samples , endpoint = True )
436461 else :
437- omega = sp .logspace (lsp_min , lsp_max , endpoint = False )
438-
439-
440-
462+ omega = sp .logspace (lsp_min , lsp_max , endpoint = True )
441463 return omega
442464
443465#
0 commit comments