8000 Merge pull request #790 from murrayrm/fix_isstatic-12Nov2022 · python-control/python-control@5180c7b · GitHub
[go: up one dir, main page]

Skip to content

Commit 5180c7b

Browse files
Merge pull request #790 from murrayrm/fix_isstatic-12Nov2022
fix _isstatic() to use nstates==0
2 parents b32e355 + c82605b commit 5180c7b

File tree

3 files changed

+25
-29
lines changed

3 files changed

+25
-29
lines changed

control/statesp.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def __init__(self, *args, init_namedio=True, **kwargs):
326326
D = np.zeros((C.shape[0], B.shape[1]))
327327
D = _ssmatrix(D)
328328

329-
# Matrices definining the linear system
329+
# Matrices defining the linear system
330330
self.A = A
331331
self.B = B
332332
self.C = C
@@ -346,9 +346,8 @@ def __init__(self, *args, init_namedio=True, **kwargs):
346346
defaults = args[0] if len(args) == 1 else \
347347
{'inputs': D.shape[1], 'outputs': D.shape[0],
348348
'states': A.shape[0]}
349-
static = (A.size == 0)
350349
name, inputs, outputs, states, dt = _process_namedio_keywords(
351-
kwargs, defaults, static=static, end=True)
350+
kwargs, defaults, static=(A.size == 0), end=True)
352351

353352
# Initialize LTI (NamedIOSystem) object
354353
super().__init__(
@@ -1484,11 +1483,6 @@ def output(self, t, x, u=None, params=None):
14841483
return (self.C @ x).reshape((-1,)) \
14851484
+ (self.D @ u).reshape((-1,)) # return as row vector
14861485

1487-
def _isstatic(self):
1488-
"""True if and only if the system has no dynamics, that is,
1489-
if A and B are zero. """
1490-
return not np.any(self.A) and not np.any(self.B)
1491-
14921486

14931487
# TODO: add discrete time check
14941488
def _convert_to_statespace(sys):

control/tests/iosys_test.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class TSys:
4141
[[-1, 1], [0, -2]], [[0, 1], [1, 0]],
4242
[[1, 0], [0, 1]], np.zeros((2, 2)))
4343

44+
# Create a static gain linear system
45+
T.staticgain = ct.StateSpace([], [], [], 1)
46+
4447
# Create simulation parameters
4548
T.T = np.linspace(0, 10, 100)
4649
T.U = np.sin(T.T)
@@ -51,7 +54,7 @@ class TSys:
5154
def test_linear_iosys(self, tsys):
5255
# Create an input/output system from the linear system
5356
linsys = tsys.siso_linsys
54-
iosys = ios.LinearIOSystem(linsys)
57+
iosys = ios.LinearIOSystem(linsys).copy()
5558

5659
# Make sure that the right hand side matches linear system
5760
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):
6669
np.testing.assert_array_almost_equal(lti_t, ios_t)
6770
np.testing.assert_allclose(lti_y, ios_y, atol=0.002, rtol=0.)
6871

72+
# Make sure that a static linear system has dt=None
73+
# and otherwise dt is as specified
74+
assert ios.LinearIOSystem(tsys.staticgain).dt is None
75+
assert ios.LinearIOSystem(tsys.staticgain, dt=.1).dt == .1
76+
6977
def test_tf2io(self, tsys):
7078
# Create a transfer function from the state space system
7179
linsys = tsys.siso_linsys

control/tests/statesp_test.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -399,25 +399,6 @@ def test_freq_resp(self):
399399
mag, phase, omega = sys.freqresp(true_omega)
400400
np.testing.assert_almost_equal(mag, true_mag)
401401

402-
def test__isstatic(self):
403-
A0 = np.zeros((2,2))
404-
A1 = A0.copy()
405-
A1[0,1] = 1.1
406-
B0 = np.zeros((2,1))
407-
B1 = B0.copy()
408-
B1[0,0] = 1.3
409-
C0 = A0
410-
C1 = np.eye(2)
411-
D0 = 0
412-
D1 = np.ones((2,1))
413-
assert StateSpace(A0, B0, C1, D1)._isstatic()
414-
assert not StateSpace(A1, B0, C1, D1)._isstatic()
415-
assert not StateSpace(A0, B1, C1, D1)._isstatic()
416-
assert not StateSpace(A1, B1, C1, D1)._isstatic()
417-
assert StateSpace(A0, B0, C0, D0)._isstatic()
418-
assert StateSpace(A0, B0, C0, D1)._isstatic()
419-
assert StateSpace(A0, B0, C1, D0)._isstatic()
420-
421402
@slycotonly
422403
def test_minreal(self):
423404
"""Test a minreal model reduction."""
@@ -1160,6 +1141,20 @@ def test_linfnorm_ct_mimo(self, ct_siso):
11601141
np.testing.assert_allclose(fpeak, reffpeak)
11611142

11621143

1144+
@pytest.mark.parametrize("args, static", [
1145+
(([], [], [], 1), True), # ctime, empty state
1146+
(([], [], [], 1, 1), True), # dtime, empty state
1147+
((0, 0, 0, 1), False), # ctime, unused state
1148+
((-1, 0, 0, 1), False), # ctime, exponential decay
1149+
((-1, 0, 0, 0), False), # ctime, no input, no output
1150+
((0, 0, 0, 1, 1), False), # dtime, integrator
1151+
((1, 0, 0, 1, 1), False), # dtime, unused state
1152+
((0, 0, 0, 1, None), False), # unspecified, unused state
1153+
])
1154+
def test_isstatic(args, static):
1155+
sys = ct.StateSpace(*args)
1156+
assert sys._isstatic() == static
1157+
11631158
# Make sure that using params for StateSpace objects generates a warning
11641159
def test_params_warning():
11651160
sys = StateSpace(-1, 1, 1, 0)
@@ -1169,4 +1164,3 @@ def test_params_warning():
11691164

11701165
with pytest.warns(UserWarning, match="params keyword ignored"):
11711166
sys.output(0, [0], [0], {'k': 5})
1172-

0 commit comments

Comments
 (0)
0