2020except ImportError :
2121 ab13md = None
2222
23- __all__ = ['stability_margins' , 'phase_crossover_frequencies' , 'margin' ,\
23+ __all__ = ['stability_margins' , 'phase_crossover_frequencies' , 'margin' ,
2424 'disk_margins' ]
2525
2626# private helper functions
@@ -173,6 +173,7 @@ def fun(wdt):
173173
174174 return z , w
175175
176+
176177def _likely_numerical_inaccuracy (sys ):
177178 # crude, conservative check for if
178179 # num(z)*num(1/z) << den(z)*den(1/z) for DT systems
@@ -468,6 +469,7 @@ def phase_crossover_frequencies(sys):
468469
469470 return omega , gains
470471
472+
471473def margin (* args ):
472474 """
473475 margin(sys) \
@@ -522,25 +524,26 @@ def margin(*args):
522524
523525 return margin [0 ], margin [1 ], margin [3 ], margin [4 ]
524526
527+
525528def disk_margins (L , omega , skew = 0.0 , returnall = False ):
526- """Compute disk -based stability margins for SISO or MIMO LTI
527- loop transfer function.
529+ """Disk -based stability margins of loop transfer function.
530+ ----------------------------------------------------------------
528531
529532 Parameters
530533 ----------
531534 L : `StateSpace` or `TransferFunction`
532- Linear SISO or MIMO loop transfer function system
535+ Linear SISO or MIMO loop transfer function.
533536 omega : sequence of array_like
534537 1D array of (non-negative) frequencies (rad/s) at which
535- to evaluate the disk-based stability margins
538+ to evaluate the disk-based stability margins.
536539 skew : float or array_like, optional
537- skew parameter(s) for disk margin calculation .
538- skew = 0.0 (default) uses the "balanced" sensitivity function 0.5*(S - T)
539- skew = 1.0 uses the sensitivity function S
540- skew = -1.0 uses the complementary sensitivity function T
540+ skew parameter(s) for disk margin (default = 0.0) .
541+ skew = 0.0 (default) "balanced" sensitivity 0.5*(S - T).
542+ skew = 1.0 sensitivity function S.
543+ skew = -1.0 complementary sensitivity function T.
541544 returnall : bool, optional
542- If True, return frequency-dependent margins. If False (default),
543- return only the worst-case (minimum) margins.
545+ If True, return frequency-dependent margins.
546+ If False (default), return worst-case (minimum) margins.
544547
545548 Returns
546549 -------
@@ -554,15 +557,16 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
554557 Example
555558 --------
556559 >> omega = np.logspace(-1, 3, 1001)
557- >> P = control.ss([[0, 10], [-10, 0]], np.eye(2), [[1, 10], [-10, 1]], 0)
560+ >> P = control.ss([[0, 10], [-10, 0]], np.eye(2), [[1, 10],
561+ [-10, 1]], 0)
558562 >> K = control.ss([], [], [], [[1, -2], [0, 1]])
559563 >> L = P * K
560564 >> DM, DGM, DPM = control.disk_margins(L, omega, skew=0.0)
561565 """
562566
563567 # First argument must be a system
564568 if not isinstance (L , (statesp .StateSpace , xferfcn .TransferFunction )):
565- raise ValueError (\
569+ raise ValueError (
566570 "Loop gain must be state-space or transfer function object" )
567571
568572 # Loop transfer function must be square
@@ -571,7 +575,7 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
571575
572576 # Need slycot if L is MIMO, for mu calculation
573577 if not L .issiso () and ab13md == None :
574- raise ControlMIMONotImplemented (\
578+ raise ControlMIMONotImplemented (
575579 "Need slycot to compute MIMO disk_margins" )
576580
577581 # Get dimensions of feedback system
@@ -589,8 +593,9 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
589593 if not L .issiso ():
590594 ST_jw = ST_jw .transpose (2 , 0 , 1 )
591595
592- # Frequency-dependent complex disk margin, computed using upper bound of
593- # the structured singular value, a.k.a. "mu", of (S + (skew - I)/2).
596+ # Frequency-dependent complex disk margin, computed using
597+ # upper bound of the structured singular value, a.k.a. "mu",
598+ # of (S + (skew - I)/2).
594599 DM = np .zeros (omega .shape )
595600 DGM = np .zeros (omega .shape )
596601 DPM = np .zeros (omega .shape )
@@ -602,11 +607,11 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
602607 # of the frequency response.
603608 DM [ii ] = 1.0 / ST_mag [ii ]
604609 else :
605- # For the MIMO case, the norm on (S + (skew - I)/2) assumes a
606- # single complex uncertainty block diagonal uncertainty
607- # structure. AB13MD provides an upper bound on this norm at
608- # the given frequency omega[ii].
609- DM [ii ] = 1.0 / ab13md (ST_jw [ii ], np .array (num_loops * [1 ]),\
610+ # For the MIMO case, the norm on (S + (skew - I)/2)
611+ # assumes a single complex uncertainty block diagonal
612+ # uncertainty structure. AB13MD provides an upper bound
613+ # on this norm at the given frequency omega[ii].
614+ DM [ii ] = 1.0 / ab13md (ST_jw [ii ], np .array (num_loops * [1 ]),
610615 np .array (num_loops * [2 ]))[0 ]
611616
612617 # Disk-based gain margin (dB) and phase margin (deg)
@@ -626,7 +631,8 @@ def disk_margins(L, omega, skew=0.0, returnall=False):
626631 if np .isinf (gamma_max ):
627632 DPM [ii ] = 90.0
628633 else :
629- DPM [ii ] = (1 + gamma_min * gamma_max ) / (gamma_min + gamma_max )
634+ DPM [ii ] = (1 + gamma_min * gamma_max ) \
635+ / (gamma_min + gamma_max )
630636 if abs (DPM [ii ]) >= 1.0 :
631637 DPM [ii ] = float ('Inf' )
632638 else :
0 commit comments