|
54 | 54 | import scipy as sp # SciPy library (used all over) |
55 | 55 | import numpy as np # NumPy library |
56 | 56 | import re # regular expressions |
57 | | -from copy import deepcopy |
58 | 57 |
|
59 | 58 | # Import MATLAB-like functions that are defined in other packages |
60 | 59 | from scipy.signal import zpk2ss, ss2zpk, tf2zpk, zpk2tf |
|
81 | 80 | from ..exception import ControlArgument |
82 | 81 |
|
83 | 82 | # Import MATLAB-like functions that can be used as-is |
84 | | -from ..ctrlutil import unwrap |
| 83 | +from ..ctrlutil import * |
85 | 84 | from ..freqplot import nyquist, gangof4 |
86 | 85 | from ..nichols import nichols, nichols_grid |
87 | 86 | from ..bdalg import series, parallel, negate, feedback, append, connect |
|
90 | 89 | from ..delay import pade |
91 | 90 | from ..modelsimp import hsvd, balred, modred, minreal |
92 | 91 | from ..mateqn import lyap, dlyap, dare, care |
| 92 | +from ..margins import margin |
| 93 | +from ..rlocus import rlocus |
| 94 | +from ..dtime import c2d |
93 | 95 |
|
94 | 96 | # Import functions specific to Matlab compatibility package |
95 | 97 | from .timeresp import * |
|
386 | 388 |
|
387 | 389 | """ |
388 | 390 |
|
389 | | -from ..margins import stability_margins |
390 | | - |
391 | | -def margin(*args): |
392 | | - """Calculate gain and phase margins and associated crossover frequencies |
393 | | -
|
394 | | - Function ``margin`` takes either 1 or 3 parameters. |
395 | | -
|
396 | | - Parameters |
397 | | - ---------- |
398 | | - sys : StateSpace or TransferFunction |
399 | | - Linear SISO system |
400 | | - mag, phase, w : array_like |
401 | | - Input magnitude, phase (in deg.), and frequencies (rad/sec) from |
402 | | - bode frequency response data |
403 | | -
|
404 | | - Returns |
405 | | - ------- |
406 | | - gm, pm, Wcg, Wcp : float |
407 | | - Gain margin gm, phase margin pm (in deg), gain crossover frequency |
408 | | - (corresponding to phase margin) and phase crossover frequency |
409 | | - (corresponding to gain margin), in rad/sec of SISO open-loop. |
410 | | - If more than one crossover frequency is detected, returns the lowest |
411 | | - corresponding margin. |
412 | | -
|
413 | | - Examples |
414 | | - -------- |
415 | | - >>> sys = tf(1, [1, 2, 1, 0]) |
416 | | - >>> gm, pm, Wcg, Wcp = margin(sys) |
417 | | -
|
418 | | - """ |
419 | | - if len(args) == 1: |
420 | | - sys = args[0] |
421 | | - margin = stability_margins(sys) |
422 | | - elif len(args) == 3: |
423 | | - margin = stability_margins(args) |
424 | | - else: |
425 | | - raise ValueError("Margin needs 1 or 3 arguments; received %i." |
426 | | - % len(args)) |
427 | | - |
428 | | - return margin[0], margin[1], margin[4], margin[3] |
429 | | - |
430 | 391 | def dcgain(*args): |
431 | 392 | ''' |
432 | 393 | Compute the gain of the system in steady state. |
@@ -480,68 +441,3 @@ def dcgain(*args): |
480 | 441 | #gain = - C * A**-1 * B + D |
481 | 442 | gain = sys.D - sys.C * sys.A.I * sys.B |
482 | 443 | return gain |
483 | | - |
484 | | -def damp(sys, doprint=True): |
485 | | - ''' |
486 | | - Compute natural frequency, damping and poles of a system |
487 | | -
|
488 | | - The function takes 1 or 2 parameters |
489 | | -
|
490 | | - Parameters |
491 | | - ---------- |
492 | | - sys: LTI (StateSpace or TransferFunction) |
493 | | - A linear system object |
494 | | - doprint: |
495 | | - if true, print table with values |
496 | | -
|
497 | | - Returns |
498 | | - ------- |
499 | | - wn: array |
500 | | - Natural frequencies of the poles |
501 | | - damping: array |
502 | | - Damping values |
503 | | - poles: array |
504 | | - Pole locations |
505 | | -
|
506 | | - See Also |
507 | | - -------- |
508 | | - pole |
509 | | - ''' |
510 | | - wn, damping, poles = sys.damp() |
511 | | - if doprint: |
512 | | - print('_____Eigenvalue______ Damping___ Frequency_') |
513 | | - for p, d, w in zip(poles, damping, wn) : |
514 | | - if abs(p.imag) < 1e-12: |
515 | | - print("%10.4g %10.4g %10.4g" % |
516 | | - (p.real, 1.0, -p.real)) |
517 | | - else: |
518 | | - print("%10.4g%+10.4gj %10.4g %10.4g" % |
519 | | - (p.real, p.imag, d, w)) |
520 | | - return wn, damping, poles |
521 | | - |
522 | | -# Convert a continuous time system to a discrete time system |
523 | | -def c2d(sysc, Ts, method='zoh'): |
524 | | - ''' |
525 | | - Return a discrete-time system |
526 | | -
|
527 | | - Parameters |
528 | | - ---------- |
529 | | - sysc: LTI (StateSpace or TransferFunction), continuous |
530 | | - System to be converted |
531 | | -
|
532 | | - Ts: number |
533 | | - Sample time for the conversion |
534 | | -
|
535 | | - method: string, optional |
536 | | - Method to be applied, |
537 | | - 'zoh' Zero-order hold on the inputs (default) |
538 | | - 'foh' First-order hold, currently not implemented |
539 | | - 'impulse' Impulse-invariant discretization, currently not implemented |
540 | | - 'tustin' Bilinear (Tustin) approximation, only SISO |
541 | | - 'matched' Matched pole-zero method, only SISO |
542 | | - ''' |
543 | | - # Call the sample_system() function to do the work |
544 | | - sysd = sample_system(sysc, Ts, method) |
545 | | - if isinstance(sysc, StateSpace) and not isinstance(sysd, StateSpace): |
546 | | - return _convertToStateSpace(sysd) |
547 | | - return sysd |
0 commit comments