2424from .iosys import isdtime
2525from .xferfcn import _convert_to_transfer_function
2626from .exception import ControlMIMONotImplemented
27- from .grid import sgrid , zgrid
2827from . import config
2928import warnings
3029
@@ -96,19 +95,25 @@ def root_locus_plot(
9695 (see :doc:`matplotlib:api/axes_api`).
9796 plotstr : :func:`matplotlib.pyplot.plot` format string, optional
9897 plotting style specification
98+ TODO: check
9999 plot : boolean, optional
100100 If True (default), plot root locus diagram.
101+ TODO: legacy
101102 print_gain : bool
102103 If True (default), report mouse clicks when close to the root locus
103104 branches, calculate gain, damping and print.
104- grid : bool
105- If True plot omega-damping grid. Default is False.
105+ TODO: update
106+ grid : bool or str, optional
107+ If `True` plot omega-damping grid, if `False` show imaginary axis
108+ for continuous time systems, unit circle for discrete time systems.
109+ If `empty`, do not draw any additonal lines. Default value is set
110+ by config.default['rlocus.grid'].
106111 ax : :class:`matplotlib.axes.Axes`
107112 Axes on which to create root locus plot
108113 initial_gain : float, optional
109114 Specify the initial gain to use when marking current gain. [TODO: update]
110115
111- Returns
116+ Returns (TODO: update)
112117 -------
113118 roots : ndarray
114119 Closed-loop root locations, arranged in which each row corresponds
@@ -156,8 +161,7 @@ def root_locus_plot(
156161 return out
157162
158163
159- # TODO: get rid of zoom functionality?
160- def _default_gains (num , den , xlim , ylim , zoom_xlim = None , zoom_ylim = None ):
164+ def _default_gains (num , den , xlim , ylim ):
161165 """Unsupervised gains calculation for root locus plot.
162166
163167 References
@@ -237,8 +241,7 @@ def _default_gains(num, den, xlim, ylim, zoom_xlim=None, zoom_ylim=None):
237241 tolerance = x_tolerance
238242 else :
239243 tolerance = np .min ([x_tolerance , y_tolerance ])
240- indexes_too_far = _indexes_filt (
241- root_array , tolerance , zoom_xlim , zoom_ylim )
244+ indexes_too_far = _indexes_filt (root_array , tolerance )
242245
243246 # Add more points into the root locus for points that are too far apart
244247 while len (indexes_too_far ) > 0 and kvect .size < 5000 :
@@ -250,8 +253,7 @@ def _default_gains(num, den, xlim, ylim, zoom_xlim=None, zoom_ylim=None):
250253 root_array = np .insert (root_array , index + 1 , new_points , axis = 0 )
251254
252255 root_array = _RLSortRoots (root_array )
253- indexes_too_far = _indexes_filt (
254- root_array , tolerance , zoom_xlim , zoom_ylim )
256+ indexes_too_far = _indexes_filt (root_array , tolerance )
255257
256258 new_gains = kvect [- 1 ] * np .hstack ((np .logspace (0 , 3 , 4 )))
257259 new_points = _RLFindRoots (num , den , new_gains [1 :4 ])
@@ -261,7 +263,7 @@ def _default_gains(num, den, xlim, ylim, zoom_xlim=None, zoom_ylim=None):
261263 return kvect , root_array , xlim , ylim
262264
263265
264- def _indexes_filt (root_array , tolerance , zoom_xlim = None , zoom_ylim = None ):
266+ def _indexes_filt (root_array , tolerance ):
265267 """Calculate the distance between points and return the indices.
266268
267269 Filter the indexes so only the resolution of points within the xlim and
@@ -270,48 +272,6 @@ def _indexes_filt(root_array, tolerance, zoom_xlim=None, zoom_ylim=None):
270272 """
271273 distance_points = np .abs (np .diff (root_array , axis = 0 ))
272274 indexes_too_far = list (np .unique (np .where (distance_points > tolerance )[0 ]))
273-
274- if zoom_xlim is not None and zoom_ylim is not None :
275- x_tolerance_zoom = 0.05 * (zoom_xlim [1 ] - zoom_xlim [0 ])
276- y_tolerance_zoom = 0.05 * (zoom_ylim [1 ] - zoom_ylim [0 ])
277- tolerance_zoom = np .min ([x_tolerance_zoom , y_tolerance_zoom ])
278- indexes_too_far_zoom = list (
279- np .unique (np .where (distance_points > tolerance_zoom )[0 ]))
280- indexes_too_far_filtered = []
281-
282- for index in indexes_too_far_zoom :
283- for point in root_array [index ]:
284- if (zoom_xlim [0 ] <= point .real <= zoom_xlim [1 ]) and \
285- (zoom_ylim [0 ] <= point .imag <= zoom_ylim [1 ]):
286- indexes_too_far_filtered .append (index )
287- break
288-
289- # Check if zoom box is not overshot & insert points where neccessary
290- if len (indexes_too_far_filtered ) == 0 and len (root_array ) < 500 :
291- limits = [zoom_xlim [0 ], zoom_xlim [1 ], zoom_ylim [0 ], zoom_ylim [1 ]]
292- for index , limit in enumerate (limits ):
293- if index <= 1 :
294- asign = np .sign (real (root_array )- limit )
295- else :
296- asign = np .sign (imag (root_array ) - limit )
297- signchange = ((np .roll (asign , 1 , axis = 0 )
298- - asign ) != 0 ).astype (int )
299- signchange [0 ] = np .zeros ((len (root_array [0 ])))
300- if len (np .where (signchange == 1 )[0 ]) > 0 :
301- indexes_too_far_filtered .append (
302- np .where (signchange == 1 )[0 ][0 ]- 1 )
303-
304- if len (indexes_too_far_filtered ) > 0 :
305- if indexes_too_far_filtered [0 ] != 0 :
306- indexes_too_far_filtered .insert (
307- 0 , indexes_too_far_filtered [0 ]- 1 )
308- if not indexes_too_far_filtered [- 1 ] + 1 >= len (root_array ) - 2 :
309- indexes_too_far_filtered .append (
310- indexes_too_far_filtered [- 1 ] + 1 )
311-
312- indexes_too_far .extend (indexes_too_far_filtered )
313-
314- indexes_too_far = list (np .unique (indexes_too_far ))
315275 indexes_too_far .sort ()
316276 return indexes_too_far
317277
0 commit comments