Repository: python-control/python-control
Pull request #989 (2024-04-05 04:50:23)

Update documentation, processing of root_locus kvect keyword
This PR addresses issue #987, which was partially fixed in #988, by consistently using the keyword `gains` instead of `kvect` in the root locus commands.  In addition, if the `kvect` keyword is used, a warning is generated indicating that `kvect` has been deprecated and `gains` should be used instead.

Also include some minor reformatting of docstrings in rlocus.py.




Patch:
diff --git a/control/rlocus.py b/control/rlocus.py
index b3c14123..631185cc 100644
--- a/control/rlocus.py
+++ b/control/rlocus.py
@@ -42,15 +42,15 @@ def root_locus_map(sysdata, gains=None):
     """Compute the root locus map for an LTI system.
 
     Calculate the root locus by finding the roots of 1 + k * G(s) where G
-    is a linear system with transfer function num(s)/den(s) and each k is
-    an element of kvect.
+    is a linear system and k varies over a range of gains.
 
     Parameters
     ----------
     sys : LTI system or list of LTI systems
         Linear input/output systems (SISO only, for now).
     gains : array_like, optional
-        Gains to use in computing plot of closed-loop poles.
+        Gains to use in computing plot of closed-loop poles.  If not given,
+        gains are chosen to include the main features of the root locus map.
 
     Returns
     -------
@@ -98,20 +98,20 @@ def root_locus_map(sysdata, gains=None):
 
 
 def root_locus_plot(
-        sysdata, kvect=None, grid=None, plot=None, **kwargs):
+        sysdata, gains=None, grid=None, plot=None, **kwargs):
 
     """Root locus plot.
 
     Calculate the root locus by finding the roots of 1 + k * G(s) where G
-    is a linear system with transfer function num(s)/den(s) and each k is
-    an element of kvect.
+    is a linear system and k varies over a range of gains.
 
     Parameters
     ----------
     sysdata : PoleZeroMap or LTI object or list
         Linear input/output systems (SISO only, for now).
-    kvect : array_like, optional
-        Gains to use in computing plot of closed-loop poles.
+    gains : array_like, optional
+        Gains to use in computing plot of closed-loop poles.  If not given,
+        gains are chosen to include the main features of the root locus map.
     xlim : tuple or list, optional
         Set limits of x axis, normally with tuple
         (see :doc:`matplotlib:api/axes_api`).
@@ -145,10 +145,9 @@ def root_locus_plot(
         * lines[idx, 2]: loci
 
     roots, gains : ndarray
-        (legacy) If the `plot` keyword is given, returns the
-        closed-loop root locations, arranged such that each row
-        corresponds to a gain in gains, and the array of gains (ame as
-        kvect keyword argument if provided).
+        (legacy) If the `plot` keyword is given, returns the closed-loop
+        root locations, arranged such that each row corresponds to a gain,
+        and the array of gains (same as `gains` keyword argument if provided).
 
     Notes
     -----
@@ -160,13 +159,16 @@ def root_locus_plot(
     """
     from .pzmap import pole_zero_plot
 
+    # Legacy parameters
+    gains = config._process_legacy_keyword(kwargs, 'kvect', 'gains', gains)
+
     # Set default parameters
     grid = config._get_param('rlocus', 'grid', grid, _rlocus_defaults)
 
     if isinstance(sysdata, list) and all(
             [isinstance(sys, LTI) for sys in sysdata]) or \
             isinstance(sysdata, LTI):
-        responses = root_locus_map(sysdata, gains=kvect)
+        responses = root_locus_map(sysdata, gains=gains)
     else:
         responses = sysdata
 


Test patch:
diff --git a/control/tests/rlocus_test.py b/control/tests/rlocus_test.py
index 5511f5b8..0b3e868e 100644
--- a/control/tests/rlocus_test.py
+++ b/control/tests/rlocus_test.py
@@ -180,6 +180,13 @@ def test_root_locus_plots(sys, grid, xlim, ylim, interactive):
     # TODO: add tests to make sure everything "looks" OK
 
 
+# Test deprecated keywords
+def test_root_locus_legacy():
+    sys = ct.rss(2, 1, 1)
+    with pytest.warns(DeprecationWarning, match="'kvect' is deprecated"):
+        ct.root_locus_plot(sys, kvect=[0, 1, 2])
+
+
 # Generate plots used in documentation
 def test_root_locus_documentation(savefigs=False):
     plt.figure()