|
58 | 58 | from .statesp import _convertToStateSpace, _mimo2simo, _mimo2siso
|
59 | 59 | from .lti import isdtime, isctime
|
60 | 60 |
|
61 |
| -__all__ = ['forced_response', 'step_response', 'initial_response', |
| 61 | +__all__ = ['forced_response', 'step_response', 'step_info', 'initial_response', |
62 | 62 | 'impulse_response']
|
63 | 63 |
|
64 | 64 | # Helper function for checking array-like parameters
|
@@ -433,6 +433,98 @@ def step_response(sys, T=None, X0=0., input=None, output=None,
|
433 | 433 |
|
434 | 434 | return T, yout
|
435 | 435 |
|
| 436 | +def step_info(sys, T=None, SettlingTimeThreshold=0.02, RiseTimeLimits=(0.1,0.9)): |
| 437 | + ''' |
| 438 | + Step response characteristics (Rise time, Settling Time, Peak and others). |
| 439 | +
|
| 440 | + Parameters |
| 441 | + ---------- |
| 442 | + sys: StateSpace, or TransferFunction |
| 443 | + LTI system to simulate |
| 444 | +
|
| 445 | + T: array-like object, optional |
| 446 | + Time vector (argument is autocomputed if not given) |
| 447 | +
|
| 448 | + SettlingTimeThreshold: float value, optional |
| 449 | + Defines the error to compute settling time (default = 0.02) |
| 450 | +
|
| 451 | + RiseTimeLimits: tuple (lower_threshold, upper_theshold) |
| 452 | + Defines the lower and upper threshold for RiseTime computation |
| 453 | +
|
| 454 | + Returns |
| 455 | + ------- |
| 456 | + S: a dictionary containing: |
| 457 | + RiseTime: Time from 10% to 90% of the steady-state value. |
| 458 | + SettlingTime: Time to enter inside a default error of 2% |
| 459 | + SettlingMin: Minimum value after RiseTime |
| 460 | + SettlingMax: Maximum value after RiseTime |
| 461 | + Overshoot: Percentage of the Peak relative to steady value |
| 462 | + Undershoot: Percentage of undershoot |
| 463 | + Peak: Absolute peak value |
| 464 | + PeakTime: time of the Peak |
| 465 | + SteadyStateValue: Steady-state value |
| 466 | +
|
| 467 | +
|
| 468 | + See Also |
| 469 | + -------- |
| 470 | + step, lsim, initial, impulse |
| 471 | +
|
| 472 | + Examples |
| 473 | + -------- |
| 474 | + >>> info = step_info(sys, T) |
| 475 | + ''' |
| 476 | + sys = _get_ss_simo(sys) |
| 477 | + if T is None: |
| 478 | + if isctime(sys): |
| 479 | + T = _default_response_times(sys.A, 1000) |
| 480 | + else: |
| 481 | + # For discrete time, use integers |
| 482 | + tvec = _default_response_times(sys.A, 1000) |
| 483 | + T = range(int(np.ceil(max(tvec)))) |
| 484 | + |
| 485 | + T, yout = step_response(sys, T) |
| 486 | + |
| 487 | + # Steady state value |
| 488 | + InfValue = yout[-1] |
| 489 | + |
| 490 | + # RiseTime |
| 491 | + tr_lower_index = (np.where(yout >= RiseTimeLimits[0] * InfValue)[0])[0] |
| 492 | + tr_upper_index = (np.where(yout >= RiseTimeLimits[1] * InfValue)[0])[0] |
| 493 | + RiseTime = T[tr_upper_index] - T[tr_lower_index] |
| 494 | + |
| 495 | + # SettlingTime |
| 496 | + sup_margin = (1. + SettlingTimeThreshold) * InfValue |
| 497 | + inf_margin = (1. - SettlingTimeThreshold) * InfValue |
| 498 | + # find Steady State looking for the first point out of specified limits |
| 499 | + for i in reversed(range(T.size)): |
| 500 | + if((yout[i] <= inf_margin) | (yout[i] >= sup_margin)): |
| 501 | + SettlingTime = T[i + 1] |
| 502 | + break |
| 503 | + |
| 504 | + # Peak |
| 505 | + PeakIndex = np.abs(yout).argmax() |
| 506 | + PeakValue = yout[PeakIndex] |
| 507 | + PeakTime = T[PeakIndex] |
| 508 | + SettlingMax = (yout).max() |
| 509 | + SettlingMin = (yout[tr_upper_index:]).min() |
| 510 | + # I'm really not very confident about UnderShoot: |
| 511 | + UnderShoot = yout.min() |
| 512 | + OverShoot = 100. * (yout.max() - InfValue) / (InfValue - yout[0]) |
| 513 | + |
| 514 | + # Return as a dictionary |
| 515 | + S = { |
| 516 | + 'RiseTime': RiseTime, |
| 517 | + 'SettlingTime': SettlingTime, |
| 518 | + 'SettlingMin': SettlingMin, |
| 519 | + 'SettlingMax': SettlingMax, |
| 520 | + 'Overshoot': OverShoot, |
| 521 | + 'Undershoot': UnderShoot, |
| 522 | + 'Peak': PeakValue, |
| 523 | + 'PeakTime': PeakTime, |
| 524 | + 'SteadyStateValue': InfValue |
| 525 | + } |
| 526 | + |
| 527 | + return S |
436 | 528 |
|
437 | 529 | def initial_response(sys, T=None, X0=0., input=0, output=None,
|
438 | 530 | transpose=False, return_x=False):
|
|
0 commit comments