Skip to content

Commit 91c0260

Browse files
murrayrmbnavigator
authored andcommitted
add support for 1D gain scheduling
1 parent a3cffd7 commit 91c0260

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

control/statefbk.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,10 @@ def create_statefbk_iosystem(
826826
gainsched_indices = range(sys.nstates) if gainsched_indices is None \
827827
else list(gainsched_indices)
828828

829+
# If points is a 1D list, convert to 2D
830+
if points.ndim == 1:
831+
points = points.reshape(-1, 1)
832+
829833
# Make sure the scheduling variable indices are the right length
830834
if len(gainsched_indices) != points.shape[1]:
831835
raise ControlArgument(
@@ -838,7 +842,12 @@ def create_statefbk_iosystem(
838842
gainsched_indices[i] = inputs.index(gainsched_indices[i])
839843

840844
# Create interpolating function
841-
if gainsched_method == 'nearest':
845+
if points.shape[1] < 2:
846+
_interp = sp.interpolate.interp1d(
847+
points[:, 0], gains, axis=0, kind=gainsched_method)
848+
_nearest = sp.interpolate.interp1d(
849+
points[:, 0], gains, axis=0, kind='nearest')
850+
elif gainsched_method == 'nearest':
842851
_interp = sp.interpolate.NearestNDInterpolator(points, gains)
843852
def _nearest(mu):
844853
raise SystemError(f"could not find nearest gain at mu = {mu}")

control/tests/statefbk_test.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,34 @@ def test_gainsched_unicycle(unicycle, method):
924924
resp.states[:, -1], Xd[:, -1], atol=1e-2, rtol=1e-2)
925925

926926

927+
@pytest.mark.parametrize("method", ['nearest', 'linear', 'cubic'])
928+
def test_gainsched_1d(method):
929+
# Define a linear system to test
930+
sys = ct.ss([[-1, 0.1], [0, -2]], [[0], [1]], np.eye(2), 0)
931+
932+
# Define gains for the first state only
933+
points = [-1, 0, 1]
934+
935+
# Define gain to be constant
936+
K, _, _ = ct.lqr(sys, np.eye(sys.nstates), np.eye(sys.ninputs))
937+
gains = [K for p in points]
938+
939+
# Define the paramters for the simulations
940+
timepts = np.linspace(0, 10, 100)
941+
X0 = np.ones(sys.nstates) * 1.1 # Start outside defined range
942+
943+
# Create a controller and simulate the initial response
944+
gs_ctrl, gs_clsys = ct.create_statefbk_iosystem(
945+
sys, (gains, points), gainsched_indices=[0])
946+
gs_resp = ct.input_output_response(gs_clsys, timepts, 0, X0)
947+
948+
# Verify that we get the same result as a constant gain
949+
ck_clsys = ct.ss(sys.A - sys.B @ K, sys.B, sys.C, 0)
950+
ck_resp = ct.input_output_response(ck_clsys, timepts, 0, X0)
951+
952+
np.testing.assert_allclose(gs_resp.states, ck_resp.states)
953+
954+
927955
def test_gainsched_default_indices():
928956
# Define a linear system to test
929957
sys = ct.ss([[-1, 0.1], [0, -2]], [[0], [1]], np.eye(2), 0)
@@ -937,7 +965,7 @@ def test_gainsched_default_indices():
937965

938966
# Define the paramters for the simulations
939967
timepts = np.linspace(0, 10, 100)
940-
X0 = np.ones(sys.nstates) * 0.9
968+
X0 = np.ones(sys.nstates) * 1.1 # Start outside defined range
941969

942970
# Create a controller and simulate the initial response
943971
gs_ctrl, gs_clsys = ct.create_statefbk_iosystem(sys, (gains, points))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy