From c425d2c9312af16eb49c13222f81ce0e94ff7b16 Mon Sep 17 00:00:00 2001 From: Richard Murray Date: Sat, 12 Nov 2022 22:03:18 -0800 Subject: [PATCH] fix _isstatic() to use nstates==0 --- control/statesp.py | 10 ++-------- control/tests/iosys_test.py | 10 +++++++++- control/tests/statesp_test.py | 33 ++++++++++++++------------------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/control/statesp.py b/control/statesp.py index 374b036ca..ca14a5690 100644 --- a/control/statesp.py +++ b/control/statesp.py @@ -326,7 +326,7 @@ def __init__(self, *args, init_namedio=True, **kwargs): D = np.zeros((C.shape[0], B.shape[1])) D = _ssmatrix(D) - # Matrices definining the linear system + # Matrices defining the linear system self.A = A self.B = B self.C = C @@ -346,9 +346,8 @@ def __init__(self, *args, init_namedio=True, **kwargs): defaults = args[0] if len(args) == 1 else \ {'inputs': D.shape[1], 'outputs': D.shape[0], 'states': A.shape[0]} - static = (A.size == 0) name, inputs, outputs, states, dt = _process_namedio_keywords( - kwargs, defaults, static=static, end=True) + kwargs, defaults, static=(A.size == 0), end=True) # Initialize LTI (NamedIOSystem) object super().__init__( @@ -1478,11 +1477,6 @@ def output(self, t, x, u=None): return (self.C @ x).reshape((-1,)) \ + (self.D @ u).reshape((-1,)) # return as row vector - def _isstatic(self): - """True if and only if the system has no dynamics, that is, - if A and B are zero. """ - return not np.any(self.A) and not np.any(self.B) - # TODO: add discrete time check def _convert_to_statespace(sys): diff --git a/control/tests/iosys_test.py b/control/tests/iosys_test.py index 693be979e..8a6ed8165 100644 --- a/control/tests/iosys_test.py +++ b/control/tests/iosys_test.py @@ -41,6 +41,9 @@ class TSys: [[-1, 1], [0, -2]], [[0, 1], [1, 0]], [[1, 0], [0, 1]], np.zeros((2, 2))) + # Create a static gain linear system + T.staticgain = ct.StateSpace([], [], [], 1) + # Create simulation parameters T.T = np.linspace(0, 10, 100) T.U = np.sin(T.T) @@ -51,7 +54,7 @@ class TSys: def test_linear_iosys(self, tsys): # Create an input/output system from the linear system linsys = tsys.siso_linsys - iosys = ios.LinearIOSystem(linsys) + iosys = ios.LinearIOSystem(linsys).copy() # Make sure that the right hand side matches linear system for x, u in (([0, 0], 0), ([1, 0], 0), ([0, 1], 0), ([0, 0], 1)): @@ -66,6 +69,11 @@ def test_linear_iosys(self, tsys): np.testing.assert_array_almost_equal(lti_t, ios_t) np.testing.assert_allclose(lti_y, ios_y, atol=0.002, rtol=0.) + # Make sure that a static linear system has dt=None + # and otherwise dt is as specified + assert ios.LinearIOSystem(tsys.staticgain).dt is None + assert ios.LinearIOSystem(tsys.staticgain, dt=.1).dt == .1 + def test_tf2io(self, tsys): # Create a transfer function from the state space system linsys = tsys.siso_linsys diff --git a/control/tests/statesp_test.py b/control/tests/statesp_test.py index 97dc84e3c..5fe7d36af 100644 --- a/control/tests/statesp_test.py +++ b/control/tests/statesp_test.py @@ -399,25 +399,6 @@ def test_freq_resp(self): mag, phase, omega = sys.freqresp(true_omega) np.testing.assert_almost_equal(mag, true_mag) - def test__isstatic(self): - A0 = np.zeros((2,2)) - A1 = A0.copy() - A1[0,1] = 1.1 - B0 = np.zeros((2,1)) - B1 = B0.copy() - B1[0,0] = 1.3 - C0 = A0 - C1 = np.eye(2) - D0 = 0 - D1 = np.ones((2,1)) - assert StateSpace(A0, B0, C1, D1)._isstatic() - assert not StateSpace(A1, B0, C1, D1)._isstatic() - assert not StateSpace(A0, B1, C1, D1)._isstatic() - assert not StateSpace(A1, B1, C1, D1)._isstatic() - assert StateSpace(A0, B0, C0, D0)._isstatic() - assert StateSpace(A0, B0, C0, D1)._isstatic() - assert StateSpace(A0, B0, C1, D0)._isstatic() - @slycotonly def test_minreal(self): """Test a minreal model reduction.""" @@ -1158,3 +1139,17 @@ def test_linfnorm_ct_mimo(self, ct_siso): gpeak, fpeak = linfnorm(sys) np.testing.assert_allclose(gpeak, refgpeak) np.testing.assert_allclose(fpeak, reffpeak) + +@pytest.mark.parametrize("args, static", [ + (([], [], [], 1), True), # ctime, empty state + (([], [], [], 1, 1), True), # dtime, empty state + ((0, 0, 0, 1), False), # ctime, unused state + ((-1, 0, 0, 1), False), # ctime, exponential decay + ((-1, 0, 0, 0), False), # ctime, no input, no output + ((0, 0, 0, 1, 1), False), # dtime, integrator + ((1, 0, 0, 1, 1), False), # dtime, unused state + ((0, 0, 0, 1, None), False), # unspecified, unused state +]) +def test_isstatic(args, static): + sys = ct.StateSpace(*args) + assert sys._isstatic() == static 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