Skip to content

Commit 73ce1a6

Browse files
committed
allow specified frequency range to exceed nyquist frequency if desired
1 parent 24d57e1 commit 73ce1a6

File tree

1 file changed

+48
-36
lines changed

1 file changed

+48
-36
lines changed

control/freqplot.py

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -194,28 +194,25 @@ def bode_plot(syslist, omega=None,
194194
if not hasattr(syslist, '__iter__'):
195195
syslist = (syslist,)
196196

197+
# decide whether to go above nyquist. freq
198+
omega_range_given = True if omega is not None else False
197199

198200
if omega is None:
199-
omega_was_given = False # used do decide whether to include nyq. freq
201+
omega_num = config._get_param('freqplot','number_of_samples', omega_num)
200202
if omega_limits is None:
201203
# Select a default range if none is provided
202-
omega = _default_frequency_range(syslist, Hz=Hz,
203-
number_of_samples=omega_num)
204+
omega = _default_frequency_range(syslist,
205+
number_of_samples=omega_num)
204206
else:
207+
omega_range_given = True
205208
omega_limits = np.asarray(omega_limits)
206209
if len(omega_limits) != 2:
207210
raise ValueError("len(omega_limits) must be 2")
208211
if Hz:
209212
omega_limits *= 2. * math.pi
210-
if omega_num:
211-
num = omega_num
212-
else:
213-
num = config.defaults['freqplot.number_of_samples']
214213
omega = np.logspace(np.log10(omega_limits[0]),
215-
np.log10(omega_limits[1]), num=num,
214+
np.log10(omega_limits[1]), num=omega_num,
216215
endpoint=True)
217-
else:
218-
omega_was_given = True
219216

220217
if plot:
221218
# Set up the axes with labels so that multiple calls to
@@ -264,12 +261,11 @@ def bode_plot(syslist, omega=None,
264261
else:
265262
omega_sys = np.asarray(omega)
266263
if sys.isdtime(strict=True):
267-
nyquistfrq = 2. * math.pi * 1. / sys.dt / 2.
268-
if not omega_was_given:
269-
# include nyquist frequency
264+
nyquistfrq = math.pi / sys.dt
265+
if not omega_range_given:
266+
# limit up to and including nyquist frequency
270267
omega_sys = np.hstack((
271-
omega_sys[omega_sys < nyquistfrq],
272-
nyquistfrq))
268+
omega_sys[omega_sys < nyquistfrq], nyquistfrq))
273269
else:
274270
nyquistfrq = None
275271

@@ -332,21 +328,27 @@ def bode_plot(syslist, omega=None,
332328
nyquistfrq_plot = nyquistfrq
333329
phase_plot = phase * 180. / math.pi if deg else phase
334330
mag_plot = mag
335-
#
336-
# Magnitude plot
337-
#
338331

339332
if nyquistfrq_plot:
340-
# add data for vertical nyquist freq indicator line
341-
# so it is a single plot action. This preserves line
342-
# order when creating legend eg. legend('sys1', 'sys2)
343-
omega_plot = np.hstack((omega_plot, nyquistfrq,nyquistfrq))
344-
mag_plot = np.hstack((mag_plot,
345-
0.7*min(mag_plot),1.3*max(mag_plot)))
333+
# append data for vertical nyquist freq indicator line.
334+
# if this extra nyquist lime is is plotted in a single plot
335+
# command then line order is preserved when
336+
# creating a legend eg. legend(('sys1', 'sys2'))
337+
omega_nyq_line = np.array((np.nan, nyquistfrq, nyquistfrq))
338+
omega_plot = np.hstack((omega_plot, omega_nyq_line))
339+
mag_nyq_line = np.array((
340+
np.nan, 0.7*min(mag_plot), 1.3*max(mag_plot)))
341+
mag_plot = np.hstack((mag_plot, mag_nyq_line))
346342
phase_range = max(phase_plot) - min(phase_plot)
347-
phase_plot = np.hstack((phase_plot,
343+
phase_nyq_line = np.array((np.nan,
348344
min(phase_plot) - 0.2 * phase_range,
349345
max(phase_plot) + 0.2 * phase_range))
346+
phase_plot = np.hstack((phase_plot, phase_nyq_line))
347+
348+
#
349+
# Magnitude plot
350+
#
351+
350352
if dB:
351353
ax_mag.semilogx(omega_plot, 20 * np.log10(mag_plot),
352354
*args, **kwargs)
@@ -535,8 +537,8 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
535537
omega : array_like
536538
Set of frequencies to be evaluated in rad/sec.
537539
omega_limits : array_like of two values
538-
Limits to the range of frequencies. Ignored if omega
539-
is provided, and auto-generated if omitted.
540+
Limits to the range of frequencies. Ignored if omega
541+
is provided, and auto-generated if omitted.
540542
omega_num : int
541543
Number of samples to plot. Defaults to
542544
config.defaults['freqplot.number_of_samples'].
@@ -588,33 +590,43 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
588590
if not hasattr(syslist, '__iter__'):
589591
syslist = (syslist,)
590592

591-
# Select a default range if none is provided
593+
# decide whether to go above nyquist. freq
594+
omega_range_given = True if omega is not None else False
595+
592596
if omega is None:
597+
omega_num = config._get_param('freqplot','number_of_samples',omega_num)
593598
if omega_limits is None:
594599
# Select a default range if none is provided
595-
omega = _default_frequency_range(syslist, Hz=False,
596-
number_of_samples=omega_num)
600+
omega = _default_frequency_range(syslist,
601+
number_of_samples=omega_num)
597602
else:
603+
omega_range_given = True
598604
omega_limits = np.asarray(omega_limits)
599605
if len(omega_limits) != 2:
600606
raise ValueError("len(omega_limits) must be 2")
601-
num = \
602-
ct.config._get_param('freqplot','number_of_samples', omega_num)
603607
omega = np.logspace(np.log10(omega_limits[0]),
604-
np.log10(omega_limits[1]), num=num,
608+
np.log10(omega_limits[1]), num=omega_num,
605609
endpoint=True)
606610

607611
xs, ys, omegas = [], [], []
608612
for sys in syslist:
609-
mag, phase, omega = sys.frequency_response(omega)
613+
omega_sys = np.asarray(omega)
614+
if sys.isdtime(strict=True):
615+
nyquistfrq = math.pi / sys.dt
616+
if not omega_range_given:
617+
# limit up to and including nyquist frequency
618+
omega_sys = np.hstack((
619+
omega_sys[omega_sys < nyquistfrq], nyquistfrq))
620+
621+
mag, phase, omega_sys = sys.frequency_response(omega_sys)
610622

611623
# Compute the primary curve
612624
x = mag * np.cos(phase)
613625
y = mag * np.sin(phase)
614626

615627
xs.append(x)
616628
ys.append(y)
617-
omegas.append(omega)
629+
omegas.append(omega_sys)
618630

619631
if plot:
620632
if not sys.issiso():
@@ -642,7 +654,7 @@ def nyquist_plot(syslist, omega=None, plot=True, omega_limits=None,
642654
# Label the frequencies of the points
643655
if label_freq:
644656
ind = slice(None, None, label_freq)
645-
for xpt, ypt, omegapt in zip(x[ind], y[ind], omega[ind]):
657+
for xpt, ypt, omegapt in zip(x[ind], y[ind], omega_sys[ind]):
646658
# Convert to Hz
647659
f = omegapt / (2 * np.pi)
648660

0 commit comments

Comments
 (0)