@@ -85,6 +85,35 @@ def test_DLQE(method):
8585 L , P , poles = dlqe (A , G , C , QN , RN , method = method )
8686 check_DLQE (L , P , poles , G , QN , RN )
8787
88+ @pytest .mark .parametrize ("method" , [None ,
89+ pytest .param ('slycot' , marks = pytest .mark .slycot ),
90+ 'scipy' ])
91+ def test_DLQE_return_filter_form (method ):
92+ A = np .array ([[0. , 1. ], [0. , 0.5 ]])
93+ G = np .eye (2 )
94+ C = np .array ([[1. , 0. ]])
95+ QN = np .eye (2 )
96+ RN = np .array ([[1. ]])
97+
98+ L_pred , P_pred , E_pred = dlqe (A , G , C , QN , RN , method = method )
99+ L_filter , P_filter , E_filter = dlqe (
100+ A , G , C , QN , RN , method = method , return_filter_form = True )
101+ L_expected = np .linalg .solve (
102+ (C @ P_pred @ C .T + RN ).T , (P_pred @ C .T ).T ).T
103+
104+ assert np .linalg .matrix_rank (A ) < A .shape [0 ]
105+ assert not np .allclose (L_filter , L_pred )
106+ np .testing .assert_allclose (P_filter , P_pred )
107+ np .testing .assert_allclose (E_filter , E_pred )
108+ np .testing .assert_allclose (L_filter , L_expected )
109+ np .testing .assert_allclose (L_pred , A @ L_filter )
110+ np .testing .assert_allclose (
111+ np .sort_complex (E_pred ),
112+ np .sort_complex (np .linalg .eigvals (A - L_pred @ C )))
113+ np .testing .assert_allclose (
114+ np .sort_complex (E_filter ),
115+ np .sort_complex (np .linalg .eigvals (A @ (np .eye (2 ) - L_filter @ C ))))
116+
88117def test_lqe_discrete ():
89118 """Test overloading of lqe operator for discrete-time systems"""
90119 csys = ct .rss (2 , 1 , 1 )
@@ -106,6 +135,13 @@ def test_lqe_discrete():
106135 np .testing .assert_almost_equal (S_lqe , S_dlqe )
107136 np .testing .assert_almost_equal (E_lqe , E_dlqe )
108137
138+ # Optional dlqe() keywords should pass through lqe() for DT systems
139+ K_lqe , S_lqe , E_lqe = ct .lqe (dsys , Q , R , return_filter_form = True )
140+ K_dlqe , S_dlqe , E_dlqe = ct .dlqe (dsys , Q , R , return_filter_form = True )
141+ np .testing .assert_almost_equal (K_lqe , K_dlqe )
142+ np .testing .assert_almost_equal (S_lqe , S_dlqe )
143+ np .testing .assert_almost_equal (E_lqe , E_dlqe )
144+
109145 # Calling lqe() with no timebase should call lqe()
110146 asys = ct .ss (csys .A , csys .B , csys .C , csys .D , dt = None )
111147 K_asys , S_asys , E_asys = ct .lqe (asys , Q , R )
0 commit comments