@@ -85,6 +85,95 @@ 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+
89+ def test_lqe_symmetrizes_projected_process_covariance ():
90+ A = np .array ([
91+ [- 1.945215 , 0.071519 , 0.060276 , 0.054488 , 0.042365 ],
92+ [0.064589 , - 1.956241 , 0.089177 , 0.043759 , 0.038344 ],
93+ [0.079173 , 0.052889 , - 1.943196 , 0.096366 , 0.038344 ],
94+ [0. , 0. , 0. , - 2.920827 , 0.052889 ],
95+ [0. , 0. , 0. , 0.056804 , - 2.90744 ],
96+ ])
97+ G = np .array ([
98+ [0.087129 , 0.020218 , 0.83262 ],
99+ [0.778157 , 0.870012 , 0.978618 ],
100+ [0.799159 , 0.461479 , 0.780529 ],
101+ [0. , 0. , 0. ],
102+ [0. , 0. , 0. ],
103+ ])
104+ C = np .array ([
105+ [0.118274 , 0.639921 , 0.143353 , 0.944669 , 0.521848 ],
106+ [0.414662 , 0.264556 , 0.774234 , 0.45615 , 0.568434 ],
107+ [0.01879 , 0.617635 , 0.612096 , 0.616934 , 0.943748 ],
108+ ])
109+ QN = np .array ([
110+ [3.661526 , - 1.465017 , 1.00303 ],
111+ [- 1.465017 , 1.013103 , - 0.582237 ],
112+ [1.00303 , - 0.582237 , 0.502097 ],
113+ ])
114+ RN = np .array ([
115+ [1.17295 , - 0.446977 , - 0.010618 ],
116+ [- 0.446977 , 3.675234 , 0.558705 ],
117+ [- 0.010618 , 0.558705 , 0.53198 ],
118+ ])
119+
120+ L , P , poles = lqe (A , G , C , QN , RN , method = 'scipy' )
121+
122+ assert L .shape == (A .shape [0 ], C .shape [0 ])
123+ assert P .shape == A .shape
124+ assert poles .shape == (A .shape [0 ],)
125+
126+
127+ def test_dlqe_symmetrizes_projected_process_covariance ():
128+ A = np .array ([
129+ [0.109763 , 0.143038 , 0.120553 , 0.054488 , 0.042365 ],
130+ [0.108977 , 0.084731 , 0.129179 , 0.043759 , 0.089177 ],
131+ [0.192733 , 0.076688 , 0.158345 , 0.096366 , 0.038344 ],
132+ [0. , 0. , 0. , 0.279173 , 0.052889 ],
133+ [0. , 0. , 0. , 0.056804 , 0.29256 ],
134+ ])
135+ G = np .array ([
136+ [0.087129 , 0.020218 , 0.83262 ],
137+ [0.778157 , 0.870012 , 0.978618 ],
138+ [0.799159 , 0.461479 , 0.780529 ],
139+ [0. , 0. , 0. ],
140+ [0. , 0. , 0. ],
141+ ])
142+ C = np .array ([
143+ [0.118274 , 0.639921 , 0.143353 , 0.944669 , 0.521848 ],
144+ [0.414662 , 0.264556 , 0.774234 , 0.45615 , 0.568434 ],
145+ [0.01879 , 0.617635 , 0.612096 , 0.616934 , 0.943748 ],
146+ ])
147+ QN = np .array ([
148+ [3.661526 , - 1.465017 , 1.00303 ],
149+ [- 1.465017 , 1.013103 , - 0.582237 ],
150+ [1.00303 , - 0.582237 , 0.502097 ],
151+ ])
152+ RN = np .array ([
153+ [1.17295 , - 0.446977 , - 0.010618 ],
154+ [- 0.446977 , 3.675234 , 0.558705 ],
155+ [- 0.010618 , 0.558705 , 0.53198 ],
156+ ])
157+
158+ L , P , poles = dlqe (A , G , C , QN , RN , method = 'scipy' )
159+
160+ assert L .shape == (A .shape [0 ], C .shape [0 ])
161+ assert P .shape == A .shape
162+ assert poles .shape == (A .shape [0 ],)
163+
164+
165+ @pytest .mark .parametrize ("cdlqe" , [lqe , dlqe ])
166+ def test_lqe_rejects_user_supplied_asymmetric_covariance (cdlqe ):
167+ A = np .diag ([0.4 , 0.5 ])
168+ G = np .eye (2 )
169+ C = np .array ([[1. , 0. ]])
170+ QN = np .array ([[1. , 1. ], [0. , 1. ]])
171+ RN = np .array ([[1. ]])
172+
173+ with pytest .raises (ControlArgument , match = "QN must be a symmetric matrix" ):
174+ cdlqe (A , G , C , QN , RN , method = 'scipy' )
175+
176+
88177def test_lqe_discrete ():
89178 """Test overloading of lqe operator for discrete-time systems"""
90179 csys = ct .rss (2 , 1 , 1 )
0 commit comments