76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# rlocus_test.py - unit test for root locus diagrams
|
||
|
# RMM, 1 Jul 2011
|
||
|
|
||
|
import unittest
|
||
|
import numpy as np
|
||
|
from control.rlocus import root_locus, _RLClickDispatcher
|
||
|
from control.xferfcn import TransferFunction
|
||
|
from control.statesp import StateSpace
|
||
|
from control.bdalg import feedback
|
||
|
import matplotlib.pyplot as plt
|
||
|
from control.tests.margin_test import assert_array_almost_equal
|
||
|
|
||
|
|
||
|
class TestRootLocus(unittest.TestCase):
|
||
|
"""These are tests for the feedback function in rlocus.py."""
|
||
|
|
||
|
def setUp(self):
|
||
|
"""This contains some random LTI systems and scalars for testing."""
|
||
|
|
||
|
# Two random SISO systems.
|
||
|
sys1 = TransferFunction([1, 2], [1, 2, 3])
|
||
|
sys2 = StateSpace([[1., 4.], [3., 2.]], [[1.], [-4.]],
|
||
|
[[1., 0.]], [[0.]])
|
||
|
self.systems = (sys1, sys2)
|
||
|
|
||
|
def check_cl_poles(self, sys, pole_list, k_list):
|
||
|
for k, poles in zip(k_list, pole_list):
|
||
|
poles_expected = np.sort(feedback(sys, k).pole())
|
||
|
poles = np.sort(poles)
|
||
|
np.testing.assert_array_almost_equal(poles, poles_expected)
|
||
|
|
||
|
def testRootLocus(self):
|
||
|
"""Basic root locus plot"""
|
||
|
klist = [-1, 0, 1]
|
||
|
for sys in self.systems:
|
||
|
roots, k_out = root_locus(sys, klist, Plot=False)
|
||
|
np.testing.assert_equal(len(roots), len(klist))
|
||
|
np.testing.assert_array_equal(klist, k_out)
|
||
|
self.check_cl_poles(sys, roots, klist)
|
||
|
|
||
|
def test_without_gains(self):
|
||
|
for sys in self.systems:
|
||
|
roots, kvect = root_locus(sys, Plot=False)
|
||
|
self.check_cl_poles(sys, roots, kvect)
|
||
|
|
||
|
def test_root_locus_zoom(self):
|
||
|
"""Check the zooming functionality of the Root locus plot"""
|
||
|
system = TransferFunction([1000], [1, 25, 100, 0])
|
||
|
root_locus(system)
|
||
|
fig = plt.gcf()
|
||
|
ax_rlocus = fig.axes[0]
|
||
|
|
||
|
event = type('test', (object,), {'xdata': 14.7607954359, 'ydata': -35.6171379864, 'inaxes': ax_rlocus.axes})()
|
||
|
ax_rlocus.set_xlim((-10.813628105112421, 14.760795435937652))
|
||
|
ax_rlocus.set_ylim((-35.61713798641108, 33.879716621220311))
|
||
|
plt.get_current_fig_manager().toolbar.mode = 'zoom rect'
|
||
|
_RLClickDispatcher(event, system, fig, ax_rlocus, '-')
|
||
|
|
||
|
zoom_x = ax_rlocus.lines[-2].get_data()[0][0:5]
|
||
|
zoom_y = ax_rlocus.lines[-2].get_data()[1][0:5]
|
||
|
zoom_y = [abs(y) for y in zoom_y]
|
||
|
|
||
|
zoom_x_valid = [-5. ,- 4.61281263, - 4.16689986, - 4.04122642, - 3.90736502]
|
||
|
zoom_y_valid = [0. ,0., 0., 0., 0.]
|
||
|
|
||
|
assert_array_almost_equal(zoom_x,zoom_x_valid)
|
||
|
assert_array_almost_equal(zoom_y,zoom_y_valid)
|
||
|
|
||
|
def test_suite():
|
||
|
return unittest.TestLoader().loadTestsFromTestCase(TestRootLocus)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
unittest.main()
|