Skip to content

Commit 7e7ae9c

Browse files
committed
initial commit changing default array type in statespace to be ndarray instead of matrix. two failing unit tests to fix still
1 parent d3142ff commit 7e7ae9c

6 files changed

Lines changed: 44 additions & 52 deletions

File tree

control/statesp.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,17 @@
7070

7171
# Define module default parameter values
7272
_statesp_defaults = {
73-
'statesp.use_numpy_matrix': True,
73+
'statesp.use_numpy_matrix': False,
7474
'statesp.default_dt': None,
7575
'statesp.remove_useless_states': True,
7676
}
7777

7878

7979
def _ssmatrix(data, axis=1):
80-
"""Convert argument to a (possibly empty) state space matrix.
80+
"""Convert argument to a (possibly empty) 2D state space matrix.
81+
82+
The axis keyword argument makes it convenient to specify that if the input
83+
is a vector, it is a row (axis=1) or column (axis=0) vector.
8184
8285
Parameters
8386
----------
@@ -94,8 +97,10 @@ def _ssmatrix(data, axis=1):
9497
"""
9598
# Convert the data into an array or matrix, as configured
9699
# If data is passed as a string, use (deprecated?) matrix constructor
97-
if config.defaults['statesp.use_numpy_matrix'] or isinstance(data, str):
100+
if config.defaults['statesp.use_numpy_matrix']:
98101
arr = np.matrix(data, dtype=float)
102+
elif isinstance(data, str):
103+
arr = np.array(np.matrix(data, dtype=float))
99104
else:
100105
arr = np.array(data, dtype=float)
101106
ndim = arr.ndim
@@ -195,12 +200,20 @@ def __init__(self, *args, **kw):
195200
raise ValueError("Needs 1 or 4 arguments; received %i." % len(args))
196201

197202
# Process keyword arguments
198-
remove_useless = kw.get('remove_useless', config.defaults['statesp.remove_useless_states'])
203+
remove_useless = kw.get('remove_useless',
204+
config.defaults['statesp.remove_useless_states'])
199205

200206
# Convert all matrices to standard form
201207
A = _ssmatrix(A)
202-
B = _ssmatrix(B, axis=0)
203-
C = _ssmatrix(C, axis=1)
208+
# if B is a 1D array, turn it into a column vector if it fits
209+
if np.asarray(B).ndim == 1 and len(B) == A.shape[0]:
210+
B = _ssmatrix(B, axis=0)
211+
else:
212+
B = _ssmatrix(B)
213+
if np.asarray(C).ndim == 1 and len(C) == A.shape[0]:
214+
C = _ssmatrix(C, axis=1)
215+
else:
216+
C = _ssmatrix(C, axis=0) #if this doesn't work, error below
204217
if np.isscalar(D) and D == 0 and B.shape[1] > 0 and C.shape[0] > 0:
205218
# If D is a scalar zero, broadcast it to the proper size
206219
D = np.zeros((C.shape[0], B.shape[1]))
@@ -1240,8 +1253,8 @@ def _mimo2simo(sys, input, warn_conversion=False):
12401253
"Only input {i} is used." .format(i=input))
12411254
# $X = A*X + B*U
12421255
# Y = C*X + D*U
1243-
new_B = sys.B[:, input]
1244-
new_D = sys.D[:, input]
1256+
new_B = sys.B[:, input:input+1]
1257+
new_D = sys.D[:, input:input+1]
12451258
sys = StateSpace(sys.A, new_B, sys.C, new_D, sys.dt)
12461259

12471260
return sys

control/tests/discrete_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ def test_sample_ss(self):
353353
for sys in (sys1, sys2):
354354
for h in (0.1, 0.5, 1, 2):
355355
Ad = I + h * sys.A
356-
Bd = h * sys.B + 0.5 * h**2 * (sys.A * sys.B)
356+
Bd = h * sys.B + 0.5 * h**2 * np.dot(sys.A, sys.B)
357357
sysd = sample_system(sys, h, method='zoh')
358358
np.testing.assert_array_almost_equal(sysd.A, Ad)
359359
np.testing.assert_array_almost_equal(sysd.B, Bd)

control/tests/iosys_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_linear_iosys(self):
5353
for x, u in (([0, 0], 0), ([1, 0], 0), ([0, 1], 0), ([0, 0], 1)):
5454
np.testing.assert_array_almost_equal(
5555
np.reshape(iosys._rhs(0, x, u), (-1,1)),
56-
linsys.A * np.reshape(x, (-1, 1)) + linsys.B * u)
56+
np.dot(linsys.A, np.reshape(x, (-1, 1))) + np.dot(linsys.B, u))
5757

5858
# Make sure that simulations also line up
5959
T, U, X0 = self.T, self.U, self.X0

control/tests/statesp_array_test.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from control.lti import evalfr
1414
from control.exception import slycot_check
1515
from control.config import use_numpy_matrix, reset_defaults
16+
from control.config import defaults
1617

1718
class TestStateSpace(unittest.TestCase):
1819
"""Tests for the StateSpace class."""
@@ -74,8 +75,12 @@ def test_matlab_style_constructor(self):
7475
self.assertEqual(sys.B.shape, (2, 1))
7576
self.assertEqual(sys.C.shape, (1, 2))
7677
self.assertEqual(sys.D.shape, (1, 1))
77-
for X in [sys.A, sys.B, sys.C, sys.D]:
78-
self.assertTrue(isinstance(X, np.matrix))
78+
if defaults['statesp.use_numpy_matrix']:
79+
for X in [sys.A, sys.B, sys.C, sys.D]:
80+
self.assertTrue(isinstance(X, np.matrix))
81+
else:
82+
for X in [sys.A, sys.B, sys.C, sys.D]:
83+
self.assertTrue(isinstance(X, np.ndarray))
7984

8085
def test_pole(self):
8186
"""Evaluate the poles of a MIMO system."""

control/tests/statesp_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ def test_array_access_ss(self):
323323
np.testing.assert_array_almost_equal(sys1_11.A,
324324
sys1.A)
325325
np.testing.assert_array_almost_equal(sys1_11.B,
326-
sys1.B[:, 1])
326+
sys1.B[:, 1:2])
327327
np.testing.assert_array_almost_equal(sys1_11.C,
328-
sys1.C[0, :])
328+
sys1.C[0:1, :])
329329
np.testing.assert_array_almost_equal(sys1_11.D,
330330
sys1.D[0, 1])
331331

control/tests/test_control_matlab.py

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from numpy.testing import assert_array_almost_equal
1212
from numpy import array, asarray, matrix, asmatrix, zeros, ones, linspace,\
1313
all, hstack, vstack, c_, r_
14-
from matplotlib.pylab import show, figure, plot, legend, subplot2grid
14+
from matplotlib.pyplot import show, figure, plot, legend, subplot2grid
1515
from control.matlab import ss, step, impulse, initial, lsim, dcgain, \
1616
ss2tf
1717
from control.statesp import _mimo2siso
@@ -24,29 +24,13 @@ class TestControlMatlab(unittest.TestCase):
2424
def setUp(self):
2525
pass
2626

27-
def plot_matrix(self):
28-
#Test: can matplotlib correctly plot matrices?
29-
#Yes, but slightly inconvenient
30-
figure()
31-
t = matrix([[ 1.],
32-
[ 2.],
33-
[ 3.],
34-
[ 4.]])
35-
y = matrix([[ 1., 4.],
36-
[ 4., 5.],
37-
[ 9., 6.],
38-
[16., 7.]])
39-
plot(t, y)
40-
#plot(asarray(t)[0], asarray(y)[0])
41-
42-
4327
def make_SISO_mats(self):
4428
"""Return matrices for a SISO system"""
45-
A = matrix([[-81.82, -45.45],
29+
A = array([[-81.82, -45.45],
4630
[ 10., -1. ]])
47-
B = matrix([[9.09],
31+
B = array([[9.09],
4832
[0. ]])
49-
C = matrix([[0, 0.159]])
33+
C = array([[0, 0.159]])
5034
D = zeros((1, 1))
5135
return A, B, C, D
5236

@@ -181,7 +165,7 @@ def test_impulse(self):
181165

182166
#Test MIMO system
183167
A, B, C, D = self.make_MIMO_mats()
184-
sys = ss(A, B, C, D)
168+
sys = ss(A, B, C, D)
185169
t, y = impulse(sys)
186170
plot(t, y, label='MIMO System')
187171

@@ -202,7 +186,7 @@ def test_initial(self):
202186

203187
#X0=[1,1] : produces a spike
204188
subplot2grid(plot_shape, (0, 1))
205-
t, y = initial(sys, X0=matrix("1; 1"))
189+
t, y = initial(sys, X0=array(matrix("1; 1")))
206190
plot(t, y)
207191

208192
#Test MIMO system
@@ -318,21 +302,11 @@ def test_lsim(self):
318302
plot(t, y, label='y')
319303
legend(loc='best')
320304

321-
#Test with matrices
322-
subplot2grid(plot_shape, (1, 0))
323-
t = matrix(linspace(0, 1, 100))
324-
u = matrix(r_[1:1:50j, 0:0:50j])
325-
x0 = matrix("0.; 0")
326-
y, t_out, _x = lsim(sys, u, t, x0)
327-
plot(t_out, y, label='y')
328-
plot(t_out, asarray(u/10)[0], label='u/10')
329-
legend(loc='best')
330-
331305
#Test with MIMO system
332306
subplot2grid(plot_shape, (1, 1))
333307
A, B, C, D = self.make_MIMO_mats()
334308
sys = ss(A, B, C, D)
335-
t = matrix(linspace(0, 1, 100))
309+
t = array(linspace(0, 1, 100))
336310
u = array([r_[1:1:50j, 0:0:50j],
337311
r_[0:1:50j, 0:0:50j]])
338312
x0 = [0, 0, 0, 0]
@@ -404,12 +378,12 @@ def test_convert_MIMO_to_SISO(self):
404378
#Test with additional systems --------------------------------------------
405379
#They have crossed inputs and direct feedthrough
406380
#SISO system
407-
As = matrix([[-81.82, -45.45],
381+
As = array([[-81.82, -45.45],
408382
[ 10., -1. ]])
409-
Bs = matrix([[9.09],
383+
Bs = array([[9.09],
410384
[0. ]])
411-
Cs = matrix([[0, 0.159]])
412-
Ds = matrix([[0.02]])
385+
Cs = array([[0, 0.159]])
386+
Ds = array([[0.02]])
413387
sys_siso = ss(As, Bs, Cs, Ds)
414388
# t, y = step(sys_siso)
415389
# plot(t, y, label='sys_siso d=0.02')
@@ -428,7 +402,7 @@ def test_convert_MIMO_to_SISO(self):
428402
[0 , 0 ]])
429403
Cm = array([[0, 0, 0, 0.159],
430404
[0, 0.159, 0, 0 ]])
431-
Dm = matrix([[0, 0.02],
405+
Dm = array([[0, 0.02],
432406
[0.02, 0 ]])
433407
sys_mimo = ss(Am, Bm, Cm, Dm)
434408

0 commit comments

Comments
 (0)