@@ -1060,7 +1060,9 @@ def gen_zero_centered_series(val_min, val_max, period):
1060
1060
'nyquist.max_curve_magnitude' : 20 , # clip large values
1061
1061
'nyquist.max_curve_offset' : 0.02 , # offset of primary/mirror
1062
1062
'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 }
1064
1066
}
1065
1067
1066
1068
@@ -1477,8 +1479,8 @@ def nyquist_response(
1477
1479
1478
1480
def nyquist_plot (
1479
1481
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 ):
1482
1484
"""Nyquist plot for a system.
1483
1485
1484
1486
Generates a Nyquist plot for the system over a (optional) frequency
@@ -1501,7 +1503,13 @@ def nyquist_plot(
1501
1503
``omega_limits``.
1502
1504
color : string, optional
1503
1505
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.
1505
1513
**kwargs : :func:`matplotlib.pyplot.plot` keyword properties, optional
1506
1514
Additional keywords (passed to `matplotlib`)
1507
1515
@@ -1856,7 +1864,48 @@ def _parse_linestyle(style_name, allow_false=False):
1856
1864
# Mark the -1 point
1857
1865
plt .plot ([- 1 ], [0 ], 'r+' )
1858
1866
1859
- # 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
1860
1909
if label_freq :
1861
1910
ind = slice (None , None , label_freq )
1862
1911
omega_sys = np .imag (splane_contour [np .real (splane_contour ) == 0 ])
0 commit comments