Skip to content
Prev Previous commit
Next Next commit
[statefbk.py] Check that LQR problem is solvable
  • Loading branch information
don4get committed Apr 13, 2019
commit 8644954350cb77e90715f921aca247c5e347730c
7 changes: 7 additions & 0 deletions control/statefbk.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,13 @@ def lqr(*args):
else:
N = np.zeros((Q.shape[0], R.shape[1]))

# Check that LQR problem is solvable
QN = np.column_stack((Q, N))
NTR = np.column_stack((N.T, R))
QN_NTR = np.row_stack((QN, NTR))
if not np.all(np.linalg.eigvals(QN_NTR) >= 0):
raise ValueError("[Q N;N' R] should be positive semi-definite.")

# Check dimensions for consistency
nstates = B.shape[0]
ninputs = B.shape[1]
Expand Down
16 changes: 11 additions & 5 deletions control/tests/matlab_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,20 +410,26 @@ def testPlace(self):
def testAcker(self):
place(self.siso_ss1.A, self.siso_ss1.B, [-2, -2.5], method="acker")

@unittest.skipIf(not slycot_check(), "slycot not installed")
def test_lqr_not_semi_positive_definite_constraints(self):
np.testing.assert_raises(ValueError, lqr, self.siso_ss1.A, self.siso_ss1.B, np.eye(2),
-np.eye(1))

np.testing.assert_raises(ValueError, lqr, self.siso_ss2.A, self.siso_ss2.B, np.eye(3),
np.eye(1), [[1], [1], [2]])

@unittest.skipIf(not slycot_check(), "slycot not installed")
def testLQR(self):
def test_lqr(self):
(K, S, E) = lqr(self.siso_ss1.A, self.siso_ss1.B, np.eye(2), np.eye(1))

# Should work if [Q N;N' R] is positive semi-definite
(K, S, E) = lqr(self.siso_ss2.A, self.siso_ss2.B, 10*np.eye(3), \
np.eye(1), [[1], [1], [2]])
(K, S, E) = lqr(self.siso_ss2.A, self.siso_ss2.B, 10*np.eye(3),
np.eye(1), [[1], [1], [2]])

@unittest.skip("check not yet implemented")
def testLQR_checks(self):
# Make sure we get a warning if [Q N;N' R] is not positive semi-definite
(K, S, E) = lqr(self.siso_ss2.A, self.siso_ss2.B, np.eye(3), \
np.eye(1), [[1], [1], [2]])
np.eye(1), [[1], [1], [2]])

def testRss(self):
rss(1)
Expand Down