|
From: <kk...@us...> - 2011-02-08 22:18:29
|
Revision: 105
http://python-control.svn.sourceforge.net/python-control/?rev=105&view=rev
Author: kkchen
Date: 2011-02-08 22:18:23 +0000 (Tue, 08 Feb 2011)
Log Message:
-----------
Modified _common_den to handle complex roots more accurately.
Minor changes in TestConvert.py and TestBDAlg.py.
Kevin K. Chen <kk...@pr...>
Modified Paths:
--------------
branches/control-0.4a/src/TestBDAlg.py
branches/control-0.4a/src/TestConvert.py
branches/control-0.4a/src/xferfcn.py
Modified: branches/control-0.4a/src/TestBDAlg.py
===================================================================
--- branches/control-0.4a/src/TestBDAlg.py 2011-02-08 22:18:19 UTC (rev 104)
+++ branches/control-0.4a/src/TestBDAlg.py 2011-02-08 22:18:23 UTC (rev 105)
@@ -38,7 +38,6 @@
ans1 = feedback(self.x1, self.sys2)
ans2 = feedback(self.x1, self.sys2, 1.)
- # This one doesn't work yet. The feedback system has too many states.
np.testing.assert_array_almost_equal(ans1.A, [[-1.5, 4.], [13., 2.]])
np.testing.assert_array_almost_equal(ans1.B, [[2.5], [-10.]])
np.testing.assert_array_almost_equal(ans1.C, [[-2.5, 0.]])
@@ -65,7 +64,6 @@
ans1 = feedback(self.sys2, self.x1)
ans2 = feedback(self.sys2, self.x1, 1.)
- # This one doesn't work yet. The feedback system has too many states.
np.testing.assert_array_almost_equal(ans1.A, [[-1.5, 4.], [13., 2.]])
np.testing.assert_array_almost_equal(ans1.B, [[1.], [-4.]])
np.testing.assert_array_almost_equal(ans1.C, [[1., 0.]])
Modified: branches/control-0.4a/src/TestConvert.py
===================================================================
--- branches/control-0.4a/src/TestConvert.py 2011-02-08 22:18:19 UTC (rev 104)
+++ branches/control-0.4a/src/TestConvert.py 2011-02-08 22:18:23 UTC (rev 105)
@@ -4,11 +4,14 @@
Test state space and transfer function conversion.
-Currently, this unit test script is not complete. It converts
-several random state spaces back and forth between state space and transfer
-function representations, and asserts that the conversion outputs are correct.
-As it stands, tests pass but there is some rounding error in one of the conversions leading to imaginary numbers. See the warning message. This script may be used to diagnose errors.
+Currently, this unit test script is not complete. It converts several random
+state spaces back and forth between state space and transfer function
+representations. Ideally, it should be able to assert that the conversion
+outputs are correct. This is not yet implemented.
+Also, the conversion seems to enter an infinite loop once in a while. The cause
+of this is unknown.
+
"""
import numpy as np
@@ -22,11 +25,11 @@
"""Set up testing parameters."""
# Number of times to run each of the randomized tests.
- self.numTests = 1
+ self.numTests = 10
# Maximum number of states to test + 1
- self.maxStates = 3
+ self.maxStates = 2
# Maximum number of inputs and outputs to test + 1
- self.maxIO = 3
+ self.maxIO = 2
# Set to True to print systems to the output.
self.debug = True
Modified: branches/control-0.4a/src/xferfcn.py
===================================================================
--- branches/control-0.4a/src/xferfcn.py 2011-02-08 22:18:19 UTC (rev 104)
+++ branches/control-0.4a/src/xferfcn.py 2011-02-08 22:18:23 UTC (rev 105)
@@ -75,8 +75,8 @@
"""
# External function declarations
-from numpy import angle, array, empty, finfo, insert, ndarray, ones, polyadd, \
- polymul, polyval, roots, sort, zeros
+from numpy import angle, any, array, empty, finfo, insert, ndarray, ones, \
+ polyadd, polymul, polyval, roots, sort, sqrt, zeros
from scipy.signal import lti
from copy import deepcopy
from slycot import tb04ad
@@ -491,7 +491,10 @@
[something] array.
"""
-
+
+ # Machine precision for floats.
+ eps = finfo(float).eps
+
# A sorted list to keep track of cumulative poles found as we scan
# self.den.
poles = []
@@ -512,8 +515,7 @@
# cumulative poles, until one of them reaches the end. Keep in
# mind that both lists are always sorted.
while cp_ind < len(currentpoles) and p_ind < len(poles):
- if abs(currentpoles[cp_ind] - poles[p_ind]) < (10 *
- finfo(float).eps):
+ if abs(currentpoles[cp_ind] - poles[p_ind]) < (10 * eps):
# If the current element of both lists match, then we're
# good. Move to the next pair of elements.
cp_ind += 1
@@ -558,9 +560,22 @@
# Construct the common denominator.
den = 1.
- for p in poles:
- den = polymul(den, [1., -p])
+ n = 0
+ while n < len(poles):
+ if abs(poles[n].imag) > 10 * eps:
+ # To prevent buildup of imaginary part error, handle complex
+ # pole pairs together.
+ quad = polymul([1., -poles[n]], [1., -poles[n+1]])
+ assert all(quad.imag < eps), "The quadratic has a nontrivial \
+imaginary part: %g" % quad.imag.max()
+ quad = quad.real
+ den = polymul(den, quad)
+ n += 2
+ else:
+ den = polymul(den, [1., -poles[n].real])
+ n += 1
+
# Modify the numerators so that they each take the common denominator.
num = deepcopy(self.num)
for i in range(self.outputs):
@@ -585,6 +600,11 @@
zeros(largest - len(num[i][j])))
# Finally, convert the numerator to a 3-D array.
num = array(num)
+ # Remove trivial imaginary parts. Check for nontrivial imaginary parts.
+ if any(abs(num.imag) > sqrt(eps)):
+ print ("Warning: The numerator has a nontrivial nontrivial part: %g"
+ % abs(num.imag).max())
+ num = num.real
return num, den
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|