1010
1111# Python 3 compatibility (needs to go here)
1212from __future__ import print_function
13- from __future__ import division # for _convertToStateSpace
13+ from __future__ import division # for _convertToStateSpace
1414
1515"""Copyright (c) 2010 by California Institute of Technology
1616All rights reserved.
@@ -166,9 +166,9 @@ def __init__(self, *args):
166166 if 0 == self .states :
167167 # static gain
168168 # matrix's default "empty" shape is 1x0
169- A .shape = (0 ,0 )
170- B .shape = (0 ,self .inputs )
171- C .shape = (self .outputs ,0 )
169+ A .shape = (0 , 0 )
170+ B .shape = (0 , self .inputs )
171+ C .shape = (self .outputs , 0 )
172172
173173 # Check that the matrix sizes are consistent.
174174 if self .states != A .shape [0 ]:
@@ -200,13 +200,13 @@ def _remove_useless_states(self):
200200 # Search for useless states.
201201 for i in range (self .states ):
202202 if (all (self .A [i , :] == zeros ((1 , self .states ))) and
203- all (self .B [i , :] == zeros ((1 , self .inputs )))):
203+ all (self .B [i , :] == zeros ((1 , self .inputs )))):
204204 useless .append (i )
205205 # To avoid duplicate indices in useless, jump to the next
206206 # iteration.
207207 continue
208208 if (all (self .A [:, i ] == zeros ((self .states , 1 ))) and
209- all (self .C [:, i ] == zeros ((self .outputs , 1 )))):
209+ all (self .C [:, i ] == zeros ((self .outputs , 1 )))):
210210 useless .append (i )
211211
212212 # Remove the useless states.
@@ -227,9 +227,9 @@ def __str__(self):
227227 str += "C = " + self .C .__str__ () + "\n \n "
228228 str += "D = " + self .D .__str__ () + "\n "
229229 # TODO: replace with standard calls to lti functions
230- if ( type (self .dt ) == bool and self .dt is True ) :
230+ if type (self .dt ) == bool and self .dt is True :
231231 str += "\n dt unspecified\n "
232- elif ( not (self .dt is None ) and type (self .dt ) != bool and self .dt > 0 ) :
232+ elif not (self .dt is None ) and type (self .dt ) != bool and self .dt > 0 :
233233 str += "\n dt = " + self .dt .__str__ () + "\n "
234234 return str
235235
@@ -262,20 +262,20 @@ def __add__(self, other):
262262
263263 # Figure out the sampling time to use
264264 if self .dt is None and other .dt is not None :
265- dt = other .dt # use dt from second argument
265+ dt = other .dt # use dt from second argument
266266 elif (other .dt is None and self .dt is not None ) or \
267267 (timebaseEqual (self , other )):
268- dt = self .dt # use dt from first argument
268+ dt = self .dt # use dt from first argument
269269 else :
270270 raise ValueError ("Systems have different sampling times" )
271271
272272 # Concatenate the various arrays
273273 A = concatenate ((
274274 concatenate ((self .A , zeros ((self .A .shape [0 ],
275- other .A .shape [- 1 ]))),axis = 1 ),
275+ other .A .shape [- 1 ]))), axis = 1 ),
276276 concatenate ((zeros ((other .A .shape [0 ], self .A .shape [- 1 ])),
277- other .A ),axis = 1 )
278- ), axis = 0 )
277+ other .A ), axis = 1 )
278+ ), axis = 0 )
279279 B = concatenate ((self .B , other .B ), axis = 0 )
280280 C = concatenate ((self .C , other .C ), axis = 1 )
281281 D = self .D + other .D
@@ -319,21 +319,20 @@ def __mul__(self, other):
319319 but B has %i row(s)\n (output(s))." % (self .inputs , other .outputs ))
320320
321321 # Figure out the sampling time to use
322- if (self .dt == None and other .dt != None ):
323- dt = other .dt # use dt from second argument
324- elif (other .dt == None and self .dt != None ) or \
325- (timebaseEqual (self , other )):
326- dt = self .dt # use dt from first argument
322+ if self .dt is None and other .dt is not None :
323+ dt = other .dt # use dt from second argument
324+ elif other .dt is None and self .dt is not None or timebaseEqual (self , other ):
325+ dt = self .dt # use dt from first argument
327326 else :
328327 raise ValueError ("Systems have different sampling times" )
329328
330329 # Concatenate the various arrays
331330 A = concatenate (
332- (concatenate ((other .A , zeros ((other .A .shape [0 ], self .A .shape [1 ]))),
333- axis = 1 ),
334- concatenate ((self .B * other .C , self .A ), axis = 1 )), axis = 0 )
331+ (concatenate ((other .A , zeros ((other .A .shape [0 ], self .A .shape [1 ]))),
332+ axis = 1 ),
333+ concatenate ((self .B * other .C , self .A ), axis = 1 )), axis = 0 )
335334 B = concatenate ((other .B , self .B * other .D ), axis = 0 )
336- C = concatenate ((self .D * other .C , self .C ),axis = 1 )
335+ C = concatenate ((self .D * other .C , self .C ), axis = 1 )
337336 D = self .D * other .D
338337
339338 return StateSpace (A , B , C , D , dt )
@@ -497,7 +496,7 @@ def freqresp(self, omega):
497496
498497 # kk+1 because enumerate starts at kk = 0.
499498 # but zero-th spot is already filled.
500- Gfrf [:, :, kk + 1 ] = result [0 ] + self .D
499+ Gfrf [:, :, kk + 1 ] = result [0 ] + self .D
501500
502501 except ImportError : # Slycot unavailable. Fall back to horner.
503502 for kk , cmplx_freqs_kk in enumerate (cmplx_freqs ):
@@ -562,14 +561,14 @@ def feedback(self, other=1, sign=-1):
562561
563562 # Check to make sure the dimensions are OK
564563 if (self .inputs != other .outputs ) or (self .outputs != other .inputs ):
565- raise ValueError ("State space systems don't have compatible inputs/outputs for "
566- "feedback." )
564+ raise ValueError ("State space systems don't have compatible inputs/outputs for "
565+ "feedback." )
567566
568567 # Figure out the sampling time to use
569568 if self .dt is None and other .dt is not None :
570- dt = other .dt # use dt from second argument
569+ dt = other .dt # use dt from second argument
571570 elif other .dt is None and self .dt is not None or timebaseEqual (self , other ):
572- dt = self .dt # use dt from first argument
571+ dt = self .dt # use dt from first argument
573572 else :
574573 raise ValueError ("Systems have different sampling times" )
575574
@@ -614,19 +613,18 @@ def minreal(self, tol=0.0):
614613 try :
615614 from slycot import tb01pd
616615 B = empty ((self .states , max (self .inputs , self .outputs )))
617- B [:,:self .inputs ] = self .B
616+ B [:, :self .inputs ] = self .B
618617 C = empty ((max (self .outputs , self .inputs ), self .states ))
619- C [:self .outputs ,:] = self .C
618+ C [:self .outputs , :] = self .C
620619 A , B , C , nr = tb01pd (self .states , self .inputs , self .outputs ,
621620 self .A , B , C , tol = tol )
622- return StateSpace (A [:nr ,:nr ], B [:nr ,:self .inputs ],
623- C [:self .outputs ,:nr ], self .D )
621+ return StateSpace (A [:nr , :nr ], B [:nr , :self .inputs ],
622+ C [:self .outputs , :nr ], self .D )
624623 except ImportError :
625624 raise TypeError ("minreal requires slycot tb01pd" )
626625 else :
627626 return StateSpace (self )
628627
629-
630628 # TODO: add discrete time check
631629 def returnScipySignalLTI (self ):
632630 """Return a list of a list of scipy.signal.lti objects.
@@ -750,7 +748,7 @@ def dcgain(self):
750748 """
751749 try :
752750 if self .isctime ():
753- gain = np .asarray (self .D - self .C .dot (np .linalg .solve (self .A , self .B )))
751+ gain = np .asarray (self .D - self .C .dot (np .linalg .solve (self .A , self .B )))
754752 else :
755753 gain = self .horner (1 )
756754 except LinAlgError :
@@ -839,18 +837,19 @@ def _convertToStateSpace(sys, **kw):
839837 # The following Doesn't work due to inconsistencies in ltisys:
840838 # return StateSpace([[]], [[]], [[]], eye(outputs, inputs))
841839 return StateSpace (0. , zeros ((1 , inputs )), zeros ((outputs , 1 )),
842- sys * ones ((outputs , inputs )))
840+ sys * ones ((outputs , inputs )))
843841
844842 # If this is a matrix, try to create a constant feedthrough
845843 try :
846844 D = _matrix (sys )
847845 return StateSpace ([], [], [], D )
848846 except Exception as e :
849847 print ("Failure to assume argument is matrix-like in" \
850- " _convertToStateSpace, result %s" % e )
848+ " _convertToStateSpace, result %s" % e )
851849
852850 raise TypeError ("Can't convert given type to StateSpace system." )
853851
852+
854853# TODO: add discrete time option
855854def _rss_generate (states , inputs , outputs , type ):
856855 """Generate a random state space.
@@ -876,13 +875,13 @@ def _rss_generate(states, inputs, outputs, type):
876875 # Check for valid input arguments.
877876 if states < 1 or states % 1 :
878877 raise ValueError ("states must be a positive integer. states = %g." %
879- states )
878+ states )
880879 if inputs < 1 or inputs % 1 :
881880 raise ValueError ("inputs must be a positive integer. inputs = %g." %
882- inputs )
881+ inputs )
883882 if outputs < 1 or outputs % 1 :
884883 raise ValueError ("outputs must be a positive integer. outputs = %g." %
885- outputs )
884+ outputs )
886885
887886 # Make some poles for A. Preallocate a complex array.
888887 poles = zeros (states ) + zeros (states ) * 0.j
@@ -892,13 +891,13 @@ def _rss_generate(states, inputs, outputs, type):
892891 if rand () < pRepeat and i != 0 and i != states - 1 :
893892 # Small chance of copying poles, if we're not at the first or last
894893 # element.
895- if poles [i - 1 ].imag == 0 :
894+ if poles [i - 1 ].imag == 0 :
896895 # Copy previous real pole.
897- poles [i ] = poles [i - 1 ]
896+ poles [i ] = poles [i - 1 ]
898897 i += 1
899898 else :
900899 # Copy previous complex conjugate pair of poles.
901- poles [i :i + 2 ] = poles [i - 2 :i ]
900+ poles [i :i + 2 ] = poles [i - 2 :i ]
902901 i += 2
903902 elif rand () < pReal or i == states - 1 :
904903 # No-oscillation pole.
@@ -915,7 +914,7 @@ def _rss_generate(states, inputs, outputs, type):
915914 mag = rand ()
916915 phase = 2. * math .pi * rand ()
917916 poles [i ] = complex (mag * cos (phase ), mag * sin (phase ))
918- poles [i + 1 ] = complex (poles [i ].real , - poles [i ].imag )
917+ poles [i + 1 ] = complex (poles [i ].real , - poles [i ].imag )
919918 i += 2
920919
921920 # Now put the poles in A as real blocks on the diagonal.
@@ -926,9 +925,9 @@ def _rss_generate(states, inputs, outputs, type):
926925 A [i , i ] = poles [i ].real
927926 i += 1
928927 else :
929- A [i , i ] = A [i + 1 , i + 1 ] = poles [i ].real
930- A [i , i + 1 ] = poles [i ].imag
931- A [i + 1 , i ] = - poles [i ].imag
928+ A [i , i ] = A [i + 1 , i + 1 ] = poles [i ].real
929+ A [i , i + 1 ] = poles [i ].imag
930+ A [i + 1 , i ] = - poles [i ].imag
932931 i += 2
933932 # Finally, apply a transformation so that A is not block-diagonal.
934933 while True :
@@ -970,7 +969,7 @@ def _rss_generate(states, inputs, outputs, type):
970969# Convert a MIMO system to a SISO system
971970# TODO: add discrete time check
972971def _mimo2siso (sys , input , output , warn_conversion = False ):
973- #pylint: disable=W0622
972+ # pylint: disable=W0622
974973 """
975974 Convert a MIMO system to a SISO system. (Convert a system with multiple
976975 inputs and/or outputs, to a system with a single input and output.)
@@ -1010,7 +1009,7 @@ def _mimo2siso(sys, input, output, warn_conversion=False):
10101009 "Selected output: {sel}, "
10111010 "number of system outputs: {ext}."
10121011 .format (sel = output , ext = sys .outputs ))
1013- #Convert sys to SISO if necessary
1012+ # Convert sys to SISO if necessary
10141013 if sys .inputs > 1 or sys .outputs > 1 :
10151014 if warn_conversion :
10161015 warn ("Converting MIMO system to SISO system. "
@@ -1065,7 +1064,7 @@ def _mimo2simo(sys, input, warn_conversion=False):
10651064 if sys .inputs > 1 :
10661065 if warn_conversion :
10671066 warn ("Converting MIMO system to SIMO system. "
1068- "Only input {i} is used." .format (i = input ))
1067+ "Only input {i} is used." .format (i = input ))
10691068 # $X = A*X + B*U
10701069 # Y = C*X + D*U
10711070 new_B = sys .B [:, input ]
0 commit comments