Skip to content

Commit 4d878a9

Browse files
authored
Merge pull request #969 from basicmachines/main
Updated gram to support discrete-time systems
2 parents 7a70be1 + 0836ad8 commit 4d878a9

File tree

2 files changed

+78
-18
lines changed

2 files changed

+78
-18
lines changed

control/statefbk.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,18 +1119,21 @@ def gram(sys, type):
11191119
if type not in ['c', 'o', 'cf', 'of']:
11201120
raise ValueError("That type is not supported!")
11211121

1122-
# TODO: Check for continuous or discrete, only continuous supported for now
1123-
# if isCont():
1124-
# dico = 'C'
1125-
# elif isDisc():
1126-
# dico = 'D'
1127-
# else:
1128-
dico = 'C'
1129-
1130-
# TODO: Check system is stable, perhaps a utility in ctrlutil.py
1131-
# or a method of the StateSpace class?
1132-
if np.any(np.linalg.eigvals(sys.A).real >= 0.0):
1133-
raise ValueError("Oops, the system is unstable!")
1122+
# Check if system is continuous or discrete
1123+
if sys.isctime():
1124+
dico = 'C'
1125+
1126+
# TODO: Check system is stable, perhaps a utility in ctrlutil.py
1127+
# or a method of the StateSpace class?
1128+
if np.any(np.linalg.eigvals(sys.A).real >= 0.0):
1129+
raise ValueError("Oops, the system is unstable!")
1130+
1131+
else:
1132+
assert sys.isdtime()
1133+
dico = 'D'
1134+
1135+
if np.any(np.abs(sys.poles()) >= 1.):
1136+
raise ValueError("Oops, the system is unstable!")
11341137

11351138
if type == 'c' or type == 'o':
11361139
# Compute Gramian by the Slycot routine sb03md

control/tests/statefbk_test.py

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,28 @@ def testGramWc(self):
9898
Wctrue = np.array([[18.5, 24.5], [24.5, 32.5]])
9999
Wc = gram(sys, 'c')
100100
np.testing.assert_array_almost_equal(Wc, Wctrue)
101+
sysd = ct.c2d(sys, 0.2)
102+
Wctrue = np.array([[3.666767, 4.853625],
103+
[4.853625, 6.435233]])
104+
Wc = gram(sysd, 'c')
105+
np.testing.assert_array_almost_equal(Wc, Wctrue)
106+
107+
@slycotonly
108+
def testGramWc2(self):
109+
A = np.array([[1., -2.], [3., -4.]])
110+
B = np.array([[5.], [7.]])
111+
C = np.array([[6., 8.]])
112+
D = np.array([[9.]])
113+
sys = ss(A,B,C,D)
114+
Wctrue = np.array([[ 7.166667, 9.833333],
115+
[ 9.833333, 13.5]])
116+
Wc = gram(sys, 'c')
117+
np.testing.assert_array_almost_equal(Wc, Wctrue)
118+
sysd = ct.c2d(sys, 0.2)
119+
Wctrue = np.array([[1.418978, 1.946180],
120+
[1.946180, 2.670758]])
121+
Wc = gram(sysd, 'c')
122+
np.testing.assert_array_almost_equal(Wc, Wctrue)
101123

102124
@slycotonly
103125
def testGramRc(self):
@@ -106,9 +128,15 @@ def testGramRc(self):
106128
C = np.array([[4., 5.], [6., 7.]])
107129
D = np.array([[13., 14.], [15., 16.]])
108130
sys = ss(A, B, C, D)
109-
Rctrue = np.array([[4.30116263, 5.6961343], [0., 0.23249528]])
131+
Rctrue = np.array([[4.30116263, 5.6961343],
132+
[0., 0.23249528]])
110133
Rc = gram(sys, 'cf')
111134
np.testing.assert_array_almost_equal(Rc, Rctrue)
135+
sysd = ct.c2d(sys, 0.2)
136+
Rctrue = np.array([[1.91488054, 2.53468814],
137+
[0. , 0.10290372]])
138+
Rc = gram(sysd, 'cf')
139+
np.testing.assert_array_almost_equal(Rc, Rctrue)
112140

113141
@slycotonly
114142
def testGramWo(self):
@@ -120,6 +148,11 @@ def testGramWo(self):
120148
Wotrue = np.array([[257.5, -94.5], [-94.5, 56.5]])
121149
Wo = gram(sys, 'o')
122150
np.testing.assert_array_almost_equal(Wo, Wotrue)
151+
sysd = ct.c2d(sys, 0.2)
152+
Wotrue = np.array([[ 1305.369179, -440.046414],
153+
[ -440.046414, 333.034844]])
154+
Wo = gram(sysd, 'o')
155+
np.testing.assert_array_almost_equal(Wo, Wotrue)
123156

124157
@slycotonly
125158
def testGramWo2(self):
@@ -131,6 +164,11 @@ def testGramWo2(self):
131164
Wotrue = np.array([[198., -72.], [-72., 44.]])
132165
Wo = gram(sys, 'o')
133166
np.testing.assert_array_almost_equal(Wo, Wotrue)
167+
sysd = ct.c2d(sys, 0.2)
168+
Wotrue = np.array([[ 1001.835511, -335.337663],
169+
[ -335.337663, 263.355793]])
170+
Wo = gram(sysd, 'o')
171+
np.testing.assert_array_almost_equal(Wo, Wotrue)
134172

135173
@slycotonly
136174
def testGramRo(self):
@@ -142,15 +180,34 @@ def testGramRo(self):
142180
Rotrue = np.array([[16.04680654, -5.8890222], [0., 4.67112593]])
143181
Ro = gram(sys, 'of')
144182
np.testing.assert_array_almost_equal(Ro, Rotrue)
183+
sysd = ct.c2d(sys, 0.2)
184+
Rotrue = np.array([[ 36.12989315, -12.17956588],
185+
[ 0. , 13.59018097]])
186+
Ro = gram(sysd, 'of')
187+
np.testing.assert_array_almost_equal(Ro, Rotrue)
145188

146189
def testGramsys(self):
147-
num =[1.]
148-
den = [1., 1., 1.]
149-
sys = tf(num,den)
150-
with pytest.raises(ValueError):
190+
sys = tf([1.], [1., 1., 1.])
191+
with pytest.raises(ValueError) as excinfo:
151192
gram(sys, 'o')
152-
with pytest.raises(ValueError):
193+
assert "must be StateSpace" in str(excinfo.value)
194+
with pytest.raises(ValueError) as excinfo:
195+
gram(sys, 'c')
196+
assert "must be StateSpace" in str(excinfo.value)
197+
sys = tf([1], [1, -1], 0.5)
198+
with pytest.raises(ValueError) as excinfo:
199+
gram(sys, 'o')
200+
assert "must be StateSpace" in str(excinfo.value)
201+
with pytest.raises(ValueError) as excinfo:
202+
gram(sys, 'c')
203+
assert "must be StateSpace" in str(excinfo.value)
204+
sys = ct.ss(sys) # this system is unstable
205+
with pytest.raises(ValueError) as excinfo:
206+
gram(sys, 'o')
207+
assert "is unstable" in str(excinfo.value)
208+
with pytest.raises(ValueError) as excinfo:
153209
gram(sys, 'c')
210+
assert "is unstable" in str(excinfo.value)
154211

155212
def testAcker(self, fixedseed):
156213
for states in range(1, self.maxStates):

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