|
8 | 8 | """ |
9 | 9 |
|
10 | 10 | import numpy as np |
| 11 | +from numpy.testing import assert_allclose, assert_array_almost_equal |
11 | 12 | import pytest |
12 | 13 | import operator |
13 | 14 | from numpy.linalg import solve |
@@ -42,14 +43,26 @@ def sys322ABCD(self): |
42 | 43 | [0., 1.]] |
43 | 44 | return (A322, B322, C322, D322) |
44 | 45 |
|
| 46 | + |
| 47 | + @pytest.fixture |
| 48 | + def sys121(self): |
| 49 | + """2 state, 1 input, 1 output (siso) system""" |
| 50 | + A121 = [[4., 1.], |
| 51 | + [2., -3]] |
| 52 | + B121 = [[5.], |
| 53 | + [-3.]] |
| 54 | + C121 = [[2., -4]] |
| 55 | + D121 = [[3.]] |
| 56 | + return StateSpace(A121, B121, C121, D121) |
| 57 | + |
45 | 58 | @pytest.fixture |
46 | 59 | def sys322(self, sys322ABCD): |
47 | | - """3-states square system (2 inputs x 2 outputs)""" |
| 60 | + """3-state square system (2 inputs x 2 outputs)""" |
48 | 61 | return StateSpace(*sys322ABCD) |
49 | 62 |
|
50 | 63 | @pytest.fixture |
51 | 64 | def sys222(self): |
52 | | - """2-states square system (2 inputs x 2 outputs)""" |
| 65 | + """2-state square system (2 inputs x 2 outputs)""" |
53 | 66 | A222 = [[4., 1.], |
54 | 67 | [2., -3]] |
55 | 68 | B222 = [[5., 2.], |
@@ -744,6 +757,45 @@ def test_horner(self, sys322): |
744 | 757 | np.squeeze(sys322.horner(1.j)), |
745 | 758 | mag[:, :, 0] * np.exp(1.j * phase[:, :, 0])) |
746 | 759 |
|
| 760 | + @pytest.mark.parametrize('x', [[1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 761 | + @pytest.mark.parametrize('u', [None, 0, 1, np.atleast_1d(2)]) |
| 762 | + def test_dynamics_output_siso(self, x, u, sys121): |
| 763 | + assert_array_almost_equal( |
| 764 | + sys121.dynamics(x, u), |
| 765 | + sys121.A.dot(x) + (0 if u is None else sys121.B.dot(u))) |
| 766 | + assert_array_almost_equal( |
| 767 | + sys121.output(x, u), |
| 768 | + sys121.C.dot(x) + (0 if u is None else sys121.D.dot(u))) |
| 769 | + |
| 770 | + # too few and too many states and inputs |
| 771 | + @pytest.mark.parametrize('x', [0, 1, [], [1, 2, 3], np.atleast_1d(2)]) |
| 772 | + @pytest.mark.parametrize('u', [None, [1, 1], np.atleast_1d((2, 2))]) |
| 773 | + def test_dynamics_output_siso_fails(self, x, u, sys121): |
| 774 | + with pytest.raises(ValueError): |
| 775 | + sys121.dynamics(x, u) |
| 776 | + with pytest.raises(ValueError): |
| 777 | + sys121.output(x, u) |
| 778 | + |
| 779 | + @pytest.mark.parametrize('x',[[1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 780 | + @pytest.mark.parametrize('u', |
| 781 | + [None, [1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 782 | + def test_dynamics_output_mimo(self, x, u, sys222): |
| 783 | + assert_array_almost_equal( |
| 784 | + sys222.dynamics(x, u), |
| 785 | + sys222.A.dot(x) + (0 if u is None else sys222.B.dot(u))) |
| 786 | + assert_array_almost_equal( |
| 787 | + sys222.output(x, u), |
| 788 | + sys222.C.dot(x) + (0 if u is None else sys222.D.dot(u))) |
| 789 | + |
| 790 | + # too few and too many states and inputs |
| 791 | + @pytest.mark.parametrize('x', [0, 1, [1, 1, 1]]) |
| 792 | + @pytest.mark.parametrize('u', [None, 0, 1, [1, 1, 1]]) |
| 793 | + def test_dynamics_mimo_fails(self, x, u, sys222): |
| 794 | + with pytest.raises(ValueError): |
| 795 | + sys222.dynamics(x, u) |
| 796 | + with pytest.raises(ValueError): |
| 797 | + sys222.output(x, u) |
| 798 | + |
747 | 799 | class TestRss: |
748 | 800 | """These are tests for the proper functionality of statesp.rss.""" |
749 | 801 |
|
|
0 commit comments