Skip to content

Commit 6873c8a

Browse files
committed
Add more tests to statesp.zero
1 parent 8086376 commit 6873c8a

File tree

1 file changed

+78
-40
lines changed

1 file changed

+78
-40
lines changed

control/tests/statesp_test.py

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from numpy.linalg import solve
99
from scipy.linalg import eigvals, block_diag
1010
from control import matlab
11-
from control.statesp import StateSpace, _convertToStateSpace
12-
from control.xferfcn import TransferFunction
11+
from control.statesp import StateSpace, _convertToStateSpace, tf2ss
12+
from control.xferfcn import TransferFunction, ss2tf
1313
from control.lti import evalfr
1414
from control.exception import slycot_check
1515

@@ -20,23 +20,53 @@ class TestStateSpace(unittest.TestCase):
2020
def setUp(self):
2121
"""Set up a MIMO system to test operations on."""
2222

23-
A = [[-3., 4., 2.], [-1., -3., 0.], [2., 5., 3.]]
24-
B = [[1., 4.], [-3., -3.], [-2., 1.]]
25-
C = [[4., 2., -3.], [1., 4., 3.]]
26-
D = [[-2., 4.], [0., 1.]]
27-
28-
a = [[4., 1.], [2., -3]]
29-
b = [[5., 2.], [-3., -3.]]
30-
c = [[2., -4], [0., 1.]]
31-
d = [[3., 2.], [1., -1.]]
32-
33-
self.sys1 = StateSpace(A, B, C, D)
34-
self.sys2 = StateSpace(a, b, c, d)
23+
# sys1: 3-states square system (2 inputs x 2 outputs)
24+
A322 = [[-3., 4., 2.],
25+
[-1., -3., 0.],
26+
[2., 5., 3.]]
27+
B322 = [[1., 4.],
28+
[-3., -3.],
29+
[-2., 1.]]
30+
C322 = [[4., 2., -3.],
31+
[1., 4., 3.]]
32+
D322 = [[-2., 4.],
33+
[0., 1.]]
34+
self.sys322 = StateSpace(A322, B322, C322, D322)
35+
36+
# sys1: 2-states square system (2 inputs x 2 outputs)
37+
A222 = [[4., 1.],
38+
[2., -3]]
39+
B222 = [[5., 2.],
40+
[-3., -3.]]
41+
C222 = [[2., -4],
42+
[0., 1.]]
43+
D222 = [[3., 2.],
44+
[1., -1.]]
45+
self.sys222 = StateSpace(A222, B222, C222, D222)
46+
47+
# sys3: 6 states non square system (2 inputs x 3 outputs)
48+
A623 = np.array([[1, 0, 0, 0, 0, 0],
49+
[0, 1, 0, 0, 0, 0],
50+
[0, 0, 3, 0, 0, 0],
51+
[0, 0, 0, -4, 0, 0],
52+
[0, 0, 0, 0, -1, 0],
53+
[0, 0, 0, 0, 0, 3]])
54+
B623 = np.array([[0, -1],
55+
[-1, 0],
56+
[1, -1],
57+
[0, 0],
58+
[0, 1],
59+
[-1, -1]])
60+
C623 = np.array([[1, 0, 0, 1, 0, 0],
61+
[0, 1, 0, 1, 0, 1],
62+
[0, 0, 1, 0, 0, 1]])
63+
D623 = np.zeros((3, 2))
64+
self.sys623 = StateSpace(A623, B623, C623, D623)
3565

3666
def test_pole(self):
3767
"""Evaluate the poles of a MIMO system."""
3868

39-
p = np.sort(self.sys1.pole())
69+
p = np.sort(self.sys322.pole())
4070
true_p = np.sort([3.34747678408874,
4171
-3.17373839204437 + 1.47492908003839j,
4272
-3.17373839204437 - 1.47492908003839j])
@@ -49,35 +79,43 @@ def test_zero_empty(self):
4979
np.testing.assert_array_equal(sys.zero(), np.array([]))
5080

5181
@unittest.skipIf(not slycot_check(), "slycot not installed")
52-
def test_zero_mimo_non_square(self):
53-
"""Evaluate the zeros of a MIMO system."""
82+
def test_zero_siso(self):
83+
"""Evaluate the zeros of a SISO system."""
84+
# extract only first input / first output system of sys222. This system is denoted sys111
85+
# or tf111
86+
tf111 = ss2tf(self.sys222)
87+
sys111 = tf2ss(tf111[0, 0])
88+
89+
# compute zeros as root of the characteristic polynomial at the numerator of tf111
90+
# this method is simple and assumed as valid in this test
91+
true_z = np.sort(tf111[0, 0].zero())
92+
# Compute the zeros through ab08nd, which is tested here
93+
z = np.sort(sys111.zero())
94+
95+
np.testing.assert_almost_equal(true_z, z)
96+
97+
@unittest.skipIf(not slycot_check(), "slycot not installed")
98+
def test_zero_mimo_sys322_square(self):
99+
"""Evaluate the zeros of a square MIMO system."""
54100

55-
z = np.sort(self.sys1.zero())
101+
z = np.sort(self.sys322.zero())
56102
true_z = np.sort([44.41465, -0.490252, -5.924398])
103+
np.testing.assert_array_almost_equal(z, true_z)
104+
105+
@unittest.skipIf(not slycot_check(), "slycot not installed")
106+
def test_zero_mimo_sys222_square(self):
107+
"""Evaluate the zeros of a square MIMO system."""
57108

109+
z = np.sort(self.sys222.zero())
110+
true_z = np.sort([-10.568501, 3.368501])
58111
np.testing.assert_array_almost_equal(z, true_z)
59112

60-
A = np.array([[1, 0, 0, 0, 0, 0],
61-
[0, 1, 0, 0, 0, 0],
62-
[0, 0, 3, 0, 0, 0],
63-
[0, 0, 0, -4, 0, 0],
64-
[0, 0, 0, 0, -1, 0],
65-
[0, 0, 0, 0, 0, 3]])
66-
B = np.array([[0, -1],
67-
[-1, 0],
68-
[1, -1],
69-
[0, 0],
70-
[0, 1],
71-
[-1, -1]])
72-
C = np.array([[1, 0, 0, 1, 0, 0],
73-
[0, 1, 0, 1, 0, 1],
74-
[0, 0, 1, 0, 0, 1]])
75-
D = np.zeros((3, 2))
76-
sys = StateSpace(A, B, C, D)
113+
@unittest.skipIf(not slycot_check(), "slycot not installed")
114+
def test_zero_mimo_sys623_non_square(self):
115+
"""Evaluate the zeros of a non square MIMO system."""
77116

78-
z = np.sort(sys.zero())
117+
z = np.sort(self.sys623.zero())
79118
true_z = np.sort([2., -1.])
80-
81119
np.testing.assert_array_almost_equal(z, true_z)
82120

83121
def test_add_ss(self):
@@ -89,7 +127,7 @@ def test_add_ss(self):
89127
C = [[4., 2., -3., 2., -4.], [1., 4., 3., 0., 1.]]
90128
D = [[1., 6.], [1., 0.]]
91129

92-
sys = self.sys1 + self.sys2
130+
sys = self.sys322 + self.sys222
93131

94132
np.testing.assert_array_almost_equal(sys.A, A)
95133
np.testing.assert_array_almost_equal(sys.B, B)
@@ -105,7 +143,7 @@ def test_subtract_ss(self):
105143
C = [[4., 2., -3., -2., 4.], [1., 4., 3., 0., -1.]]
106144
D = [[-5., 2.], [-1., 2.]]
107145

108-
sys = self.sys1 - self.sys2
146+
sys = self.sys322 - self.sys222
109147

110148
np.testing.assert_array_almost_equal(sys.A, A)
111149
np.testing.assert_array_almost_equal(sys.B, B)
@@ -121,7 +159,7 @@ def test_multiply_ss(self):
121159
C = [[-4., 12., 4., 2., -3.], [0., 1., 1., 4., 3.]]
122160
D = [[-2., -8.], [1., -1.]]
123161

124-
sys = self.sys1 * self.sys2
162+
sys = self.sys322 * self.sys222
125163

126164
np.testing.assert_array_almost_equal(sys.A, A)
127165
np.testing.assert_array_almost_equal(sys.B, B)

0 commit comments

Comments
 (0)