|
5 | 5 | "id": "c017196f", |
6 | 6 | "metadata": {}, |
7 | 7 | "source": [ |
8 | | - "# PVTOL LQR + EQF example\n", |
| 8 | + "# Output feedback control using LQR and extended Kalman filtering\n", |
9 | 9 | "RMM, 14 Feb 2022\n", |
10 | 10 | "\n", |
11 | | - "This notebook illustrates the implementation of an extended Kalman filter and the use of the estimated state for LQR feedback." |
| 11 | + "This notebook illustrates the implementation of an extended Kalman filter and the use of the estimated state for LQR feedback of a vectored thrust aircraft model." |
12 | 12 | ] |
13 | 13 | }, |
14 | 14 | { |
15 | 15 | "cell_type": "code", |
16 | | - "execution_count": 1, |
| 16 | + "execution_count": 11, |
17 | 17 | "id": "544525ab", |
18 | 18 | "metadata": {}, |
19 | 19 | "outputs": [], |
|
30 | 30 | "metadata": {}, |
31 | 31 | "source": [ |
32 | 32 | "## System definition\n", |
33 | | - "The dynamics of the system\n", |
34 | | - "with disturbances on the $x$ and $y$ variables is given by\n", |
| 33 | + "We consider a (planar) vertical takeoff and landing aircraf model:\n", |
| 34 | + "\n", |
| 35 | + "\n", |
| 36 | + "\n", |
| 37 | + "The dynamics of the system with disturbances on the $x$ and $y$ variables are given by\n", |
| 38 | + "\n", |
35 | 39 | "$$\n", |
36 | 40 | " \\begin{aligned}\n", |
37 | 41 | " m \\ddot x &= F_1 \\cos\\theta - F_2 \\sin\\theta - c \\dot x + d_x, \\\\\n", |
38 | 42 | " m \\ddot y &= F_1 \\sin\\theta + F_2 \\cos\\theta - c \\dot y - m g + d_y, \\\\\n", |
39 | 43 | " J \\ddot \\theta &= r F_1.\n", |
40 | 44 | " \\end{aligned}\n", |
41 | 45 | "$$\n", |
| 46 | + "\n", |
42 | 47 | "The measured values of the system are the position and orientation,\n", |
43 | 48 | "with added noise $n_x$, $n_y$, and $n_\\theta$:\n", |
| 49 | + "\n", |
44 | 50 | "$$\n", |
45 | 51 | " \\vec y = \\begin{bmatrix} x \\\\ y \\\\ \\theta \\end{bmatrix} + \n", |
46 | 52 | " \\begin{bmatrix} n_x \\\\ n_y \\\\ n_z \\end{bmatrix}.\n", |
47 | | - "$$\n" |
| 53 | + "$$" |
| 54 | + ] |
| 55 | + }, |
| 56 | + { |
| 57 | + "cell_type": "markdown", |
| 58 | + "id": "198a068d", |
| 59 | + "metadata": {}, |
| 60 | + "source": [ |
| 61 | + "The dynamics are defined in the `pvtol` module:" |
48 | 62 | ] |
49 | 63 | }, |
50 | 64 | { |
51 | 65 | "cell_type": "code", |
52 | | - "execution_count": 2, |
| 66 | + "execution_count": 12, |
53 | 67 | "id": "ffafed74", |
54 | 68 | "metadata": {}, |
55 | 69 | "outputs": [ |
|
93 | 107 | "print(noisy_pvtol)" |
94 | 108 | ] |
95 | 109 | }, |
| 110 | + { |
| 111 | + "cell_type": "markdown", |
| 112 | + "id": "be6ec05c", |
| 113 | + "metadata": {}, |
| 114 | + "source": [ |
| 115 | + "We also define the properties of the disturbances, noise, and initial conditions:" |
| 116 | + ] |
| 117 | + }, |
96 | 118 | { |
97 | 119 | "cell_type": "code", |
98 | | - "execution_count": 3, |
| 120 | + "execution_count": 13, |
99 | 121 | "id": "1e1ee7c9", |
100 | 122 | "metadata": {}, |
101 | 123 | "outputs": [], |
|
114 | 136 | "id": "e4c52c73", |
115 | 137 | "metadata": {}, |
116 | 138 | "source": [ |
117 | | - "## Control system design" |
| 139 | + "## Control system design\n", |
| 140 | + "\n", |
| 141 | + "We start be defining an extended Kalman filter to estimate the state of the system from the measured outputs." |
118 | 142 | ] |
119 | 143 | }, |
120 | 144 | { |
121 | 145 | "cell_type": "code", |
122 | | - "execution_count": 4, |
| 146 | + "execution_count": 14, |
123 | 147 | "id": "3647bf15", |
124 | 148 | "metadata": {}, |
125 | 149 | "outputs": [ |
126 | 150 | { |
127 | 151 | "name": "stdout", |
128 | 152 | "output_type": "stream", |
129 | 153 | "text": [ |
130 | | - "Object: sys[1]\n", |
| 154 | + "Object: sys[3]\n", |
131 | 155 | "Inputs (5): x0, x1, x2, F1, F2, \n", |
132 | 156 | "Outputs (6): xh0, xh1, xh2, xh3, xh4, xh5, \n", |
133 | 157 | "States (42): x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23], x[24], x[25], x[26], x[27], x[28], x[29], x[30], x[31], x[32], x[33], x[34], x[35], x[36], x[37], x[38], x[39], x[40], x[41], \n" |
|
175 | 199 | "print(estimator)" |
176 | 200 | ] |
177 | 201 | }, |
| 202 | + { |
| 203 | + "cell_type": "markdown", |
| 204 | + "id": "8c97626d", |
| 205 | + "metadata": {}, |
| 206 | + "source": [ |
| 207 | + "We now define an LQR controller, using a physically motivated weighting:" |
| 208 | + ] |
| 209 | + }, |
178 | 210 | { |
179 | 211 | "cell_type": "code", |
180 | | - "execution_count": 5, |
| 212 | + "execution_count": 15, |
181 | 213 | "id": "9787db61", |
182 | 214 | "metadata": {}, |
183 | 215 | "outputs": [ |
|
209 | 241 | "Object: xh5\n", |
210 | 242 | "Inputs (13): xd[0], xd[1], xd[2], xd[3], xd[4], xd[5], ud[0], ud[1], Dx, Dy, Nx, Ny, Nth, \n", |
211 | 243 | "Outputs (14): x0, x1, x2, x3, x4, x5, F1, F2, xh0, xh1, xh2, xh3, xh4, xh5, \n", |
212 | | - "States (48): noisy_pvtol_x0, noisy_pvtol_x1, noisy_pvtol_x2, noisy_pvtol_x3, noisy_pvtol_x4, noisy_pvtol_x5, sys[1]_x[0], sys[1]_x[1], sys[1]_x[2], sys[1]_x[3], sys[1]_x[4], sys[1]_x[5], sys[1]_x[6], sys[1]_x[7], sys[1]_x[8], sys[1]_x[9], sys[1]_x[10], sys[1]_x[11], sys[1]_x[12], sys[1]_x[13], sys[1]_x[14], sys[1]_x[15], sys[1]_x[16], sys[1]_x[17], sys[1]_x[18], sys[1]_x[19], sys[1]_x[20], sys[1]_x[21], sys[1]_x[22], sys[1]_x[23], sys[1]_x[24], sys[1]_x[25], sys[1]_x[26], sys[1]_x[27], sys[1]_x[28], sys[1]_x[29], sys[1]_x[30], sys[1]_x[31], sys[1]_x[32], sys[1]_x[33], sys[1]_x[34], sys[1]_x[35], sys[1]_x[36], sys[1]_x[37], sys[1]_x[38], sys[1]_x[39], sys[1]_x[40], sys[1]_x[41], \n" |
| 244 | + "States (48): noisy_pvtol_x0, noisy_pvtol_x1, noisy_pvtol_x2, noisy_pvtol_x3, noisy_pvtol_x4, noisy_pvtol_x5, sys[3]_x[0], sys[3]_x[1], sys[3]_x[2], sys[3]_x[3], sys[3]_x[4], sys[3]_x[5], sys[3]_x[6], sys[3]_x[7], sys[3]_x[8], sys[3]_x[9], sys[3]_x[10], sys[3]_x[11], sys[3]_x[12], sys[3]_x[13], sys[3]_x[14], sys[3]_x[15], sys[3]_x[16], sys[3]_x[17], sys[3]_x[18], sys[3]_x[19], sys[3]_x[20], sys[3]_x[21], sys[3]_x[22], sys[3]_x[23], sys[3]_x[24], sys[3]_x[25], sys[3]_x[26], sys[3]_x[27], sys[3]_x[28], sys[3]_x[29], sys[3]_x[30], sys[3]_x[31], sys[3]_x[32], sys[3]_x[33], sys[3]_x[34], sys[3]_x[35], sys[3]_x[36], sys[3]_x[37], sys[3]_x[38], sys[3]_x[39], sys[3]_x[40], sys[3]_x[41], \n" |
213 | 245 | ] |
214 | 246 | } |
215 | 247 | ], |
216 | 248 | "source": [ |
217 | | - "#\n", |
218 | | - "# LQR design w/ physically motivated weighting\n", |
219 | | - "#\n", |
220 | 249 | "# Shoot for 1 cm error in x, 10 cm error in y. Try to keep the angle\n", |
221 | 250 | "# less than 5 degrees in making the adjustments. Penalize side forces\n", |
222 | 251 | "# due to loss in efficiency.\n", |
|
256 | 285 | "id": "7bf558a0", |
257 | 286 | "metadata": {}, |
258 | 287 | "source": [ |
259 | | - "## Simulations" |
| 288 | + "## Simulations\n", |
| 289 | + "\n", |
| 290 | + "We now simulate the response of the system, starting with an instantiation of the noise:" |
260 | 291 | ] |
261 | 292 | }, |
262 | 293 | { |
263 | 294 | "cell_type": "code", |
264 | | - "execution_count": 6, |
| 295 | + "execution_count": 16, |
265 | 296 | "id": "c2583a0e", |
266 | 297 | "metadata": {}, |
267 | 298 | "outputs": [ |
|
302 | 333 | }, |
303 | 334 | { |
304 | 335 | "cell_type": "code", |
305 | | - "execution_count": 7, |
| 336 | + "execution_count": 17, |
306 | 337 | "id": "ad7a9750", |
307 | 338 | "metadata": {}, |
308 | 339 | "outputs": [ |
|
337 | 368 | }, |
338 | 369 | { |
339 | 370 | "cell_type": "code", |
340 | | - "execution_count": 8, |
| 371 | + "execution_count": 18, |
341 | 372 | "id": "c5f24119", |
342 | 373 | "metadata": {}, |
343 | 374 | "outputs": [ |
344 | 375 | { |
345 | 376 | "data": { |
346 | 377 | "text/plain": [ |
347 | | - "<matplotlib.legend.Legend at 0x7f85f8d6ebb0>" |
| 378 | + "<matplotlib.legend.Legend at 0x7fa431d8b3a0>" |
348 | 379 | ] |
349 | 380 | }, |
350 | | - "execution_count": 8, |
| 381 | + "execution_count": 18, |
351 | 382 | "metadata": {}, |
352 | 383 | "output_type": "execute_result" |
353 | 384 | }, |
|
389 | 420 | "id": "0c0d5c99", |
390 | 421 | "metadata": {}, |
391 | 422 | "source": [ |
392 | | - "### Full state feedback" |
| 423 | + "### Full state feedback\n", |
| 424 | + "\n", |
| 425 | + "As a comparison, we can investigate the response of the system if the exact state was available:" |
393 | 426 | ] |
394 | 427 | }, |
395 | 428 | { |
396 | 429 | "cell_type": "code", |
397 | | - "execution_count": 9, |
| 430 | + "execution_count": 19, |
398 | 431 | "id": "3b6a1f1c", |
399 | 432 | "metadata": {}, |
400 | 433 | "outputs": [ |
|
0 commit comments