-
Notifications
You must be signed in to change notification settings - Fork 446
Description
The pole placement function place fails in some simple situations.
This bug is related to the current implementation of place, which is a wrapper for slicot sb01bd. If PR 176 is accepted, this bug report will refer to place_varga instead.
Example of failure:
import numpy as np
import control as pc
A = np.array([[0, 1],[100, 0]])
B = np.array([[0],[1]])
Pdes = np.array([-20 + 10*1j, -20 - 10*1j])
K = pc.place(A, B, Pdes)
This raises the error (with python 2.7)
"ValueError: an attempt was made to place a complex conjugate pair on the location of a real eigenvalue"
The problem is related to how the alpha parameter is computed when calling sb01bd, which is calculated as
system_eigs = np.linalg.eig(A_mat)[0]
alpha = min(system_eigs.real);
Clearly, A has eigenvalues [-10, +10]. But np.lingalg.eigvals(A) reports
eigvals = [10.000000000000002, -9.9999999999999982], and so we have set
alpha = -9.9999999999999982
sb01bd will only move eigenvalues that are greater than alpha. It seems that sb01bd must calculate the eigenvalues slightly differently than scipy, so it thinks it has only one eigenvalue to move (namely, the one at +10). This evidently corresponds to error 4.
If we fudge the alpha parameter, and call the sb01bd wrapper directly, this works as expected
import numpy as np
from slycot import sb01bd
A = np.array([[0, 1],[100, 0]])
B = np.array([[0],[1]])
Pdes = np.array([-20 + 10*1j, -20 - 10*1j])
alpha = min(np.linalg.eigvals(A).real)*2;
A_z,w,nfp,nap,nup,K,Z = sb01bd(B.shape[0], B.shape[1],
len(Pdes), alpha, A, B, Pdes, 'C')
print 'Placed Poles: %s'%np.linalg.eigvals(A + B.dot(K))
# yields on my system:
# Placed Poles: [-20.+10.j -20.-10.j]
place() is not implemented for discrete time
sb01bd can place poles for discrete time systems. However, the current wrapper assumes a continuous time system, both in how alpha is calculated (it should be based on abs(eigvals) for discrete systems) and by passing C as the dico parameter. This is undocumented in the doc string.