Merge pull request #997 from wueestry/nyquist_improvements · python-control/python-control@4acc78b

@@ -1060,7 +1060,9 @@ def gen_zero_centered_series(val_min, val_max, period):

10601060

'nyquist.max_curve_magnitude': 20, # clip large values

10611061

'nyquist.max_curve_offset': 0.02, # offset of primary/mirror

10621062

'nyquist.start_marker': 'o', # marker at start of curve

1063-

'nyquist.start_marker_size': 4, # size of the maker

1063+

'nyquist.start_marker_size': 4, # size of the marker

1064+

'nyquist.circle_style': # style for unit circles

1065+

{'color': 'black', 'linestyle': 'dashed', 'linewidth': 1}

10641066

}

1065106710661068

@@ -1477,8 +1479,8 @@ def nyquist_response(

1477147914781480

def nyquist_plot(

14791481

data, omega=None, plot=None, label_freq=0, color=None, label=None,

1480-

return_contour=None, title=None, legend_loc='upper right',

1481-

ax=None, **kwargs):

1482+

return_contour=None, title=None, legend_loc='upper right', ax=None,

1483+

unit_circle=False, mt_circles=None, ms_circles=None, **kwargs):

14821484

"""Nyquist plot for a system.

1483148514841486

Generates a Nyquist plot for the system over a (optional) frequency

@@ -1501,7 +1503,13 @@ def nyquist_plot(

15011503

``omega_limits``.

15021504

color : string, optional

15031505

Used to specify the color of the line and arrowhead.

1504-1506+

unit_circle : bool, optional

1507+

If ``True``, display the unit circle, to read gain crossover frequency.

1508+

mt_circles : array_like, optional

1509+

Draw circles corresponding to the given magnitudes of sensitivity.

1510+

ms_circles : array_like, optional

1511+

Draw circles corresponding to the given magnitudes of complementary

1512+

sensitivity.

15051513

**kwargs : :func:`matplotlib.pyplot.plot` keyword properties, optional

15061514

Additional keywords (passed to `matplotlib`)

15071515

@@ -1856,7 +1864,48 @@ def _parse_linestyle(style_name, allow_false=False):

18561864

# Mark the -1 point

18571865

plt.plot([-1], [0], 'r+')

185818661859-

# Label the frequencies of the points

1867+

#

1868+

# Draw circles for gain crossover and sensitivity functions

1869+

#

1870+

theta = np.linspace(0, 2*np.pi, 100)

1871+

cos = np.cos(theta)

1872+

sin = np.sin(theta)

1873+

label_pos = 15

1874+1875+

# Display the unit circle, to read gain crossover frequency

1876+

if unit_circle:

1877+

plt.plot(cos, sin, **config.defaults['nyquist.circle_style'])

1878+1879+

# Draw circles for given magnitudes of sensitivity

1880+

if ms_circles is not None:

1881+

for ms in ms_circles:

1882+

pos_x = -1 + (1/ms)*cos

1883+

pos_y = (1/ms)*sin

1884+

plt.plot(

1885+

pos_x, pos_y, **config.defaults['nyquist.circle_style'])

1886+

plt.text(pos_x[label_pos], pos_y[label_pos], ms)

1887+1888+

# Draw circles for given magnitudes of complementary sensitivity

1889+

if mt_circles is not None:

1890+

for mt in mt_circles:

1891+

if mt != 1:

1892+

ct = -mt**2/(mt**2-1) # Mt center

1893+

rt = mt/(mt**2-1) # Mt radius

1894+

pos_x = ct+rt*cos

1895+

pos_y = rt*sin

1896+

plt.plot(

1897+

pos_x, pos_y,

1898+

**config.defaults['nyquist.circle_style'])

1899+

plt.text(pos_x[label_pos], pos_y[label_pos], mt)

1900+

else:

1901+

_, _, ymin, ymax = plt.axis()

1902+

pos_y = np.linspace(ymin, ymax, 100)

1903+

plt.vlines(

1904+

-0.5, ymin=ymin, ymax=ymax,

1905+

**config.defaults['nyquist.circle_style'])

1906+

plt.text(-0.5, pos_y[label_pos], 1)

1907+1908+

# Label the frequencies of the points on the Nyquist curve

18601909

if label_freq:

18611910

ind = slice(None, None, label_freq)

18621911

omega_sys = np.imag(splane_contour[np.real(splane_contour) == 0])