6161Initial Author: Eike Welk
6262Date: 12 May 2011
6363
64- Modified: Sawyer B. Fuller (minster@uw.edu) to add discrete-time
64+ Modified: Sawyer B. Fuller (minster@uw.edu) to add discrete-time
6565capability and better automatic time vector creation
6666Date: June 2020
6767
@@ -463,14 +463,14 @@ def step_response(sys, T=None, X0=0., input=None, output=None, T_num=None,
463463 LTI system to simulate
464464
465465 T: array-like or number, optional
466- Time vector, or simulation time duration if a number. If T is not
467- provided, an attempt is made to create it automatically from the
468- dynamics of sys. If sys is continuous-time, the time increment dt
469- is chosen small enough to show the fastest mode, and the simulation
470- time period tfinal long enough to show the slowest mode, excluding
466+ Time vector, or simulation time duration if a number. If T is not
467+ provided, an attempt is made to create it automatically from the
468+ dynamics of sys. If sys is continuous-time, the time increment dt
469+ is chosen small enough to show the fastest mode, and the simulation
470+ time period tfinal long enough to show the slowest mode, excluding
471471 poles at the origin. If this results in too many time steps (>5000),
472- dt is reduced. If sys is discrete-time, only tfinal is computed, and
473- tfinal is reduced if it requires too many simulation steps.
472+ dt is reduced. If sys is discrete-time, only tfinal is computed, and
473+ tfinal is reduced if it requires too many simulation steps.
474474
475475 X0: array-like or number, optional
476476 Initial condition (default = 0)
@@ -483,10 +483,10 @@ def step_response(sys, T=None, X0=0., input=None, output=None, T_num=None,
483483 output: int
484484 Index of the output that will be used in this simulation. Set to None
485485 to not trim outputs
486-
486+
487487 T_num: number, optional
488- Number of time steps to use in simulation if T is not provided as an
489- array (autocomputed if not given); ignored if sys is discrete-time.
488+ Number of time steps to use in simulation if T is not provided as an
489+ array (autocomputed if not given); ignored if sys is discrete-time.
490490
491491 transpose: bool
492492 If True, transpose all input and output arrays (for backward
@@ -550,12 +550,12 @@ def step_info(sys, T=None, T_num=None, SettlingTimeThreshold=0.02,
550550 LTI system to simulate
551551
552552 T: array-like or number, optional
553- Time vector, or simulation time duration if a number (time vector is
553+ Time vector, or simulation time duration if a number (time vector is
554554 autocomputed if not given, see :func:`step_response` for more detail)
555555
556556 T_num: number, optional
557- Number of time steps to use in simulation if T is not provided as an
558- array (autocomputed if not given); ignored if sys is discrete-time.
557+ Number of time steps to use in simulation if T is not provided as an
558+ array (autocomputed if not given); ignored if sys is discrete-time.
559559
560560 SettlingTimeThreshold: float value, optional
561561 Defines the error to compute settling time (default = 0.02)
@@ -588,7 +588,7 @@ def step_info(sys, T=None, T_num=None, SettlingTimeThreshold=0.02,
588588 sys = _get_ss_simo (sys )
589589 if T is None or np .asarray (T ).size == 1 :
590590 T = _default_time_vector (sys , N = T_num , tfinal = T )
591-
591+
592592 T , yout = step_response (sys , T )
593593
594594 # Steady state value
@@ -640,7 +640,7 @@ def initial_response(sys, T=None, X0=0., input=0, output=None, T_num=None,
640640 LTI system to simulate
641641
642642 T: array-like or number, optional
643- Time vector, or simulation time duration if a number (time vector is
643+ Time vector, or simulation time duration if a number (time vector is
644644 autocomputed if not given; see :func:`step_response` for more detail)
645645
646646 X0: array-like or number, optional
@@ -655,10 +655,10 @@ def initial_response(sys, T=None, X0=0., input=0, output=None, T_num=None,
655655 output: int
656656 Index of the output that will be used in this simulation. Set to None
657657 to not trim outputs
658-
658+
659659 T_num: number, optional
660- Number of time steps to use in simulation if T is not provided as an
661- array (autocomputed if not given); ignored if sys is discrete-time.
660+ Number of time steps to use in simulation if T is not provided as an
661+ array (autocomputed if not given); ignored if sys is discrete-time.
662662
663663 transpose: bool
664664 If True, transpose all input and output arrays (for backward
@@ -730,7 +730,7 @@ def impulse_response(sys, T=None, X0=0., input=0, output=None, T_num=None,
730730 LTI system to simulate
731731
732732 T: array-like or number, optional
733- Time vector, or simulation time duration if a number (time vector is
733+ Time vector, or simulation time duration if a number (time vector is
734734 autocomputed if not given; see :func:`step_response` for more detail)
735735
736736 X0: array-like or number, optional
@@ -746,8 +746,8 @@ def impulse_response(sys, T=None, X0=0., input=0, output=None, T_num=None,
746746 to not trim outputs
747747
748748 T_num: number, optional
749- Number of time steps to use in simulation if T is not provided as an
750- array (autocomputed if not given); ignored if sys is discrete-time.
749+ Number of time steps to use in simulation if T is not provided as an
750+ array (autocomputed if not given); ignored if sys is discrete-time.
751751
752752 transpose: bool
753753 If True, transpose all input and output arrays (for backward
@@ -830,56 +830,55 @@ def _ideal_tfinal_and_dt(sys):
830830 constant = 7.0
831831 tolerance = 1e-10
832832 A = ssdata (sys )[0 ]
833- if A .shape == (0 ,0 ):
833+ if A .shape == (0 ,0 ):
834834 # no dynamics
835- tfinal = constant * 1.0
835+ tfinal = constant * 1.0
836836 dt = sys .dt if isdtime (sys , strict = True ) else 1.0
837837 else :
838838 poles = sp .linalg .eigvals (A )
839- if isdtime (sys , strict = True ):
840- poles = np .log (poles )/ sys .dt # z-poles to s-plane using s=(lnz)/dt
841-
842839 # calculate ideal dt
843840 if isdtime (sys , strict = True ):
841+ # z-poles to s-plane using s=(lnz)/dt, no ln(0)
842+ poles = np .log (poles [abs (poles ) > 0 ])/ sys .dt
844843 dt = sys .dt
845844 else :
846845 fastest_natural_frequency = max (abs (poles ))
847846 dt = 1 / constant / fastest_natural_frequency
848-
847+
849848 # calculate ideal tfinal
850849 poles = poles [abs (poles .real ) > tolerance ] # ignore poles near im axis
851- if poles .size == 0 :
850+ if poles .size == 0 :
852851 slowest_decay_rate = 1.0
853852 else :
854853 slowest_decay_rate = min (abs (poles .real ))
855- tfinal = constant / slowest_decay_rate
854+ tfinal = constant / slowest_decay_rate
856855
857856 return tfinal , dt
858857
859- # test below: ct with pole at the origin is 7 seconds, ct with pole at .5 is 14 s long,
858+ # test below: ct with pole at the origin is 7 seconds, ct with pole at .5 is 14 s long,
860859def _default_time_vector (sys , N = None , tfinal = None ):
861- """Returns a time vector suitable for observing the response of the
862- both the slowest poles and fastest resonant modes. if system is
860+ """Returns a time vector suitable for observing the response of the
861+ both the slowest poles and fastest resonant modes. if system is
863862 discrete-time, N is ignored """
864-
863+
865864 N_max = 5000
866865 N_min_ct = 100
867866 N_min_dt = 7 # more common to see just a few samples in discrete-time
868-
867+
869868 ideal_tfinal , ideal_dt = _ideal_tfinal_and_dt (sys )
870-
869+
871870 if isdtime (sys , strict = True ):
872- if tfinal is None :
871+ if tfinal is None :
873872 # for discrete time, change from ideal_tfinal if N too large/small
874873 N = int (np .clip (ideal_tfinal / sys .dt , N_min_dt , N_max ))# [N_min, N_max]
875874 tfinal = sys .dt * N
876- else :
875+ else :
877876 N = int (tfinal / sys .dt )
878- else :
879- if tfinal is None :
877+ else :
878+ if tfinal is None :
880879 # for continuous time, simulate to ideal_tfinal but limit N
881880 tfinal = ideal_tfinal
882- if N is None :
881+ if N is None :
883882 N = int (np .clip (tfinal / ideal_dt , N_min_ct , N_max )) # N<-[N_min, N_max]
884-
883+
885884 return np .linspace (0 , tfinal , N , endpoint = False )
0 commit comments