From: <re...@us...> - 2014-05-23 12:41:56
|
Revision: 299 http://sourceforge.net/p/python-control/code/299 Author: repa Date: 2014-05-23 12:41:47 +0000 (Fri, 23 May 2014) Log Message: ----------- Added c2d functionality for MIMO state-space systems; both in matlab mode and for python mode; added tests for same Modified Paths: -------------- trunk/src/dtime.py trunk/src/matlab.py trunk/src/statesp.py trunk/tests/discrete_test.py trunk/tests/matlab_test.py Modified: trunk/src/dtime.py =================================================================== --- trunk/src/dtime.py 2014-03-23 20:39:48 UTC (rev 298) +++ trunk/src/dtime.py 2014-05-23 12:41:47 UTC (rev 299) @@ -94,11 +94,25 @@ if not isctime(sysc): raise ValueError("First argument must be continuous time system") - # TODO: impelement MIMO version + # If we are passed a state space system, convert to transfer function first + if isinstance(sysc, StateSpace) and method == 'zoh': + + try: + # try with slycot routine + from slycot import mb05nd + F, H = mb05nd(sysc.A, Ts) + return StateSpace(F, H*sysc.B, sysc.C, sysc.D, Ts) + except ImportError: + if sysc.inputs != 1 or sysc.outputs != 1: + raise TypeError( + "mb05nd not found in slycot, or slycot not installed") + + # TODO: implement MIMO version for other than ZOH state-space if (sysc.inputs != 1 or sysc.outputs != 1): raise NotImplementedError("MIMO implementation not available") - # If we are passed a state space system, convert to transfer function first + # SISO state-space, with other than ZOH, or failing slycot import, + # is handled by conversion to TF if isinstance(sysc, StateSpace): warn("sample_system: converting to transfer function") sysc = _convertToTransferFunction(sysc) Modified: trunk/src/matlab.py =================================================================== --- trunk/src/matlab.py 2014-03-23 20:39:48 UTC (rev 298) +++ trunk/src/matlab.py 2014-05-23 12:41:47 UTC (rev 299) @@ -1524,8 +1524,29 @@ return (tf.num, tf.den) # Convert a continuous time system to a discrete time system -def c2d(sysc, Ts, method): - # TODO: add docstring +def c2d(sysc, Ts, method='zoh'): + ''' + Return a discrete-time system + + Parameters + ---------- + sysc: Lti (StateSpace or TransferFunction), continuous + System to be converted + + Ts: number + Sample time for the conversion + + method: string, optional + Method to be applied, + 'zoh' Zero-order hold on the inputs (default) + 'foh' First-order hold, currently not implemented + 'impulse' Impulse-invariant discretization, currently not implemented + 'tustin' Bilinear (Tustin) approximation, only SISO + 'matched' Matched pole-zero method, only SISO + ''' # Call the sample_system() function to do the work - return sample_system(sysc, Ts, method) + sysd = sample_system(sysc, Ts, method) + if isinstance(sysc, StateSpace) and not isinstance(sysd, StateSpace): + return _convertToStateSpace(sysd) + return sysd Modified: trunk/src/statesp.py =================================================================== --- trunk/src/statesp.py 2014-03-23 20:39:48 UTC (rev 298) +++ trunk/src/statesp.py 2014-05-23 12:41:47 UTC (rev 299) @@ -610,7 +610,7 @@ ssout[3][:sys.outputs, :states], ssout[4], sys.dt) except ImportError: - # TODO: do we want to squeeze first and check dimenations? + # TODO: do we want to squeeze first and check dimensions? # I think this will fail if num and den aren't 1-D after # the squeeze lti_sys = lti(squeeze(sys.num), squeeze(sys.den)) Modified: trunk/tests/discrete_test.py =================================================================== --- trunk/tests/discrete_test.py 2014-03-23 20:39:48 UTC (rev 298) +++ trunk/tests/discrete_test.py 2014-05-23 12:41:47 UTC (rev 299) @@ -272,6 +272,10 @@ self.assertEqual(sysd.dt, 1) # TODO: put in other generic checks + for sysc in (self.mimo_ss1, self.mimo_ss1c): + sysd = sample_system(sysc, 1, method='zoh') + self.assertEqual(sysd.dt, 1) + # TODO: check results of converstion # Check errors Modified: trunk/tests/matlab_test.py =================================================================== --- trunk/tests/matlab_test.py 2014-03-23 20:39:48 UTC (rev 298) +++ trunk/tests/matlab_test.py 2014-05-23 12:41:47 UTC (rev 299) @@ -515,7 +515,26 @@ np.testing.assert_array_almost_equal(hm.num[0][0], hr.num[0][0]) np.testing.assert_array_almost_equal(hm.den[0][0], hr.den[0][0]) + def testSS2cont(self): + sys = ss( + np.mat("-3 4 2; -1 -3 0; 2 5 3"), + np.mat("1 4 ; -3 -3; -2 1"), + np.mat("4 2 -3; 1 4 3"), + np.mat("-2 4; 0 1")) + sysd = c2d(sys, 0.1) + np.testing.assert_array_almost_equal( + np.mat( + """0.742840837331905 0.342242024293711 0.203124211149560; + -0.074130792143890 0.724553295044645 -0.009143771143630; + 0.180264783290485 0.544385612448419 1.370501013067845"""), + sysd.A) + np.testing.assert_array_almost_equal( + np.mat(""" 0.012362066084719 0.301932197918268; + -0.260952977031384 -0.274201791021713; + -0.304617775734327 0.075182622718853"""), sysd.B) + + #! TODO: not yet implemented # def testMIMOtfdata(self): # sisotf = ss2tf(self.siso_ss1) |