diff --git a/control/statefbk.py b/control/statefbk.py index b6e9c9655..414673fcf 100644 --- a/control/statefbk.py +++ b/control/statefbk.py @@ -251,7 +251,7 @@ def place_acker(A, B, poles): pmat = pmat + p[n-i-1] * np.linalg.matrix_power(A, i) K = np.linalg.solve(ct, pmat) - K = K[-1, :] # Extract the last row + K = K[-1:, :] # Extract the last row return K diff --git a/control/tests/statefbk_test.py b/control/tests/statefbk_test.py index 97cf7be68..d0230fb18 100644 --- a/control/tests/statefbk_test.py +++ b/control/tests/statefbk_test.py @@ -1272,3 +1272,23 @@ def test_create_statefbk_params(unicycle): assert [k for k in clsys.params.keys()] == ['K', 'a', 'b'] assert clsys.params['a'] == 2 assert clsys.params['b'] == 1 + + +@pytest.mark.parametrize('ny, nu', [(1, 1), (2, 2), (2, 1)]) +@pytest.mark.parametrize( + 'method', [ + place, place_acker, + pytest.param(place_varga, marks=pytest.mark.slycot)]) +def test_place_variants(ny, nu, method): + sys = ct.rss(states=2, inputs=nu, outputs=ny) + desired_poles = -np.arange(1, sys.nstates + 1, 1) + + if method == place_acker and sys.ninputs != 1: + with pytest.raises(np.linalg.LinAlgError, match="must be square"): + K = method(sys.A, sys.B, desired_poles) + else: + K = method(sys.A, sys.B, desired_poles) + + placed_poles = np.linalg.eigvals(sys.A - sys.B @ K) + np.testing.assert_array_almost_equal( + np.sort(desired_poles), np.sort(placed_poles))