|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +import unittest |
| 4 | +import numpy as np |
| 5 | +from control import ss |
| 6 | +from control.canonical import canonical_form |
| 7 | + |
| 8 | + |
| 9 | +class TestCanonical(unittest.TestCase): |
| 10 | + """Tests for the canonical forms class""" |
| 11 | + |
| 12 | + def test_reachable_form(self): |
| 13 | + """Test the reachable canonical form""" |
| 14 | + |
| 15 | + # Create a system in the reachable canonical form |
| 16 | + coeffs = [1.0, 2.0, 3.0, 4.0, 1.0] |
| 17 | + A_true = np.polynomial.polynomial.polycompanion(coeffs) |
| 18 | + A_true = np.fliplr(np.rot90(A_true)) |
| 19 | + B_true = np.matrix("1.0 0.0 0.0 0.0").T |
| 20 | + C_true = np.matrix("1.0 1.0 1.0 1.0") |
| 21 | + D_true = 42.0 |
| 22 | + |
| 23 | + # Perform a coordinate transform with a random invertible matrix |
| 24 | + T_true = np.matrix([[-0.27144004, -0.39933167, 0.75634684, 0.44135471], |
| 25 | + [-0.74855725, -0.39136285, -0.18142339, -0.50356997], |
| 26 | + [-0.40688007, 0.81416369, 0.38002113, -0.16483334], |
| 27 | + [-0.44769516, 0.15654653, -0.50060858, 0.72419146]]) |
| 28 | + A = np.linalg.solve(T_true, A_true)*T_true |
| 29 | + B = np.linalg.solve(T_true, B_true) |
| 30 | + C = C_true*T_true |
| 31 | + D = D_true |
| 32 | + |
| 33 | + # Create a state space system and convert it to the reachable canonical form |
| 34 | + sys_check, T_check = canonical_form(ss(A, B, C, D), "reachable") |
| 35 | + |
| 36 | + # Check against the true values |
| 37 | + np.testing.assert_array_almost_equal(sys_check.A, A_true) |
| 38 | + np.testing.assert_array_almost_equal(sys_check.B, B_true) |
| 39 | + np.testing.assert_array_almost_equal(sys_check.C, C_true) |
| 40 | + np.testing.assert_array_almost_equal(sys_check.D, D_true) |
| 41 | + np.testing.assert_array_almost_equal(T_check, T_true) |
0 commit comments