From 920649b393dc739f6a9dd3302946bf26e279f4bd Mon Sep 17 00:00:00 2001 From: bnavigator Date: Tue, 18 Aug 2020 13:08:35 +0200 Subject: [PATCH] no log(0) in automatic timevector calculation --- control/timeresp.py | 83 ++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/control/timeresp.py b/control/timeresp.py index b472cb2fd..fa4ced2bd 100644 --- a/control/timeresp.py +++ b/control/timeresp.py @@ -61,7 +61,7 @@ Initial Author: Eike Welk Date: 12 May 2011 -Modified: Sawyer B. Fuller (minster@uw.edu) to add discrete-time +Modified: Sawyer B. Fuller (minster@uw.edu) to add discrete-time capability and better automatic time vector creation Date: June 2020 @@ -463,14 +463,14 @@ def step_response(sys, T=None, X0=0., input=None, output=None, T_num=None, LTI system to simulate T: array-like or number, optional - Time vector, or simulation time duration if a number. If T is not - provided, an attempt is made to create it automatically from the - dynamics of sys. If sys is continuous-time, the time increment dt - is chosen small enough to show the fastest mode, and the simulation - time period tfinal long enough to show the slowest mode, excluding + Time vector, or simulation time duration if a number. If T is not + provided, an attempt is made to create it automatically from the + dynamics of sys. If sys is continuous-time, the time increment dt + is chosen small enough to show the fastest mode, and the simulation + time period tfinal long enough to show the slowest mode, excluding poles at the origin. If this results in too many time steps (>5000), - dt is reduced. If sys is discrete-time, only tfinal is computed, and - tfinal is reduced if it requires too many simulation steps. + dt is reduced. If sys is discrete-time, only tfinal is computed, and + tfinal is reduced if it requires too many simulation steps. X0: array-like or number, optional Initial condition (default = 0) @@ -483,10 +483,10 @@ def step_response(sys, T=None, X0=0., input=None, output=None, T_num=None, output: int Index of the output that will be used in this simulation. Set to None to not trim outputs - + T_num: number, optional - Number of time steps to use in simulation if T is not provided as an - array (autocomputed if not given); ignored if sys is discrete-time. + Number of time steps to use in simulation if T is not provided as an + array (autocomputed if not given); ignored if sys is discrete-time. transpose: bool 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, LTI system to simulate T: array-like or number, optional - Time vector, or simulation time duration if a number (time vector is + Time vector, or simulation time duration if a number (time vector is autocomputed if not given, see :func:`step_response` for more detail) T_num: number, optional - Number of time steps to use in simulation if T is not provided as an - array (autocomputed if not given); ignored if sys is discrete-time. + Number of time steps to use in simulation if T is not provided as an + array (autocomputed if not given); ignored if sys is discrete-time. SettlingTimeThreshold: float value, optional 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, sys = _get_ss_simo(sys) if T is None or np.asarray(T).size == 1: T = _default_time_vector(sys, N=T_num, tfinal=T) - + T, yout = step_response(sys, T) # Steady state value @@ -640,7 +640,7 @@ def initial_response(sys, T=None, X0=0., input=0, output=None, T_num=None, LTI system to simulate T: array-like or number, optional - Time vector, or simulation time duration if a number (time vector is + Time vector, or simulation time duration if a number (time vector is autocomputed if not given; see :func:`step_response` for more detail) 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, output: int Index of the output that will be used in this simulation. Set to None to not trim outputs - + T_num: number, optional - Number of time steps to use in simulation if T is not provided as an - array (autocomputed if not given); ignored if sys is discrete-time. + Number of time steps to use in simulation if T is not provided as an + array (autocomputed if not given); ignored if sys is discrete-time. transpose: bool 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, LTI system to simulate T: array-like or number, optional - Time vector, or simulation time duration if a number (time vector is + Time vector, or simulation time duration if a number (time vector is autocomputed if not given; see :func:`step_response` for more detail) 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, to not trim outputs T_num: number, optional - Number of time steps to use in simulation if T is not provided as an - array (autocomputed if not given); ignored if sys is discrete-time. + Number of time steps to use in simulation if T is not provided as an + array (autocomputed if not given); ignored if sys is discrete-time. transpose: bool If True, transpose all input and output arrays (for backward @@ -830,56 +830,55 @@ def _ideal_tfinal_and_dt(sys): constant = 7.0 tolerance = 1e-10 A = ssdata(sys)[0] - if A.shape == (0,0): + if A.shape == (0,0): # no dynamics - tfinal = constant * 1.0 + tfinal = constant * 1.0 dt = sys.dt if isdtime(sys, strict=True) else 1.0 else: poles = sp.linalg.eigvals(A) - if isdtime(sys, strict=True): - poles = np.log(poles)/sys.dt # z-poles to s-plane using s=(lnz)/dt - # calculate ideal dt if isdtime(sys, strict=True): + # z-poles to s-plane using s=(lnz)/dt, no ln(0) + poles = np.log(poles[abs(poles) > 0])/sys.dt dt = sys.dt else: fastest_natural_frequency = max(abs(poles)) dt = 1/constant / fastest_natural_frequency - + # calculate ideal tfinal poles = poles[abs(poles.real) > tolerance] # ignore poles near im axis - if poles.size == 0: + if poles.size == 0: slowest_decay_rate = 1.0 else: slowest_decay_rate = min(abs(poles.real)) - tfinal = constant / slowest_decay_rate + tfinal = constant / slowest_decay_rate return tfinal, dt -# test below: ct with pole at the origin is 7 seconds, ct with pole at .5 is 14 s long, +# test below: ct with pole at the origin is 7 seconds, ct with pole at .5 is 14 s long, def _default_time_vector(sys, N=None, tfinal=None): - """Returns a time vector suitable for observing the response of the - both the slowest poles and fastest resonant modes. if system is + """Returns a time vector suitable for observing the response of the + both the slowest poles and fastest resonant modes. if system is discrete-time, N is ignored """ - + N_max = 5000 N_min_ct = 100 N_min_dt = 7 # more common to see just a few samples in discrete-time - + ideal_tfinal, ideal_dt = _ideal_tfinal_and_dt(sys) - + if isdtime(sys, strict=True): - if tfinal is None: + if tfinal is None: # for discrete time, change from ideal_tfinal if N too large/small N = int(np.clip(ideal_tfinal/sys.dt, N_min_dt, N_max))# [N_min, N_max] tfinal = sys.dt * N - else: + else: N = int(tfinal/sys.dt) - else: - if tfinal is None: + else: + if tfinal is None: # for continuous time, simulate to ideal_tfinal but limit N tfinal = ideal_tfinal - if N is None: + if N is None: N = int(np.clip(tfinal/ideal_dt, N_min_ct, N_max)) # N<-[N_min, N_max] - + return np.linspace(0, tfinal, N, endpoint=False) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy