solvers

buzz.solvers

Functions

BH1checker(bh)

BH1controllerQZQh(bh, Q, Z, Qh[, print])

BH1setup(ss, z2, zinf, y, w, u[, print])

BH1solverQZQh(bh, Q, igsq[, asq_eff, print, ...])

This solver assumes that Einf is null and this impacts a number of choices

BH1solverset(ss[, z2, zinf, y, w, u, ...])

Takes a wield.controls.MIMO.ss object.

LQGsolverset(sys[, z2, y, w, u])

Takes a wield.controls.MIMO.ss object.

getKalmanGain(sys, processNoise, ...)

Get the Kalman Gain for a system.

lqe([sys, A, B1, C2, D21])

Calculate the Kalman gain for a system of the form:

lqe_controller([sys, A, B2, C1, D12])

Calculate the Riccati feedback gain for a system of the form:

solve_continuous_are_scipy(a, b, q, r[, e, ...])

Solves the continuous-time algebraic Riccati equation (CARE).

solve_continuous_are_special(a, b, q, r[, ...])

Details

BH1checker(bh)[source]
BH1controllerQZQh(bh, Q, Z, Qh, print=<function <lambda>>)[source]
BH1setup(ss, z2, zinf, y, w, u, print=<function <lambda>>)[source]
BH1solverQZQh(bh, Q, igsq, asq_eff=1, print=<function <lambda>>, vprint=<function <lambda>>)[source]

This solver assumes that Einf is null and this impacts a number of choices

BH1solverset(ss, z2=['S', 'O'], zinf=['Zinf'], y=['D'], w=['F1scaled', 'F2scaled'], u=['T'], igsq_start=None, igsq_capture=None, igsq_factor=1.1, print=<function <lambda>>)[source]

Takes a wield.controls.MIMO.ss object.

The arguments are the names of the inputs and outputs for a mixed H2, Hinfinity problem.

Assumes that the statespace has already been transposed. TODO, allow it to not assume this, and transpose it inside?

starting 1/gamma^2 value to use igsq_start=1e-9

end 1/gamma^2 value to seek. May terminate before that! igsq_end=1

factor to increment 1/gamma^2 by while iterating igsq_factor=1.1

list of inverse gammas to refine the search on and return in the set igsq_capture=None

if it is None, it will return them every decade

TODO, make the transition score and the refine score less magical numbers. Not sure how to auto-scale them yet

LQGsolverset(sys, z2=['S', 'O'], y=['D'], w=['F1scaled', 'F2scaled'], u=['T'])[source]

Takes a wield.controls.MIMO.ss object.

The arguments are the names of the inputs and outputs for a mixed H2, Hinfinity problem.

Assumes that the statespace has already been transposed. TODO, allow it to not assume this, and transpose it inside?

starting 1/gamma^2 value to use igsq_start=1e-9

end 1/gamma^2 value to seek. May terminate before that! igsq_end=1

factor to increment 1/gamma^2 by while iterating igsq_factor=1.1

list of inverse gammas to refine the search on and return in the set igsq_capture=None

if it is None, it will return them every decade

TODO, make the transition score and the refine score less magical numbers. Not sure how to auto-scale them yet

getKalmanGain(sys, processNoise, measurementNoise)[source]

Get the Kalman Gain for a system.

Parameters:
  • sys (control.lti) – The system to get the Kalman Gain for.

  • processNoise (np.array) – The process noise covariance matrix.

  • measurementNoise (np.array) – The measurement noise covariance matrix.

Returns:

The Kalman Gain.

Return type:

np.array

lqe(sys=None, A=None, B1=None, C2=None, D21=None)[source]
Calculate the Kalman gain for a system of the form:

dot{x} = A x + B_1 u_1 + B_2 u_2

y_1 = C_1 x + D_{12} u_2

y_2 = C_2 x + D_{21} u_1

In this case the Q matrix is the process noise covariance matrix and is given by B1 @ B1.T

Parameters:
  • sys (Bunch) – A Bunch object containing the system and the input output dictionary. this system should be reduced to only have white noise inputs and measured outputs

  • A (array) – The A matrix of the system.

  • B1 (array) – The B_1 matrix of the system. See summary of the system above to see what this matrix is.

  • C2 (array) – The C_2 matrix of the system. See summary of the system above to see what this matrix is.

  • D21 (array) – The D_{21} matrix of the system. See summary of the system above to see what this matrix is.

  • RN (_type_) – The measurement noise covariance matrix.

Returns:

Kalman gain : Riccati solution

lqe_controller(sys=None, A=None, B2=None, C1=None, D12=None)[source]
Calculate the Riccati feedback gain for a system of the form:

dot{x} = A x + B_1 u_1 + B_2 u_2

y_1 = C_1 x + D_{12} u_2

y_2 = C_2 x + D_{21} u_1

Parameters:
  • sys (Bunch) – A Bunch object containing the system and the input output dictionary. this system should be reduced to only have white noise inputs and measured outputs

  • A (array) – The A matrix of the system.

  • B2 (array) – The B_2 matrix of the system. See summary of the system above to see what this matrix is.

  • C1 (array) – The C_1 matrix of the system. See summary of the system above to see what this matrix is.

  • D12 (array) – The D_{12} matrix of the system. See summary of the system above to see what this matrix is.

  • RN (_type_) – The measurement noise covariance matrix.

Returns:

Riccati control feedback : CTARE solution

solve_continuous_are_scipy(a, b, q, r, e=None, s=None, balanced=True, positive_definite=False, symmettrization_method='mirror')[source]

Solves the continuous-time algebraic Riccati equation (CARE).

The CARE is defined as

\[X A + A^H X - X B R^{-1} B^H X + Q = 0\]

The limitations for a solution to exist are :

  • All eigenvalues of \(A\) on the right half plane, should be controllable.

  • The associated hamiltonian pencil (See Notes), should have eigenvalues sufficiently away from the imaginary axis.

Moreover, if e or s is not precisely None, then the generalized version of CARE

\[E^HXA + A^HXE - (E^HXB + S) R^{-1} (B^HXE + S^H) + Q = 0\]

is solved. When omitted, e is assumed to be the identity and s is assumed to be the zero matrix with sizes compatible with a and b, respectively.

Parameters:
  • a ((M, M) array_like) – Square matrix

  • b ((M, N) array_like) – Input

  • q ((M, M) array_like) – Input

  • r ((N, N) array_like) – Nonsingular square matrix

  • e ((M, M) array_like, optional) – Nonsingular square matrix

  • s ((M, N) array_like, optional) – Input

  • balanced (bool, optional) – The boolean that indicates whether a balancing step is performed on the data. The default is set to True.

Returns:

x – Solution to the continuous-time algebraic Riccati equation.

Return type:

(M, M) ndarray

Raises:

LinAlgError – For cases where the stable subspace of the pencil could not be isolated. See Notes section and the references for details.

See also

solve_discrete_are

Solves the discrete-time algebraic Riccati equation

Notes

The equation is solved by forming the extended hamiltonian matrix pencil, as described in [1], \(H - \lambda J\) given by the block matrices

[ A    0    B ]             [ E   0    0 ]
[-Q  -A^H  -S ] - \lambda * [ 0  E^H   0 ]
[ S^H B^H   R ]             [ 0   0    0 ]

and using a QZ decomposition method.

In this algorithm, the fail conditions are linked to the symmetry of the product \(U_2 U_1^{-1}\) and condition number of \(U_1\). Here, \(U\) is the 2m-by-m matrix that holds the eigenvectors spanning the stable subspace with 2-m rows and partitioned into two m-row matrices. See [1] and [2] for more details.

In order to improve the QZ decomposition accuracy, the pencil goes through a balancing step where the sum of absolute values of \(H\) and \(J\) entries (after removing the diagonal entries of the sum) is balanced following the recipe given in [3].

Added in version 0.11.0.

References

Examples

Given a, b, q, and r solve for x:

>>> from scipy import linalg
>>> a = np.array([[4, 3], [-4.5, -3.5]])
>>> b = np.array([[1], [-1]])
>>> q = np.array([[9, 6], [6, 4.]])
>>> r = 1
>>> x = linalg.solve_continuous_are(a, b, q, r)
>>> x
array([[ 21.72792206,  14.48528137],
       [ 14.48528137,   9.65685425]])
>>> np.allclose(a.T.dot(x) + x.dot(a)-x.dot(b).dot(b.T).dot(x), -q)
True
solve_continuous_are_special(a, b, q, r, e=None, s=None, balanced=True, positive_definite=False, symmettrization_method='mirror')[source]