|
2 | 2 |
|
3 | 3 | import unittest
|
4 | 4 | import numpy as np
|
5 |
| -from control import ss, tf |
| 5 | +from control import ss, tf, tf2ss, ss2tf |
6 | 6 | from control.canonical import canonical_form, reachable_form, \
|
7 |
| - observable_form, modal_form |
| 7 | + observable_form, modal_form, similarity_transform |
8 | 8 | from control.exception import ControlNotImplemented
|
9 | 9 |
|
10 | 10 | class TestCanonical(unittest.TestCase):
|
@@ -218,6 +218,76 @@ def test_arguments(self):
|
218 | 218 | np.testing.assert_raises(
|
219 | 219 | ControlNotImplemented, canonical_form, sys, 'unknown')
|
220 | 220 |
|
| 221 | + def test_similarity(self): |
| 222 | + """Test similarty transform""" |
| 223 | + |
| 224 | + # Single input, single output systems |
| 225 | + siso_ini = tf2ss(tf([1, 1], [1, 1, 1])) |
| 226 | + for form in 'reachable', 'observable': |
| 227 | + # Convert the system to one of the canonical forms |
| 228 | + siso_can, T_can = canonical_form(siso_ini, form) |
| 229 | + |
| 230 | + # Use a similarity transformation to transform it back |
| 231 | + siso_sim = similarity_transform(siso_can, np.linalg.inv(T_can)) |
| 232 | + |
| 233 | + # Make sure everything goes back to the original form |
| 234 | + np.testing.assert_array_almost_equal(siso_sim.A, siso_ini.A) |
| 235 | + np.testing.assert_array_almost_equal(siso_sim.B, siso_ini.B) |
| 236 | + np.testing.assert_array_almost_equal(siso_sim.C, siso_ini.C) |
| 237 | + np.testing.assert_array_almost_equal(siso_sim.D, siso_ini.D) |
| 238 | + |
| 239 | + # Multi-input, multi-output systems |
| 240 | + mimo_ini = ss( |
| 241 | + [[-1, 1, 0, 0], [0, -2, 1, 0], [0, 0, -3, 1], [0, 0, 0, -4]], |
| 242 | + [[1, 0], [0, 0], [0, 1], [1, 1]], |
| 243 | + [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]], |
| 244 | + np.zeros((3, 2))) |
| 245 | + |
| 246 | + # Simple transformation: row/col flips + scaling |
| 247 | + mimo_txf = np.array( |
| 248 | + [[0, 1, 0, 0], [2, 0, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) |
| 249 | + |
| 250 | + # Transform the system and transform it back |
| 251 | + mimo_sim = similarity_transform(mimo_ini, mimo_txf) |
| 252 | + mimo_new = similarity_transform(mimo_sim, np.linalg.inv(mimo_txf)) |
| 253 | + np.testing.assert_array_almost_equal(mimo_new.A, mimo_ini.A) |
| 254 | + np.testing.assert_array_almost_equal(mimo_new.B, mimo_ini.B) |
| 255 | + np.testing.assert_array_almost_equal(mimo_new.C, mimo_ini.C) |
| 256 | + np.testing.assert_array_almost_equal(mimo_new.D, mimo_ini.D) |
| 257 | + |
| 258 | + # Make sure rescaling by identify does nothing |
| 259 | + mimo_new = similarity_transform(mimo_ini, np.eye(4)) |
| 260 | + np.testing.assert_array_almost_equal(mimo_new.A, mimo_ini.A) |
| 261 | + np.testing.assert_array_almost_equal(mimo_new.B, mimo_ini.B) |
| 262 | + np.testing.assert_array_almost_equal(mimo_new.C, mimo_ini.C) |
| 263 | + np.testing.assert_array_almost_equal(mimo_new.D, mimo_ini.D) |
| 264 | + |
| 265 | + # Time rescaling |
| 266 | + mimo_tim = similarity_transform(mimo_ini, np.eye(4), timescale=0.3) |
| 267 | + mimo_new = similarity_transform(mimo_tim, np.eye(4), timescale=1/0.3) |
| 268 | + np.testing.assert_array_almost_equal(mimo_new.A, mimo_ini.A) |
| 269 | + np.testing.assert_array_almost_equal(mimo_new.B, mimo_ini.B) |
| 270 | + np.testing.assert_array_almost_equal(mimo_new.C, mimo_ini.C) |
| 271 | + np.testing.assert_array_almost_equal(mimo_new.D, mimo_ini.D) |
| 272 | + |
| 273 | + # Time + transformation, in one step |
| 274 | + mimo_sim = similarity_transform(mimo_ini, mimo_txf, timescale=0.3) |
| 275 | + mimo_new = similarity_transform(mimo_sim, np.linalg.inv(mimo_txf), |
| 276 | + timescale=1/0.3) |
| 277 | + np.testing.assert_array_almost_equal(mimo_new.A, mimo_ini.A) |
| 278 | + np.testing.assert_array_almost_equal(mimo_new.B, mimo_ini.B) |
| 279 | + np.testing.assert_array_almost_equal(mimo_new.C, mimo_ini.C) |
| 280 | + np.testing.assert_array_almost_equal(mimo_new.D, mimo_ini.D) |
| 281 | + |
| 282 | + # Time + transformation, in two steps |
| 283 | + mimo_sim = similarity_transform(mimo_ini, mimo_txf, timescale=0.3) |
| 284 | + mimo_tim = similarity_transform(mimo_sim, np.eye(4), timescale=1/0.3) |
| 285 | + mimo_new = similarity_transform(mimo_tim, np.linalg.inv(mimo_txf)) |
| 286 | + np.testing.assert_array_almost_equal(mimo_new.A, mimo_ini.A) |
| 287 | + np.testing.assert_array_almost_equal(mimo_new.B, mimo_ini.B) |
| 288 | + np.testing.assert_array_almost_equal(mimo_new.C, mimo_ini.C) |
| 289 | + np.testing.assert_array_almost_equal(mimo_new.D, mimo_ini.D) |
| 290 | + |
221 | 291 | def suite():
|
222 | 292 | return unittest.TestLoader().loadTestsFromTestCase(TestFeedback)
|
223 | 293 |
|
|
0 commit comments