StateSpace.zero() now supports MIMO systems · python-control/python-control@8607fb0

@@ -54,8 +54,7 @@

5454

import math

5555

import numpy as np

5656

from numpy import all, angle, any, array, asarray, concatenate, cos, delete, \

57-

dot, empty, exp, eye, matrix, ones, poly, poly1d, roots, shape, sin, \

58-

zeros, squeeze

57+

dot, empty, exp, eye, isinf, matrix, ones, pad, shape, sin, zeros, squeeze

5958

from numpy.random import rand, randn

6059

from numpy.linalg import solve, eigvals, matrix_rank

6160

from numpy.linalg.linalg import LinAlgError

@@ -516,17 +515,22 @@ def pole(self):

516515

def zero(self):

517516

"""Compute the zeros of a state space system."""

518517519-

if self.inputs > 1 or self.outputs > 1:

520-

raise NotImplementedError("StateSpace.zeros is currently \

521-

implemented only for SISO systems.")

518+

# This implements the QZ algorithm for finding transmission zeros from

519+

# https://dspace.mit.edu/bitstream/handle/1721.1/841/P-0802-06587335.pdf.

520+

# The QZ algorithm solves the generalized eigenvalue problem: given

521+

# `L = [A, B; C, D]` and `M = [I_nxn 0]`, find all finite λ for which

522+

# there exist nontrivial solutions of the equation `Lz - λMz`.

523+

L = concatenate((concatenate((self.A, self.B), axis=1),

524+

concatenate((self.C, self.D), axis=1)), axis=0)

525+

M = pad(eye(self.A.shape[0]), ((0, self.C.shape[0]),

526+

(0, self.B.shape[1])), "constant")

522527523-

den = poly1d(poly(self.A))

524-

# Compute the numerator based on zeros

525-

#! TODO: This is currently limited to SISO systems

526-

num = poly1d(poly(self.A - dot(self.B, self.C)) + ((self.D[0, 0] - 1) *

527-

den))

528-529-

return roots(num)

528+

if self.states:

529+

return np.array([x for x in sp.linalg.eigvals(L, M,

530+

overwrite_a=True)

531+

if not isinf(x)])

532+

else:

533+

return np.array([])

530534531535

# Feedback around a state space system

532536

def feedback(self, other=1, sign=-1):