|
26 | 26 | TransferFunction.pole |
27 | 27 | TransferFunction.zero |
28 | 28 | TransferFunction.feedback |
| 29 | +TransferFunction.minreal |
29 | 30 | TransferFunction.returnScipySignalLti |
30 | 31 | TransferFunction._common_den |
31 | 32 | _tfpolyToString |
|
76 | 77 |
|
77 | 78 | # External function declarations |
78 | 79 | from numpy import angle, any, array, empty, finfo, insert, ndarray, ones, \ |
79 | | - polyadd, polymul, polyval, roots, sort, sqrt, zeros, squeeze |
| 80 | + polyadd, polymul, polyval, roots, sort, sqrt, zeros, squeeze, where, \ |
| 81 | + delete, real, poly |
80 | 82 | from scipy.signal import lti |
81 | 83 | from copy import deepcopy |
82 | 84 | from lti import Lti |
@@ -505,6 +507,46 @@ def feedback(self, other, sign=-1): |
505 | 507 | # But this does not work correctly because the state size will be too |
506 | 508 | # large. |
507 | 509 |
|
| 510 | + def minreal(self, tol=None): |
| 511 | + """Remove cancelling pole/zero pairs from a transfer function""" |
| 512 | + # based on octave minreal |
| 513 | + |
| 514 | + # default accuracy |
| 515 | + from sys import float_info |
| 516 | + sqrt_eps = sqrt(float_info.epsilon) |
| 517 | + |
| 518 | + # pre-allocate arrays |
| 519 | + num = [[[] for j in range(self.inputs)] for i in range(self.outputs)] |
| 520 | + den = [[[] for j in range(self.inputs)] for i in range(self.outputs)] |
| 521 | + |
| 522 | + for i in range(self.outputs): |
| 523 | + for j in range(self.inputs): |
| 524 | + |
| 525 | + # split up in zeros, poles and gain |
| 526 | + newzeros = [] |
| 527 | + zeros = roots(self.num[i][j]) |
| 528 | + poles = roots(self.den[i][j]) |
| 529 | + gain = self.num[i][j][0] / self.den[i][j][0] |
| 530 | + |
| 531 | + # check all zeros |
| 532 | + for z in zeros: |
| 533 | + t = tol or \ |
| 534 | + 1000 * max(float_info.epsilon, abs(z) * sqrt_eps) |
| 535 | + idx = where(abs(z - poles) < t)[0] |
| 536 | + if len(idx): |
| 537 | + # cancel this zero against one of the poles |
| 538 | + poles = delete(poles, idx[0]) |
| 539 | + else: |
| 540 | + # keep this zero |
| 541 | + newzeros.append(z) |
| 542 | + |
| 543 | + # keep result |
| 544 | + num[i][j] = gain * real(poly(newzeros)) |
| 545 | + den[i][j] = real(poly(poles)) |
| 546 | + |
| 547 | + # end result |
| 548 | + return TransferFunction(num, den) |
| 549 | + |
508 | 550 | def returnScipySignalLti(self): |
509 | 551 | """Return a list of a list of scipy.signal.lti objects. |
510 | 552 | |
|
0 commit comments