|
8 | 8 | """ |
9 | 9 |
|
10 | 10 | import numpy as np |
| 11 | +from numpy.testing import assert_array_almost_equal |
11 | 12 | import pytest |
12 | 13 | import operator |
13 | 14 | from numpy.linalg import solve |
@@ -47,6 +48,17 @@ def sys322(self, sys322ABCD): |
47 | 48 | """3-states square system (2 inputs x 2 outputs)""" |
48 | 49 | return StateSpace(*sys322ABCD) |
49 | 50 |
|
| 51 | + @pytest.fixture |
| 52 | + def sys121(self): |
| 53 | + """2 state, 1 input, 1 output (siso) system""" |
| 54 | + A121 = [[4., 1.], |
| 55 | + [2., -3]] |
| 56 | + B121 = [[5.], |
| 57 | + [-3.]] |
| 58 | + C121 = [[2., -4]] |
| 59 | + D121 = [[3.]] |
| 60 | + return StateSpace(A121, B121, C121, D121) |
| 61 | + |
50 | 62 | @pytest.fixture |
51 | 63 | def sys222(self): |
52 | 64 | """2-states square system (2 inputs x 2 outputs)""" |
@@ -751,6 +763,70 @@ def test_horner(self, sys322): |
751 | 763 | np.squeeze(sys322.horner(1.j)), |
752 | 764 | mag[:, :, 0] * np.exp(1.j * phase[:, :, 0])) |
753 | 765 |
|
| 766 | + @pytest.mark.parametrize('x', |
| 767 | + [[1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 768 | + @pytest.mark.parametrize('u', [0, 1, np.atleast_1d(2)]) |
| 769 | + def test_dynamics_and_output_siso(self, x, u, sys121): |
| 770 | + assert_array_almost_equal( |
| 771 | + sys121.dynamics(0, x, u), |
| 772 | + sys121.A.dot(x).reshape((-1,)) + sys121.B.dot(u).reshape((-1,))) |
| 773 | + assert_array_almost_equal( |
| 774 | + sys121.output(0, x, u), |
| 775 | + sys121.C.dot(x).reshape((-1,)) + sys121.D.dot(u).reshape((-1,))) |
| 776 | + assert_array_almost_equal( |
| 777 | + sys121.dynamics(0, x), |
| 778 | + sys121.A.dot(x).reshape((-1,))) |
| 779 | + assert_array_almost_equal( |
| 780 | + sys121.output(0, x), |
| 781 | + sys121.C.dot(x).reshape((-1,))) |
| 782 | + |
| 783 | + # too few and too many states and inputs |
| 784 | + @pytest.mark.parametrize('x', [0, 1, [], [1, 2, 3], np.atleast_1d(2)]) |
| 785 | + def test_error_x_dynamics_and_output_siso(self, x, sys121): |
| 786 | + with pytest.raises(ValueError): |
| 787 | + sys121.dynamics(0, x) |
| 788 | + with pytest.raises(ValueError): |
| 789 | + sys121.output(0, x) |
| 790 | + @pytest.mark.parametrize('u', [[1, 1], np.atleast_1d((2, 2))]) |
| 791 | + def test_error_u_dynamics_output_siso(self, u, sys121): |
| 792 | + with pytest.raises(ValueError): |
| 793 | + sys121.dynamics(0, 1, u) |
| 794 | + with pytest.raises(ValueError): |
| 795 | + sys121.output(0, 1, u) |
| 796 | + |
| 797 | + @pytest.mark.parametrize('x', |
| 798 | + [[1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 799 | + @pytest.mark.parametrize('u', |
| 800 | + [[1, 1], [[1], [1]], np.atleast_2d([1,1]).T]) |
| 801 | + def test_dynamics_and_output_mimo(self, x, u, sys222): |
| 802 | + assert_array_almost_equal( |
| 803 | + sys222.dynamics(0, x, u), |
| 804 | + sys222.A.dot(x).reshape((-1,)) + sys222.B.dot(u).reshape((-1,))) |
| 805 | + assert_array_almost_equal( |
| 806 | + sys222.output(0, x, u), |
| 807 | + sys222.C.dot(x).reshape((-1,)) + sys222.D.dot(u).reshape((-1,))) |
| 808 | + assert_array_almost_equal( |
| 809 | + sys222.dynamics(0, x), |
| 810 | + sys222.A.dot(x).reshape((-1,))) |
| 811 | + assert_array_almost_equal( |
| 812 | + sys222.output(0, x), |
| 813 | + sys222.C.dot(x).reshape((-1,))) |
| 814 | + |
| 815 | + # too few and too many states and inputs |
| 816 | + @pytest.mark.parametrize('x', [0, 1, [1, 1, 1]]) |
| 817 | + def test_error_x_dynamics_mimo(self, x, sys222): |
| 818 | + with pytest.raises(ValueError): |
| 819 | + sys222.dynamics(0, x) |
| 820 | + with pytest.raises(ValueError): |
| 821 | + sys222.output(0, x) |
| 822 | + @pytest.mark.parametrize('u', [1, [1, 1, 1]]) |
| 823 | + def test_error_u_dynamics_mimo(self, u, sys222): |
| 824 | + with pytest.raises(ValueError): |
| 825 | + sys222.dynamics(0, (1, 1), u) |
| 826 | + with pytest.raises(ValueError): |
| 827 | + sys222.output(0, (1, 1), u) |
| 828 | + |
| 829 | + |
754 | 830 | class TestRss: |
755 | 831 | """These are tests for the proper functionality of statesp.rss.""" |
756 | 832 |
|
|
0 commit comments