diff --git a/book/_config.yml b/book/_config.yml index 91cbeac..c7d8fc2 100644 --- a/book/_config.yml +++ b/book/_config.yml @@ -19,6 +19,7 @@ sphinx: html_js_files: - https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js - tikzjax.js # Uses a local copy to expose the process_function + - remove-darkmode.js thebe_config: use_thebe_lite: true exclude_patterns: ["**/_*.yml", "**/*.md", "**/*.ipynb"] @@ -27,7 +28,7 @@ sphinx: text: Example Maglev Assignment image_light: maggy.png # Put your logo for the light mode here (can be the same as image_dark) image_dark: maggy.png # Put your logo for the dark mode here (can be the same as image_light) - repository_url: "https://github.com/ForceoftheCyber/CyberBook" #add your own repo URL here + repository_url: "https://github.com/ForceoftheCyber/CyberBook" # add your own repo URL here path_to_docs: "book" repository_branch: "main" use_edit_page_button: true @@ -42,6 +43,12 @@ sphinx: chtml: { mtextInheritFont: true # To typeset text within math prettier } + tex: { + inlineMath: [['$', '$'], ['\(', '\)']] + } + inverter_all: false + html_context: + default_mode: "light" extra_extensions: - sphinx.ext.imgconverter - jupyterbook_patches diff --git a/book/_static/2D_Maggy_Model.png b/book/_static/2D_Maggy_Model.png new file mode 100644 index 0000000..22bb698 Binary files /dev/null and b/book/_static/2D_Maggy_Model.png differ diff --git a/book/_static/chuo_shinkansen.jpg b/book/_static/chuo_shinkansen.jpg new file mode 100644 index 0000000..cd675ca Binary files /dev/null and b/book/_static/chuo_shinkansen.jpg differ diff --git a/book/_static/custom.css b/book/_static/custom.css index 30150c9..23345f2 100644 --- a/book/_static/custom.css +++ b/book/_static/custom.css @@ -4,5 +4,7 @@ Force p-elements in .jupyter-widgets to use the same color as the header-element Could alternatively use --pst-color-text-base so it matches the static p-elements in the book. */ .jupyter-widgets p { - color: var(--pst-color-muted) + color: var(--pst-color-muted); + font-size: 16px; + margin-bottom: 0; } diff --git a/book/_static/maglev_history/NASA_FLOAT.jpg b/book/_static/maglev_history/NASA_FLOAT.jpg new file mode 100644 index 0000000..007da0f Binary files /dev/null and b/book/_static/maglev_history/NASA_FLOAT.jpg differ diff --git a/book/_static/maglev_history/Suspension.png b/book/_static/maglev_history/Suspension.png new file mode 100644 index 0000000..0eede59 Binary files /dev/null and b/book/_static/maglev_history/Suspension.png differ diff --git a/book/_static/maglev_history/crealev_octo88.png b/book/_static/maglev_history/crealev_octo88.png new file mode 100644 index 0000000..4146347 Binary files /dev/null and b/book/_static/maglev_history/crealev_octo88.png differ diff --git a/book/_static/maglev_history/planar_motors.jpg b/book/_static/maglev_history/planar_motors.jpg new file mode 100644 index 0000000..1b4b4ad Binary files /dev/null and b/book/_static/maglev_history/planar_motors.jpg differ diff --git a/book/_static/maglev_history/quanser_maglev_module.jpg b/book/_static/maglev_history/quanser_maglev_module.jpg new file mode 100644 index 0000000..c038b16 Binary files /dev/null and b/book/_static/maglev_history/quanser_maglev_module.jpg differ diff --git a/book/_static/remove-themeswitch.js b/book/_static/remove-themeswitch.js new file mode 100644 index 0000000..acb86ef --- /dev/null +++ b/book/_static/remove-themeswitch.js @@ -0,0 +1,9 @@ +/** + * Fix to disable theme switching on the page. Removes the the button for switching themes. + */ +document.addEventListener("DOMContentLoaded", function () { + const btn = document.getElementsByClassName("btn btn-sm nav-link pst-navbar-icon theme-switch-button")[0]; + if (btn) { + btn.remove(); + } + }); \ No newline at end of file diff --git a/book/_static/transrapid.jpg b/book/_static/transrapid.jpg new file mode 100644 index 0000000..2b08caf Binary files /dev/null and b/book/_static/transrapid.jpg differ diff --git a/book/_toc.yml b/book/_toc.yml index 7de4c7a..d105d51 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -2,17 +2,20 @@ format: jb-book root: intro.md parts: - - caption: PID Control + - caption: Introduction numbered: True chapters: - - file: chapters/pid_control/intro.md - sections: - - file: chapters/pid_control/aligning_expectations.ipynb - - file: chapters/pid_control/checking_prerequisite_knowledge.ipynb - - file: chapters/pid_control/working_towards_the_ilos_of_this_section.ipynb - - file: chapters/pid_control/metacognition_and_reflection.ipynb - - file: chapters/simulator/maglev_dynamical_system_simulation.ipynb - + - file: chapters/introducing_maggy.md + - file: chapters/Magnetic_levitation_history.md + - caption: Assignment + numbered: True + chapters: + - file: chapters/ilo_and_prerequisites.ipynb + - file: chapters/system_description.ipynb + - file: chapters/equilibrium_analysis.ipynb + - file: chapters/linearization_and_stability.ipynb + - file: chapters/controller_design.ipynb + - file: chapters/robustness_and_model_validation.ipynb - file: references.md # - file: changelog.md # - file: credits.md diff --git a/book/chapters/Magnetic_levitation_history.md b/book/chapters/Magnetic_levitation_history.md new file mode 100644 index 0000000..2afc79b --- /dev/null +++ b/book/chapters/Magnetic_levitation_history.md @@ -0,0 +1,245 @@ +# A Brief History of Magnetic Levitation Technology + +```{note} This is an abstract from the MAGGY - Hands on control learning with a maglev system +``` + +
+
+

Maggy is far from being the first magnetic levitation system to be created. +In this chapter, we outline some other types of magnetic levitation systems and technology and discuss how Maggy fits in. +Most of the history and theory can be found in the book by Han and Kim1

+

The Birth of Maglev

+ +

The word Maglev was first introduced and popularized in the early +20th century as a term to describe a type of high-speed train that +relies on magnetic levitation to reduce friction.

+ +

The first commercial Maglev train, the Transrapid, was developed +in Germany and began operations in 1984. This train was an elec- +tromagnetic maglev. Instead of wheels, the Transrapid had a set of +electromagnets that wrapped around the train lines, and the train +levitated through the attractive force between these magnets and elec- +tromagnets in the tracks. This, combined with a linear motor propul- +sive system, has allowed the most recent version of the Transrapid +system to reach speeds up to 505 km/h.

+ +

Since the Transrapid, there has been an explosion in the devel- +opment of Maglev train technology, with the most promising being +electrodynamic maglev trains. Instead of lifting coils, these trains rely +on superconductors to passively levitate above or between a set of +guiding coils. These coils are not actively controlled, but act effec- +tively as permanent magnets that perfectly oppose the magnetic field +of the superconductors once the train reaches a certain speed, due +to induced current from the superconductors. As with the electro- +magnetic maglevs, propulsion is achieved with a linear motor, while +propulsion below the levitation speed is achieved using conventional +wheels. The electrodynamic levitation technology allows for bet- +ter stability and lower cost levitation, with trains already reaching +speeds of up to 607 km/h.

+ +
+
+

1T Hyung-Suk Han and Dong-Sung + Kim. Magnetic levitation, volume 247. + Springer, 2016

+ + +

Figure 4.1: The world-famousShanghai airport maglev + train is an 08 series Tran- + srapid [Xplore, 2024]

+ + +

Figure 4.2: The Ch ¯u ¯o +Shinkansen is an electrody- +namic maglev that is set to +start operation between Tokyo +and Nagoya in Japan from +2027 [Museum, 2024]

+
+
+ +
+
+

Modes of magnetic levitation

+

+ The above outlines two important magnetic levitation concepts; elec- +tromagnetic suspension and electromagnetic levitation. As illustrated in +Figure 4.3, suspension simply alludes to the fact that something is +suspended (against gravity) using magnetic attraction, while levita- +tion uses magnetic repulsion to counteract the gravitational force. As +already mentioned, the Transrapid is a perfect example of the for- +mer, while electrodynamic maglevs rely somewhat on both of these +concepts to achieve levitation. +

+ +

+ The above concepts are examples of static magnetic levitation. A +famous theorem by Samuel Ernshaw states that it is not possible to +achieve stable levitation using any configuration of magnets with +fixed magnetization.2 Thus, any static levitation system relies on +some sort of external corrective force for levitate. This is usually +where the electro part comes in; stability is usually solved by mea- +suring the position of the levitating magnet and stabilizing it using a +controller to adjust the current in electromagnetic solenoids. Suspen- +sion systems are naturally stable in the lateral direction (like a pen- +dulum), and thus only require vertical corrective action, while levi- +tation systems are unstable in the lateral direction (like an inverted +pendulum), and thus require lateral stabilization. In the following, +we will see examples of how the concepts above are commonly ap- +plied in industrial and commercial systems. +

+
+
+

+ Figure 4.3: A comparison be- +tween magnetic suspension and +magnetic levitation. +

+

+ 2 Roberto Bassani. Earnshaw (1805– +1888) and passive magnetic levitation. +Meccanica, 41:375–389, 2006 +

+
+
+
+
+

Maglev in Science & Industry

+

A good example of magnetic suspension in an industrial setting is +magnetic bearings. These bearings use electromagnets to actively +control the position of the rotor to be in the center of the bearing, +allowing for near frictionless rotation. However, the additional bulk +and complexity added by the suspension system make these bearings +large and expensive, and they are therefore mostly used in costly +and high-precision devices, including medical equipment, industrial +machinery, and scientific instruments.

+

+ A planar motor, such as those offered by Planar Motors Inc. and + Beckhoff 3, is a more sophisticated application of magnetic levitation. + These consist of a magnetic mover that is levitating very close to a +base filled with electromagnets. These motors operate on a flat sur- +face and can move in multiple directions without physical contact, +offering high precision and flexibility. Planar motors are essential in +industries that require precise positioning and high-speed motion, +such as semiconductor manufacturing and automated assembly lines. +

+

NASA’s Flexible Levitation on a Track (FLOAT) system offers a +unique application of magnetic levitation. This system is a conceptual +magnetic road that can be rolled out onto the lunar surface for +the transportation of material when future moon bases are to be +constructed. Like planar motors, the roads are magnetic bases with +small loaded carts levitating above them. Unlike planar motors and +most other commercial uses of magnetic levitation technology, the +levitation is achieved passively using diamagnetism, circumventing +Earnshaw’s theorem and allowing for levitation without the use of +electromagnets.

+

Magnetic levitation technology is also hugely important in other +fields of science. Aside from the use of planar motors for the pre- +cise movement of scientific equipment and components, the most +prominent use of magnetic levitation is the concept of magnetic con- +finement. The two largest research projects today — the CERN Large +Hadron Collider and the ITER Tokamak fusion reactor — would both +not be possible without magnetic confinement to guide particles/- +plasma without physical contact.4

+
+
+ +

+ Figure 4.4: An illustration of +a planar motor developed by +Planar Motors Inc. [PMI, 2024] +

+

+ 3 PMI. Planar motors, 2024. URL +https://planarmotor.com/en. Ac- +cessed: 2024-05-25; and Beckhoff Au- +tomation. Beckhoff - xplanar planar +motor system, 2024. URL. +Accessed: 2024-05-25 +

+ +

Figure 4.5: An illustration +of NASA’s FLOAT con- +cept [NASA, 2024]

+

+4 ITER Organization. Iter - the machine, +2024. URL https://www.iter.org/mach. +Accessed: 2024-05-28; and CERN. Cern + - the large hadron collider, + 2024. URL. + Accessed: 2024-05-28 +

+
+
+
+
+

Maglev in Consumer Products

+

Maglev technology has also made its way into consumer products. +For the most part, these are almost direct applications of the suspension and levitation concepts mentioned above and are mostly +used as novelty ornaments or display cases. A common example that +most people are probably familiar with is a floating globe suspended +below an electromagnet.

+

More relevant for us, though, are the systems that rely on magnetic +levitation. These systems typically consist of a base equipped with +electromagnets and/or permanent magnets, and optical or magnetic +sensors, that keep a permanent magnet levitating stably above the +base. Among these is Levimoon, which sells magnetically levitating +moons that light up using battery power.5 Floately and Flyte are known for their floating lightbulbs that are cleverly designed to light +up using magnetic induction.6 The latter offers a range of levitation +platforms that can even keep a magnet levitating in any orientation. +Having enough power to lift heavy objects is a common issue, and +so the company Crealev specializes in magnetic levitation modules +that are capable of lifting heavy loads with a large gap between the +levitating magnet and the base.7

+
+
+ +

Figure 4.6: The Crealev Octo88 +levitation module, capable of +lifting a load of 10 kg [Crealev, +2024]

+

5 Levimoon. Levimoon, 2024. URL +http://ww.levimoon.com/. Accessed: +2024-05-24

+

+6 Floately. Floately, 2024. URL https: +//www.floately.com/. Accessed: 2024- +05-24; and Flyte. Flyte, 2024. URL +https://flytestore.com/. Accessed: +2024-05-24

+

7 Crealev. Crealev, 2024. URL https: +//www.crealev.com/. Accessed: 2024- +06-04

+
+
+
+
+

Maglev in Education & Maggy

+

In terms of teaching, there are not many alternatives offered for small +magnetic levitation systems. As far as the authors know, the only +available magnetic levitation system for this is the Quanser magnetic +suspension lab.8 Quanser is a leader in engineering education soluions and offers this lab as part of their portfolio, to allow students +to study the principles of magnetic levitation and control systems in +a hands-on environment. This platform is widely used in universi- +ties and research institutions for teaching and research purposes. It +is a magnetic suspension system where an iron ball is lifted using an +electromagnet and an optical sensor. They offer a comprehensive lab +guide and seamless integration into Matlab and Simulink. However, +their lab is proprietary, and each unit can be very costly. Further- +more, the suspension design effectively makes this a 1DOF system, +limiting the potential applications and educational benefits.

+

In contrast, Maggy is a magnetic levitation system, similar to the +more common commercial levitation platforms mentioned above, +that is not proprietary, and it is designed to be cheap enough for +students to build themselves or bring home.

+
+
+ +

Figure 4.7: The Quanser mag- +netic suspension lab [Quanser, +2024]

+
+
+ diff --git a/book/chapters/controller_design.ipynb b/book/chapters/controller_design.ipynb new file mode 100644 index 0000000..3e9addb --- /dev/null +++ b/book/chapters/controller_design.ipynb @@ -0,0 +1,276 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "96d73890", + "metadata": { + "tags": [ + "auto-execute-page", + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "%pip install ipyquizjb\n", + "%pip install ipysim\n", + "from ipyquizjb.questions import display_questions, display_package" + ] + }, + { + "cell_type": "markdown", + "id": "82975921", + "metadata": {}, + "source": [ + "# Controller Design\n", + "\n", + "The maglev system -- with the above measurements of magnetic field in the x direction and the change of variables on the input -- can be controlled by a **Proportional-Derivative (PD) controller**:\n", + "\n", + "$$\n", + "u := K_p y + K_d \\dot{y},\n", + "$$\n", + "\n", + "where:\n", + "- $K_p$ is a **proportional gain**, which counteracts deviations from the equilibrium point, and\n", + "- $K_d$ is a **derivative gain**, which damps oscillations by reacting to the change in position.\n", + "\n", + "By choosing appropriate values for $K_p$ and $K_d$, the controller ensures that the levitating magnet stays levitating.\n", + "\n", + "\n", + "## Understanding Controller Effects\n", + "Below is a simulation of a maglev system in closed loop with a PD controller, initialized away from the equilirium point.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b374edf", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "from ipysim.simulation_ui import interactive_simulation\n", + "from ipysim.simulations.simulate_maglev import simulate, plot_maglev, create_maglev_animation\n", + "from ipysim.params import default_params, default_state0\n", + "\n", + "detailed_animation_fn = lambda t, sol: create_maglev_animation(t, sol, default_state0())\n", + "\n", + "# Here is the function that can be passed to the interactive_simulation() function for evaluation.\n", + "def evaluation_check(sol, t):\n", + " pass\n", + "\n", + "sliders_config = {\n", + " \"Kp\": {\"default\": 300.0, \"min\": 0.0, \"max\": 1000.0, \"step\": 10.0, \"description\": \"Kp\"},\n", + " \"Kd\": {\"default\": 30.0, \"min\": 0.0, \"max\": 200.0, \"step\": 5.0, \"description\": \"Kd\"},\n", + "}\n", + "\n", + "interactive_simulation(\n", + " simulate_fn=simulate,\n", + " plot_fn=plot_maglev,\n", + " animation_fn=detailed_animation_fn,\n", + " params=default_params(),\n", + " state0=default_state0(),\n", + " T=5.0,\n", + " evaluation_function=None,\n", + " sliders_config=sliders_config\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "a7645164", + "metadata": {}, + "source": [ + "Try to experiment with the system, obseving its response, and answer the following quiz." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10b0dd95", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "display_package(\n", + " {\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Are both the proportional term (\\\\( K_p \\\\)) and derivative term (\\\\( K_d \\\\)) necessary for stable control of the maglev system?\",\n", + " \"answers\": [\n", + " \"Yes, both are needed to balance correction and damping.\",\n", + " \"No, the proportional term is enough.\",\n", + " \"No, the derivative term alone can stabilize the system.\",\n", + " \"Neither are required if the system starts at equilibrium.\"\n", + " ],\n", + " \"answer\": [\"Yes, both are needed to balance correction and damping.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What typically happens when you increase the proportional gain \\\\( K_p \\\\) in the PD controller?\",\n", + " \"answers\": [\n", + " \"The system responds faster but may overshoot or oscillate more.\",\n", + " \"The system becomes more damped and sluggish.\",\n", + " \"The system completely ignores input disturbances.\",\n", + " \"The magnetic field sensor stops working.\"\n", + " ],\n", + " \"answer\": [\"The system responds faster but may overshoot or oscillate more.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the effect of increasing the derivative gain \\\\( K_d \\\\) in the PD controller?\",\n", + " \"answers\": [\n", + " \"The system becomes more responsive to input changes.\",\n", + " \"It dampens oscillations and improves stability.\",\n", + " \"It delays the system response and causes drift.\",\n", + " \"It increases the equilibrium height.\"\n", + " ],\n", + " \"answer\": [\"It dampens oscillations and improves stability.\"],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"The proportional gain \\\\( K_p \\\\) helps correct deviations from the target position quickly, but too much can cause instability. The derivative gain \\\\( K_d \\\\) counteracts rapid changes, helping reduce oscillations and overshoot. Together, they stabilize the levitating magnet.\"\n", + " }\n", + " }\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "2e950d6e", + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "source": [ + "## Design Your Controller\n", + "An important aspect of conrol design is to achieve a desired control performance. Tune the parameters so that the following criterions are satisfied:\n", + "- Overshoot < 5%\n", + "- Settling time < 2s\n", + "- Final error < 1mm\n", + "\n", + "\n", + "!!! TEMPTED TO REMOVE THIS TASK. It is not obvious what the student should look at. It is the bx (orange) plot that is of interest, the blue one can't really be modified. Need to think about it a bit more (add it like this for now, and just set the verification as max(x) < 5%, t(abs(x) < tol) < 2s, abs(x(end)) < 1mm)\n", + "### Quiz" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a84fe82f", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "display_package({\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which of the following controller behaviors is **most likely** to cause a large overshoot?\",\n", + " \"answers\": [\n", + " \"Very low \\\\( K_p \\\\), low \\\\( K_d \\\\)\",\n", + " \"High \\\\( K_p \\\\), low \\\\( K_d \\\\)\",\n", + " \"Low \\\\( K_p \\\\), high \\\\( K_d \\\\)\",\n", + " \"High \\\\( K_p \\\\), high \\\\( K_d \\\\)\"\n", + " ],\n", + " \"answer\": [\"High \\\\( K_p \\\\), low \\\\( K_d \\\\)\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is most likely to **reduce settling time** without increasing overshoot too much?\",\n", + " \"answers\": [\n", + " \"Decrease both \\\\( K_p \\\\) and \\\\( K_d \\\\)\",\n", + " \"Increase \\\\( K_p \\\\) and \\\\( K_d \\\\) proportionally\",\n", + " \"Increase \\\\( K_p \\\\), keep \\\\( K_d \\\\) low\",\n", + " \"Only increase \\\\( K_d \\\\)\"\n", + " ],\n", + " \"answer\": [\"Increase \\\\( K_p \\\\) and \\\\( K_d \\\\) proportionally\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is a common downside of choosing a very high derivative gain \\\\( K_d \\\\) in a PD controller?\",\n", + " \"answers\": [\n", + " \"It eliminates steady-state error completely.\",\n", + " \"It increases sensor noise sensitivity, possibly causing jitter or instability.\",\n", + " \"It slows the system down drastically.\",\n", + " \"It reduces the effect of the proportional gain.\"\n", + " ],\n", + " \"answer\": [\"It increases sensor noise sensitivity, possibly causing jitter or instability.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"In the PD-controlled maglev system, why does the \\\\( z \\\\)-position remain mostly unchanged even when the \\\\( x \\\\)- and \\\\( \\\\theta \\\\)-states are made faster?\",\n", + " \"answers\": [\n", + " \"Because \\\\( z \\\\) is part of the feedback loop and reacts instantly.\",\n", + " \"Because \\\\( z \\\\) is an unobservable but internally stable state, so it is unaffected by changes in \\\\( x \\\\) and \\\\( \\\\theta \\\\).\",\n", + " \"Because \\\\( z \\\\) is controlled separately with a different input.\",\n", + " \"Because \\\\( x \\\\) and \\\\( \\\\theta \\\\) dominate the force equation in the vertical direction.\"\n", + " ],\n", + " \"answer\": [\"Because \\\\( z \\\\) is an unobservable but internally stable state, so it is unaffected by changes in \\\\( x \\\\) and \\\\( \\\\theta \\\\).\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"Describe what happened when you increased \\\\( K_d \\\\) too much. Did the system become sluggish, or did it improve stability?\",\n", + " \"notes\": [\n", + " \"A high \\\\( K_d \\\\) value can reduce overshoot but may also slow down the response.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"Think about each performance criterion separately: Overshoot relates to damping, settling time to responsiveness, and final error to steady-state accuracy. PD controllers offer a tradeoff space—tuning is all about balance.\"\n", + " }\n", + "})\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5951b684", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/chapters/equilibrium_analysis.ipynb b/book/chapters/equilibrium_analysis.ipynb new file mode 100644 index 0000000..f2150a1 --- /dev/null +++ b/book/chapters/equilibrium_analysis.ipynb @@ -0,0 +1,202 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "9a6bd482", + "metadata": { + "tags": [ + "thebe-remove-input-init", + "auto-execute-page" + ], + "vscode": { + "languageId": "plaintext" + } + }, + "outputs": [], + "source": [ + "%pip install ipyquizjb\n", + "%pip install ipysim\n", + "from ipyquizjb.questions import display_package" + ] + }, + { + "cell_type": "markdown", + "id": "1de17b32", + "metadata": {}, + "source": [ + "# Equilibrium Analysis\n", + "\n", + "Before we can design a controller we need to analyze how the system behaves around an equilibrium point. An equilibrium point is a point where the time derivative of the system is 0, and it can be classified as being either **stable** or **unstable**. For the system above, the equilibrium point can be found by letting $x = \\theta = 0$, and then vary $z$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fac626d0", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "questions = {\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Assume now that we have only one magnet in the base so that \\\\( i = 1 \\\\) and \\\\( \\\\mathbf{d}_i = [0, z]^\\\\top \\\\). Which one of the following equations gives the correct expression for the equilibrium position \\\\( z_{eq} \\\\) of the system?\",\n", + " \"answers\": [\n", + " \"\\\\( z_{eq} = \\\\sqrt{\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g}} \\\\)\",\n", + " \"\\\\( z_{eq} = \\\\sqrt[3]{\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g}} \\\\)\",\n", + " \"\\\\( z_{eq} = \\\\sqrt[4]{\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g}} \\\\)\"\n", + " ],\n", + " \"answer\": [\"\\\\( z_{eq} = \\\\sqrt[3]{\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g}} \\\\)\"],\n", + " \"when\": \"initial\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"At equilibrium, the vertical magnetic force balances the gravitational force.\\nWhen only one magnet is used in the base, the expression for the force can be simplified to:\\n\\\\(\\\\mathbf{F}_{z} =g-\\\\frac{3\\\\mu _{0} m_{l} m_{p}}{2\\\\pi z^{3}}\\\\)\\n\\nBy setting this expression to zero, we can find the equlibrium through a few simple opreations:\\n\\\\(\\\\frac{3\\\\mu _{0} m_{l} m_{p}}{2\\\\pi z^{3}} =g\\\\)\\n\\\\(3\\\\mu _{0} m_{l} m_{p} =2\\\\pi z^{3} g\\\\)\\n\\\\(\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g} =z^{3}\\\\)\\n\\\\(z=\\\\sqrt[3]{\\\\frac{3}{2}\\\\frac{\\\\mu _{0} m_{l} m_{p}}{\\\\pi g}}\\\\)\\nThe cubic dependency makes this system quite nonlinear, as well as limiting our levitation height.\"\n", + " }\n", + "}\n", + "\n", + "\n", + "display_package(questions)" + ] + }, + { + "cell_type": "markdown", + "id": "6aa27deb", + "metadata": {}, + "source": [ + "Below is a figure of the force on the magnet in the horizontal direction, given $z$, where $x = \\theta = 0$. Try to vary the different parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce10a2e2", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "from ipysim.simulations import simulate_flip_magnet\n", + "from ipysim.simulation_ui import interactive_simulation\n", + "from ipysim.params import default_params\n", + "\n", + "interactive_simulation(\n", + " simulate_fn=simulate_flip_magnet.flip_magnet_simulation,\n", + " plot_fn=simulate_flip_magnet.plot_flip_magnet,\n", + " params=default_params(),\n", + " sliders_config={\n", + " \"M\": {\"default\": 0.075, \"min\": 0.01, \"max\": 0.2, \"step\": 0.005, \"description\": \"Mass M (kg)\"},\n", + " \"l\": {\"default\": 0.046, \"min\": 0.01, \"max\": 0.1, \"step\": 0.001, \"description\": \"Distance l (m)\"},\n", + " \"flip\": {\"default\": False, \"min\": 0, \"max\": 1, \"step\": 1, \"description\": \"Flip Magnet\"},\n", + " }\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b50de0a9", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "questions = {\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"When simulating the system and varying \\\\( z \\\\), which position initially corresponds to a **stable** equilibrium point?\",\n", + " \"answers\": [\n", + " \"Left\",\n", + " \"Right\"\n", + " ],\n", + " \"answer\": [\"Right\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What does the slope of the force curve near the equilibrium point tell us?\",\n", + " \"answers\": [\n", + " \"Whether the magnet will rotate\",\n", + " \"Whether gravity is acting\",\n", + " \"How the force will change with a change in \\\\( z \\\\)\",\n", + " \"How fast the magnet will move\"\n", + " ],\n", + " \"answer\": [\"How the force will change with a change in \\\\( z \\\\)\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What parameter is most important for determining the equilibrium height \\\\( z \\\\)?\",\n", + " \"answers\": [\n", + " \"Mass\",\n", + " \"Position\",\n", + " \"Magnetic field sensor resolution\",\n", + " \"Damping\"\n", + " ],\n", + " \"answer\": [\"Mass\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What happens when \\\\( m = 0.1 \\\\) and \\\\( l = 0.08 \\\\) in the simulation?\",\n", + " \"answers\": [\n", + " \"There is no equilibrium\",\n", + " \"There is still a stable equilibrium\",\n", + " \"There is an unstable equilibrium\"\n", + " ],\n", + " \"answer\": [\"There is an unstable equilibrium\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Approximately what is the carrying capacity of the magnet when \\\\( m = 0.075 \\\\) and \\\\( l = 0.07 \\\\)?\",\n", + " \"answers\": [\n", + " \"~20g\",\n", + " \"~75g\",\n", + " \"~800g\"\n", + " ],\n", + " \"answer\": [\"~75g\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What do you think happens if the magnet is flipped upside down?\",\n", + " \"answers\": [\n", + " \"The equilibrium disappears\",\n", + " \"A new stable equilibrium appears\",\n", + " \"It becomes unstable\",\n", + " \"The direction of gravity changes\"\n", + " ],\n", + " \"answer\": [\"A new stable equilibrium appears\"],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"A stable equilibrium occurs when a small disturbance causes a restoring force. This is related to the **slope** of the force curve: if the magnetic force increases when the magnet moves slightly down (opposing gravity), the equilibrium is stable. However, keep in mind that this figure only illustrates that the equilibrium is stable in the z-direction; the levitating magnet may still be unstable in the lateral and rotational directions.\"\n", + " }\n", + "}\n", + "\n", + "display_package(questions)\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/chapters/ilo_and_prerequisites.ipynb b/book/chapters/ilo_and_prerequisites.ipynb new file mode 100644 index 0000000..4f0ac4d --- /dev/null +++ b/book/chapters/ilo_and_prerequisites.ipynb @@ -0,0 +1,611 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init", + "auto-execute-page" + ] + }, + "outputs": [], + "source": [ + "%pip install ipyquizjb\n", + "\n", + "from ipyquizjb.questions import display_package" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Intended Learning Outcomes\n", + "\n", + "After completing this Colab notebook, you should be able to:\n", + "\n", + "1. **Explain the structure of the ODEs describing the maglev system,** and more precisely:\n", + " - Describe the governing differential equations of the magnetic levitation system, identifying the physical principles behind each term *(Bloom's taxonomy levels `Understand' and 'Apply')*. \n", + " - Illustrate how the system parameters (e.g., coil current, magnetic force, gravity) influence the system’s behavior *(Bloom's taxonomy level `Analyze')*.\n", + "\n", + "2. **Determine and interpret the equilibrium points of the maglev system,** and more precisely:\n", + " - Compute the equilibrium positions of the levitated object by solving for steady-state conditions in the ODEs describing the maglev system *(Bloom's taxonomy levels `Apply' and 'Analyze')*.\n", + " - Justify the physical meaning of each equilibrium point and connect it to real-world intuitions about system behavior (e.g., stable hovering vs. falling. *(Bloom's taxonomy levels `Evaluate' and 'Create')*). \n", + "\n", + "3. **Linearize the system equations around its equilibria,** and more precisely:\n", + " - Derive the linearized state-space representation of the maglev system at its equilibrium points *(Bloom's taxonomy levels `Apply' and 'Analyze')*. \n", + " - Compare the behavior of the nonlinear and linearized models, assessing the validity of the linear approximation *(Bloom's taxonomy level `Evaluate')*.\n", + "\n", + "4. **Analyze the stability properties of such equilibria,** and more precisely:\n", + " - Determine the stability of each equilibrium by analysing the properties of the linearized systems, and by interpreting their implications *(Bloom's taxonomy levels `Analyze' and 'Evaluate')*.\n", + " - Explain the stability properties of such equilibria using phase portraits and graphical intuitions *(Bloom's taxonomy levels `Understand' and 'Apply')*.\n", + "\n", + "5. **Design and implement a PD controller** \n", + " - Formulate a proportional-derivative (PD) control law to stabilize the system at a desired equilibrium position *(Bloom's taxonomy levels `Apply' and 'Create')*.\n", + " - Tune the controller parameters to achieve desired performance, such as reducing overshoot and settling time *(Bloom's taxonomy levels `Evaluate' and 'Analyze')*.\n", + " - Simulate the closed-loop system and validate the performance of the controller against predefined criteria *(Bloom's taxonomy levels `Create' and 'Test')*.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Prerequisites\n", + "\n", + "In this section you will be presented a list of multiple choice questions that will test your readiness levels before continuing with the notebook.\n", + "\n", + "This test is not timed, but if you see that it is taking you in average more than 5 minutes per question to find your preferred answer, consider refreshing the concepts involved in these questions in any case." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Checking your knowledge levels about ODEs\n", + "\n", + "Here you are going to be presented a (potentially expanding) list of questions about what is an ODE." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "questions = {\"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which of the following best describes what it means for a function $y(t)$ to be a solution of an ODE?\",\n", + " \"answers\": [\n", + " \"It satisfies the ODE for at least one value of $t$.\",\n", + " \"It satisfies the ODE for all values of $t$ in its domain.\",\n", + " \"It approximately satisfies the ODE within a certain error margin.\",\n", + " \"It satisfies the ODE only at integer values of $t$.\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"It satisfies the ODE for all values of $t$ in its domain.\"],\n", + " \"notes\": [\n", + " \"A function is a solution of an ODE if it satisfies the equation for all values of $t$ within its domain. A solution must be valid throughout the considered interval, not just at isolated points.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which of the following is a common limitation of linearizing a nonlinear system?\",\n", + " \"answers\": [\n", + " \"The linearized model is only valid in a small neighborhood around the linearization point.\",\n", + " \"The linearized model has no practical applications in control.\",\n", + " \"Linearization makes the system unstable.\",\n", + " \"Linearization eliminates all dynamic behavior of the system.\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\n", + " \"The linearized model is only valid in a small neighborhood around the linearization point.\"\n", + " ],\n", + " \"notes\": [\n", + " \"A linearized model is typically valid only in a small neighborhood around the equilibrium point where it was derived. If the system deviates significantly from this region, the approximation may no longer be accurate.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The following response\\n\\t\\t
\\n\\t\\t\\n\\t\\t
\\n\\t\\tcorresponds to a \\u2026 response\",\n", + " \"answers\": [\"underdamped\", \"overdamped\", \"I do not know\"],\n", + " \"answer\": [\"underdamped\"],\n", + " \"notes\": [\n", + " \"Here the output exhibits oscillations, so it is an underdamped one.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What does it mean to linearize a nonlinear ordinary differential equation (ODE)?\",\n", + " \"answers\": [\n", + " \"It means approximating the nonlinear ODE with a linear model around an equilibrium point.\",\n", + " \"It means replacing the ODE with a completely unrelated linear system.\",\n", + " \"It means integrating the ODE analytically to find a closed-form solution.\",\n", + " \"It means ignoring all nonlinear terms in the system dynamics.\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\n", + " \"It means approximating the nonlinear ODE with a linear model around an equilibrium point.\"\n", + " ],\n", + " \"notes\": [\n", + " \"Linearizing an ODE means approximating it with a linear model around an equilibrium point using a first-order Taylor series expansion. This allows for easier analysis and control design.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which function represents a linear system?\",\n", + " \"answers\": [\n", + " \"$\\\\dot{y} = y^3 + 2y$\",\n", + " \"$\\\\dot{y} = 5y + 3u$\",\n", + " \"$\\\\dot{y} = \\\\sin(y) + u$\",\n", + " \"$\\\\dot{y} = e^y - u$\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"$\\\\dot{y} = 5y + 3u$\"],\n", + " \"notes\": [\n", + " \"A system is linear if it satisfies the superposition principle. The equation $\\\\dot{y} = 5y + 3u$ is linear because it only includes first-degree terms in $y$ and $u$. The other options contain nonlinear terms such as $y^3$, $\\\\sin(y)$, or $e^y$.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The following response\\n\\t\\t
\\n\\t\\t\\n\\t\\t
\\n\\t\\tcorresponds to a \\u2026 response.\",\n", + " \"answers\": [\"underdamped\", \"overdamped\", \"I do not know\"],\n", + " \"answer\": [\"overdamped\"],\n", + " \"notes\": [\n", + " \"Here the output exhibits no oscillations, so it is an overdamped one.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What additional information is needed to uniquely determine a solution of an ODE?\",\n", + " \"answers\": [\n", + " \"The function $y(t)$ itself.\",\n", + " \"An initial condition specifying the value of $y$ at a given time.\",\n", + " \"A boundary condition at two different points.\",\n", + " \"The highest-order derivative of $y$.\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\n", + " \"An initial condition specifying the value of $y$ at a given time.\"\n", + " ],\n", + " \"notes\": [\n", + " \"An initial condition provides the necessary information to select a unique solution from the family of possible solutions to a differential equation. Without it, multiple solutions may exist.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Given the ODE $\\\\dot{y} = y$, which of the following functions is a solution?\",\n", + " \"answers\": [\n", + " \"$y(t) = t^2$\",\n", + " \"$y(t) = Ce^t$, where $C$ is a constant.\",\n", + " \"$y(t) = \\\\sin t$\",\n", + " \"$y(t) = \\\\frac{1}{t+1}$\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"$y(t) = Ce^t$, where $C$ is a constant.\"],\n", + " \"notes\": [\n", + " \"The function $y(t) = Ce^t$ satisfies the equation since its derivative is also $Ce^t$, matching the right-hand side of the ODE.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Consider the equation $\\\\dot{y} = -0.3y + (2t) u$. How should this system be classified?\",\n", + " \"answers\": [\n", + " \"Linear, autonomous, time-invariant\",\n", + " \"Linear, autonomous, time-varying\",\n", + " \"Linear, non-autonomous, time-varying\",\n", + " \"Nonlinear, non-autonomous, time-varying\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"Linear, non-autonomous, time-varying\"],\n", + " \"notes\": [\n", + " \"The system is linear because it contains no nonlinear terms in $y$ or in $u$. It is non-autonomous due to the explicit dependence on $u$, and it is time-varying since the coefficient of $u$ depends on $t$.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which of the following statements about phase portraits of nonlinear systems is correct?\",\n", + " \"answers\": [\n", + " \"Nonlinear systems always have a single equilibrium point\",\n", + " \"Nonlinear phase portraits can be analyzed only by solving the system numerically\",\n", + " \"Nonlinear phase portraits may exhibit equilibrium points, limit cycles, and chaotic behavior\",\n", + " \"Nonlinear phase portraits always resemble those of linear systems for small perturbations\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\n", + " \"Nonlinear phase portraits may exhibit equilibrium points, limit cycles, and chaotic behavior\"\n", + " ],\n", + " \"notes\": [\n", + " \"Nonlinear systems can have equilibrium points, periodic limit cycles, or even chaotic behavior depending on the dynamics. Their phase portraits often exhibit richer and more complex structures than linear systems.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " }\n", + "],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"Seems like that it would be best to refresh your knowledge about ODEs before continuing. Suggestion: check the following two sources of information:\\n\\tlink to wikipedia 1\\n\\tlink to video 1\\nand then, when ready, [todo understand how to do this 'continue with the next bunch of questions']\"\n", + "}\n", + "}\n", + "\n", + "display_package(questions)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Checking your knowledge levels about equilibria and their stability properties\n", + "\n", + "Here you are going to be presented a (potentially expanding) list of questions about what an equilibrium is, and which stability properties equilibria may have." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "questions = {\n", + " \"questions\": [\n", + " \n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the mathematical definition of an equilibrium point for a dynamical system $\\\\dot{y} = f(y, u)$?\",\n", + " \"answers\": [\n", + " \"A point where $f(y, u)$ is maximized\",\n", + " \"A point where $f(y, u) = 0$\",\n", + " \"A point where $y$ is always increasing\",\n", + " \"A point where $y$ is always decreasing\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"A point where $f(y, u) = 0$\"],\n", + " \"notes\": [\n", + " \"An equilibrium point is defined as a point where the system's derivative $\\\\dot{y}$ is zero, meaning the state remains constant over time.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Graphically, how can equilibrium points be identified for an autonomous system $\\\\dot{y} = f(y)$?\",\n", + " \"answers\": [\n", + " \"By finding where $y = 0$\",\n", + " \"By finding the points where $f(y) = 0$ on the phase plot\",\n", + " \"By locating the steepest points of the function $f(y)$\",\n", + " \"By identifying the points where $y$ reaches its maximum or minimum values\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"By finding the points where $f(y) = 0$ on the phase plot\"],\n", + " \"notes\": [\n", + " \"Equilibrium points occur where $\\\\dot{y} = f(y) = 0$, which correspond to the intersections of $f(y)$ with the horizontal axis in a phase plot.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Consider the system $\\\\dot{T} = -0.5 (T - 20)$. What is the equilibrium temperature?\",\n", + " \"answers\": [\n", + " \"$T = 0$\",\n", + " \"$T = 20$\",\n", + " \"$T = -20$\",\n", + " \"$T = 40$\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"$T = 20$\"],\n", + " \"notes\": [\n", + " \"Setting $\\\\dot{T} = 0$ gives $-0.5(T - 20) = 0$, which simplifies to $T = 20$. This is the equilibrium point of the system.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"For the linear system $\\\\dot{y} = ay + bu$, under what condition is $(y_0, u_0)$ an equilibrium?\",\n", + " \"answers\": [\n", + " \"When $a = 0$ only\",\n", + " \"When $ay_0 + bu_0 = 0$\",\n", + " \"When $y_0 = 0$ and $u_0 = 0$ always\",\n", + " \"When $u_0$ is arbitrary\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"When $ay_0 + bu_0 = 0$\"],\n", + " \"notes\": [\n", + " \"To find an equilibrium, set $\\\\dot{y} = 0$, leading to $ay + bu = 0$. Solving for $y_0$ and $u_0$ gives the equilibrium condition.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is an equilibrium point of the ODE $\\\\dot{y} = y(1-y)$?\",\n", + " \"answers\": [\n", + " \"$y=2$\",\n", + " \"$y=0$ and $y=1$\",\n", + " \"$y=-1$\",\n", + " \"$y=\\\\frac{1}{2}$\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"$y=0$ and $y=1$\"],\n", + " \"notes\": [\n", + " \"Equilibrium points occur where $\\\\dot{y} = 0$, meaning $y(1-y) = 0$. This happens at $y=0$ and $y=1$.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The equilibria of the system\\n\\t\\t$$\\n\\t\\t\\t\\\\dot{x} = f(x) = x^{2} - 2 x - 3\\n\\t\\t$$\\n\\t\\tare \\u2026\",\n", + " \"answers\": [\"-1\", \"3\", \"both -1 and 3\", \"I do not know\"],\n", + " \"answer\": [\"both -1 and 3\"],\n", + " \"notes\": [\n", + " \"We can rewrite the system as\\n\\t\\t$$\\n\\t\\t\\t\\\\dot{x} = f(x) = x^{2} - 2 x - 3 = (x - 3) (x + 1)\\n\\t\\t$$\\n\\t\\tand thus finding its equilibria corresponds to set $(x - 3) (x + 1) = 0$. In other words the equilibria are all the zeros of that polynomial, thus\\n\\t\\t$$\\n\\t\\t\\t\\\\text{equilibria: }\\n\\t\\t\\t\\\\left\\\\lbrace\\n\\t\\t\\t\\\\begin{array}{ll}\\n\\t\\t\\t\\t\\\\overline{x}_{1} = -1 \\\\\\\\\\n\\t\\t\\t\\t\\\\overline{x}_{2} = 3\\n\\t\\t\\t\\\\end{array}\\n\\t\\t\\t\\\\right.\\n\\t\\t$$\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The following definition of simple stability is correct:\\n\\t\\t
\\n\\t\\t\\t\\\\emph{${y}_{\\\\text{eq}}$ is simply stable if $\\\\forall \\\\varepsilon > 0 \\\\; \\\\exists \\\\delta > 0$ s.t.\\\\ if $\\\\| {y}_{0} - {y}_{\\\\text{eq}} \\\\| \\\\leq \\\\varepsilon$ then $\\\\| {y}(t) - {y}_{\\\\text{eq}} \\\\| \\\\leq \\\\delta \\\\quad \\\\forall t \\\\geq 0$}\\n\\t\\t
\",\n", + " \"answers\": [\"true\", \"false\", \"it depends\", \"I do not know\"],\n", + " \"answer\": [\"false\"],\n", + " \"notes\": [\n", + " \"In words, the definition for simple stability reads as \\\\emph{for every outer ball there must exist an inner ball such that if starting in the inner ball then the trajectory stays within the outer}. For how the mathematical definition in the body of the exercise starts, it seems that the symbol $\\\\varepsilon$ should be associated to the outer ball, and the symbol $\\\\delta$ to the inner one. But if so then the second part of the definition is clearly wrong, since the roles of the $\\\\delta$ and $\\\\varepsilon$ symbols are then inverted after the \\\"s.t.\\\".\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The origin $({u}, {y}) = ({0}, {0})$ is always an equilibrium for a LTI system of the type $\\\\dot{{y}} = A {y} + B {u}$.\",\n", + " \"answers\": [\"true\", \"false\", \"it depends\", \"I do not know\"],\n", + " \"answer\": [\"true\"],\n", + " \"notes\": [\n", + " \"Substituting $({u}, {y}) = ({0}, {0})$ in the equation leads naturally to $\\\\dot{{y}} = {0}$, thus the answer is true. Actually this is also true for all the pairs $({u}, {y})$ where simultaneously ${y}$ is in the kernel of $A$ and ${u}$ is in the kernel of $B$.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"The origin is always an equilibrium for a generic system of the type $\\\\dot{{y}} = {f} \\\\left( {y}, {u} \\\\right)$.\",\n", + " \"answers\": [\"true\", \"false\", \"it depends\", \"I do not know\"],\n", + " \"answer\": [\"false\"],\n", + " \"notes\": [\n", + " \"This is not true in general, and we can verify this by making an example. E.g., $\\\\dot{y} = ( y + 1 )^{2}$ is so that $y = 0, u = 0$ is not an equilibrium.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Can an autonomous LTI system of the type $\\\\dot{{x}} = A {x}$ have equilibria of different types? (i.e., have a ${x}_{1}$ that is an asymptotically stable equilibrium for the system, another ${x}_{2}$ that is instead a marginally stable equilibrium, etc.)\",\n", + " \"answers\": [\"yes\", \"no\", \"it depends\", \"I do not know\"],\n", + " \"answer\": [\"no\"],\n", + " \"notes\": [\n", + " \"The set of equilibria for the system is given by the kernel of $A$. This kernel may be trivial, i.e., formed by just an element, or a proper subspace of the domain with dimension bigger or equal than 1. For sure ${0}$ is in the kernel of $A$, i.e., it is for sure an equilibrium for the system.\\n \\n Case 1: assume the kernel of $A$ to be trivial. In this case the system has only one type of equilibria since there is only one equilibrium. Note that this implies the kernel of $A$ to be the set composed by only the element ${0}$ (note that $0 \\\\neq {0}$, the former is in $\\\\mathbb{C}$, the second is the origin of the domain and thus multidimensional as soon as $A$ is not a scalar).\\n\\n Case 2: assume the kernel of $A$ to be non-trivial, that implies that there exists at least one eigenvalue of $A$ that is equal to $0$.\\n \\n Then every $\\\\overline{{x}}$ in the kernel cannot be an asymptotically stable equilibrium, since it should in this case be also convergent. Convergency would indeed require that there exists a $\\\\delta > 0$ so that for any initial condition in the $\\\\delta$-ball centered in $\\\\overline{{x}}$ the limit of the trajectory for $t \\\\rightarrow +\\\\infty$ is $\\\\overline{{x}}$. But this $\\\\delta$-ball intersects the kernel, that is non trivial and thus contains other elements than $\\\\overline{{x}}$, and these elements are equilibria. Starting from these equilibria the trajectory won't move and thus won't converge to $\\\\overline{{x}}$.\\n \\n If $\\\\overline{{x}}$ is in the kernel of $A$ thus as an equilibrium it can be either marginally stable or unstable.\\n \\n Say then that \\\\emph{ab absurdo} the system is so that $\\\\overline{{x}}_{m}$ and $\\\\overline{{x}}_{u}$ are two distinct vectors both in the kernel of $A$, and the former is marginally stable while the latter is unstable.\\n \\n But then this conflicts with the concept that the trajectories starting around the origin ${0}$ form a sort of template for the trajectories starting around the elements in the kernel of $A$, because of the superposition principle. As in the figure below, consider the $\\\\widetilde{{x}}$ in the circle drawn around the origin.\\n \\n Assume ${0}$ to be marginally stable; starting from $\\\\widetilde{{x}}$ as initial condition, the trajectory will be confined in another opportune ball (not drawn here). Then consider the initial condition $\\\\widetilde{{x}} + \\\\overline{{x}}_{u}$. Due to the superposition effect the free evolution has to be the sum of the evolution from $\\\\widetilde{{x}}$ plus the evolution from $\\\\overline{{x}}_{u}$. The latter is just $\\\\overline{{x}}_{u}$, since the point is an equilibrium, while the former is the trajectory we were seeing around ${0}$.\\n\\n Since this reasoning can be made in the opposite direction, if $\\\\overline{{x}}_{u}$ is unstable it means that there is some initial condition $\\\\widetilde{{x}} + \\\\overline{{x}}_{u}$ in some neighborhood of $\\\\overline{{x}}_{u}$ that diverges. But then ${0}$ could not be marginally stable.\\n\\n Summarizing, all the equilibria along the kernel of $A$ share the same stability properties of ${0}$. \\n \\n
\\n \\t\\t\\n
\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"TODO: Fill out additional material\"\n", + " }\n", + "}\n", + "\n", + "display_package(questions)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Checking your knowledge levels about PID controllers\n", + "\n", + "Here you are going to be presented a (potentially expanding) list of questions about PID controllers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "questions = {\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"A PID is guaranteed to work well\",\n", + " \"answers\": [\n", + " \"yes, always\",\n", + " \"no, never\",\n", + " \"no, it depends on how well tuned it is\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"no, it depends on how well tuned it is\"],\n", + " \"notes\": [\n", + " \"A PID controller is not guaranteed to work well in all cases; its performance depends on proper tuning. Poorly tuned PID controllers can lead to instability, slow response, or excessive oscillations. The three gains (proportional ($K_p$), integral ($K_i$), and derivative ($K_d$)) must be adjusted based on the system dynamics. \\n \\n For example, if $K_p$ is too high, the system may oscillate or become unstable.\\n If $K_i$ is too high, the system may suffer from overshoot and integral windup.\\n If $K_d$ is too high, the system may become too sensitive to noise.\\n \\n Tuning methods like Ziegler-Nichols, Cohen-Coon, or optimization-based approaches help in achieving a well-performing PID controller. Therefore, the correct answer is: *no, it depends on how well tuned it is*.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Is closed loop control guaranteed to work better than open loop control?\",\n", + " \"answers\": [\n", + " \"yes, always\",\n", + " \"no, never\",\n", + " \"no, it actually depends on the situation\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"no, it actually depends on the situation\"],\n", + " \"notes\": [\n", + " \"Closed-loop control is not always guaranteed to work better than open-loop control; the effectiveness of each approach depends on the specific application and system characteristics. While closed-loop control provides feedback and can correct errors, open-loop control can be sufficient or even preferable in certain scenarios. \\n \\n Key factors influencing the choice between open-loop and closed-loop control:\\n \\\\begin{itemize}\\n \\\\item System Variability: Closed-loop control is beneficial when the system is subject to disturbances or uncertainties, as it can adjust in real time. However, for predictable systems with no disturbances, open-loop control may be simpler and more efficient.\\n \\\\item Complexity and Cost: Closed-loop systems require sensors, controllers, and actuators, increasing cost and complexity, whereas open-loop systems are often simpler and cheaper.\\n \\\\item Response Time: Open-loop control can be faster since it does not rely on feedback processing, making it suitable for high-speed operations where corrections are unnecessary.\\n \\\\item Energy and Stability Considerations: Some closed-loop systems may introduce oscillations or instability if not properly designed, while open-loop systems avoid this risk by operating in a predefined manner.\\n \\\\end{itemize}\\n \\n Thus, the correct answer is: no, it actually depends on the situation.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"PID control requires a model of the system to function correctly.\",\n", + " \"answers\": [\"yes, always\", \"no, it works without a model\", \"I do not know\"],\n", + " \"answer\": [\"no, it works without a model\"],\n", + " \"notes\": [\n", + " \"A PID controller works without requiring a model of the system. Instead, it uses feedback from the system\\u2019s output to adjust the control input. The three parameters\\u2014proportional ($K_p$), integral ($K_i$), and derivative ($K_d$)\\u2014are tuned based on system behavior, but no explicit system model is necessary. This makes PID controllers simple and widely applicable, even in systems where modeling is difficult or not feasible.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Feedforward control is generally better than feedback control for handling disturbances.\",\n", + " \"answers\": [\n", + " \"yes, feedforward is always better\",\n", + " \"no, feedback control is better for disturbances\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"no, feedback control is better for disturbances\"],\n", + " \"notes\": [\n", + " \"Feedforward control can be effective when disturbances are predictable, as it compensates for them proactively. However, feedback control is generally better for handling unexpected disturbances or system changes because it can adjust in real-time based on the system's output. Feedback ensures that the system can respond to unmeasured or unforeseen variations, making it more robust in dynamic environments.\"\n", + " ],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Open-loop control is more reliable than closed-loop control in all situations.\",\n", + " \"answers\": [\n", + " \"yes, open-loop is always more reliable\",\n", + " \"no, it depends on the system and application\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"no, it depends on the system and application\"],\n", + " \"notes\": [\n", + " \"Open-loop control is simpler and can be more reliable in cases where the system is predictable and not subject to disturbances. However, closed-loop control is more reliable when disturbances or system variations are present, as it adjusts based on feedback. The choice between open-loop and closed-loop control depends on the specific system dynamics, complexity, and performance requirements.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What does the P term in a PID controller stand for, and what is its primary effect?\",\n", + " \"answers\": [\n", + " \"Predictive - anticipates future errors based on current trends\",\n", + " \"Proportional - produces an output proportional to the current error\",\n", + " \"Periodic - adjusts the control action at regular intervals\",\n", + " \"Passive - maintains system stability without active correction\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\n", + " \"Proportional - produces an output proportional to the current error\"\n", + " ],\n", + " \"notes\": [\n", + " \"The P stands for Proportional. The proportional term produces an output value that is proportional to the current error value. The proportional response can be adjusted by multiplying the error by a constant Kp. A high proportional gain results in a large change in the output for a given change in the error, which can lead to a faster response but may also cause system instability.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the primary consequence of setting the integral term (I) too high in a PID controller?\",\n", + " \"answers\": [\n", + " \"The system becomes sluggish and unresponsive\",\n", + " \"The system oscillates at a constant amplitude\",\n", + " \"The system exhibits large overshoot and becomes unstable\",\n", + " \"The system ignores steady-state errors\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"The system exhibits large overshoot and becomes unstable\"],\n", + " \"notes\": [\n", + " \"An excessively high integral gain leads to aggressive correction of accumulated past errors, which typically causes large overshoot and system instability. The integral term is responsible for eliminating steady-state error, but too much integral action can make the system oscillate wildly or even diverge.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What does the D term in a PID controller primarily respond to?\",\n", + " \"answers\": [\n", + " \"The total accumulated error over time\",\n", + " \"The absolute value of the current error\",\n", + " \"The rate of change of the error\",\n", + " \"The desired setpoint value\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"The rate of change of the error\"],\n", + " \"notes\": [\n", + " \"The D stands for Derivative. The derivative term is concerned with the rate of change of the error with respect to time. A derivative term slows the rate of change of the controller output, which helps to reduce overshoot and improve system stability. However, too much derivative action can make the system sluggish and sensitive to noise.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the likely result of setting all PID gains to zero?\",\n", + " \"answers\": [\n", + " \"The controller will take no corrective action\",\n", + " \"The system will achieve perfect control instantly\",\n", + " \"The system will oscillate at its natural frequency\",\n", + " \"The controller will use default conservative values\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"The controller will take no corrective action\"],\n", + " \"notes\": [\n", + " \"Setting all PID gains (Kp, Ki, and Kd) to zero means the controller will generate no corrective output regardless of the error. The system will be completely uncontrolled, with the process variable potentially drifting away from the setpoint due to disturbances.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the main purpose of the integral term in a PID controller?\",\n", + " \"answers\": [\n", + " \"To speed up the initial response to large errors\",\n", + " \"To predict future errors based on current trends\",\n", + " \"To eliminate steady-state error\",\n", + " \"To filter out high-frequency noise\",\n", + " \"I do not know\"\n", + " ],\n", + " \"answer\": [\"To eliminate steady-state error\"],\n", + " \"notes\": [\n", + " \"The integral term's primary purpose is to eliminate steady-state error, which is the residual error that remains after the proportional term has done its work. It does this by integrating (summing) past errors over time and applying a correction based on this accumulated error. Without integral action, many control systems would never perfectly reach their setpoint.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"TODO: Fill out additional material\"\n", + " }\n", + "}\n", + "\n", + "display_package(questions)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/chapters/introducing_maggy.md b/book/chapters/introducing_maggy.md new file mode 100644 index 0000000..c21bc23 --- /dev/null +++ b/book/chapters/introducing_maggy.md @@ -0,0 +1,57 @@ +# Introducing Maggy + +This notebook introduces modeling and control concepts relevant when working with Maggy, the magnetic levitation system. + +```{figure} https://github.com/Hansolini/Take-home-Maglev-lab/blob/main/media/images_and_illustrations/maggy_30_levitating.jpg?raw=true +--- +name: intro_maggy +align: center +width: 70% +--- +Maggy, the magnetic levitation system +``` + +:::{dropdown} Expand to see videos of Maggy +
+ + + +
+::: +Maggy is a compact and portable magnetic levitation platform, designed similarly to many other commercial magnetic levitation platforms (https://www.crealev.com/, https://flytestore.com/). + +The purpose of Maggy is to make the magnet seen at the top levitate, using an array of permanent magnets (in the image: gray neodymium magnets), electromagnets (in the image: copper coils), and some sensors (not visible). +Ernshaws theorem asserts that stable levitation of any mangetic system containing only passive magnets is impossible! Thus, levitation, such as seen here, can _only_ be achieved with feedback control. + +The most important componets of Maggy are: + +- **Permanent Magnets**: Four sets of axially magnetized N38 type Neodymium permanent magnets provide the main lift for the levitating magnet. +- **Solenoids:** Four copper air-core solenoids provide corrective magnetic fields for stable levitation. +- **Levitating Magnet:** A large N38 type Neodymium magnet that is being levitated. +- **Hall-effect sensors:** Several digital ratiometric Hall-effect sensors mounted directly on a PCB. +- **Microcontroller:** A Teensy 4.1 microcontroller for reading sensor measurements, and managing power and control signals to the solenoids. + +The levitating magnet is free to move and rotate in any direction. The movement is picked-up as changes in the magnetic field measured by the Hall-effect sensors, and this signal can be used as feedback to the solenoids/electromagnets in order to counteract unwanted movement and ensure stable levitation. + +## Structure of the book + +The goal of this notebook is to make the reader comfortable with the theoretical concepts needed to achieve levitation. +To do so, a simpler "2D" model is used (as will be seen later), but the ideas developed here readily extends to the full "3D" system. + +The notebook is designed to guide the reader through the various concepts through text explanations, interactive elements and quizes. We encouraged the reader to take time to answer the questions and proceed only when they are fully understood. diff --git a/book/chapters/linearization_and_stability.ipynb b/book/chapters/linearization_and_stability.ipynb new file mode 100644 index 0000000..655cb79 --- /dev/null +++ b/book/chapters/linearization_and_stability.ipynb @@ -0,0 +1,150 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "0ee5652a", + "metadata": { + "tags": [ + "auto-execute-page", + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "%pip install ipyquizjb\n", + "from ipyquizjb.questions import display_package" + ] + }, + { + "cell_type": "markdown", + "id": "f8bc0321", + "metadata": {}, + "source": [ + "# Linearization & Stability\n", + "\n", + "The maglev system is most easily controlled by first applying the following change of variables on the input:\n", + "\n", + "$$\n", + "\t\tu_x := I_p-I_n, \\quad u_z := I_p + I_n.\n", + "$$\n", + "\n", + "By doing this it is possible to decouple the control of $x$ and $z$, simplifying our analysis.\n", + "With this change of variables, we may linearize the above model with an appopriate set of parameters, giving us the input-to-state transfer functions:\n", + "\n", + "$$\n", + " G_x(s) = \\frac{a_0s^2+a_1}{s^4+b_1s^2-b_2}, \\quad G_z(s) = \\frac{a_2}{s^2 + b_3},\n", + "$$\n", + "\n", + "for some parameters $a_i > 0$ and $b_i > 0$.\n", + "Assuming that we only measure the magnetic field in the $x$ direction, we have that the input-to-ouptut transfer function is given by:\n", + "\n", + "$$\n", + " G(s) = cG_x(s), \\quad c > 0.\n", + "$$\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "0608cf89", + "metadata": {}, + "source": [ + "## Quiz " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e41a6c9c", + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "display_package({\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What can you say about the stability of the system with transfer function for \\\\(u_s \\\\to y_x\\\\)?\",\n", + " \"answers\": [\n", + " \"It is stable because all coefficients are positive.\",\n", + " \"It is marginally stable because of the second-order numerator.\",\n", + " \"It is unstable due to the negative constant term in the denominator.\",\n", + " \"It is stable because the transfer function has even order.\"\n", + " ],\n", + " \"answer\": [\"It is unstable due to the negative constant term in the denominator.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Given the system input-to-state dynamics and limited actuation, how would you classify its controllability?\",\n", + " \"answers\": [\n", + " \"The system is fully controllable with any inputs.\",\n", + " \"It is controllable in the \\\\( x \\\\) and \\\\( z \\\\) directions separately.\",\n", + " \"It is not fully controllable due to limited input directions.\",\n", + " \"It is uncontrollable due to measurement noise.\"\n", + " ],\n", + " \"answer\": [\"The system is fully controllable with any inputs.\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"If we only measure the magnetic field in the \\\\( x \\\\)-direction, what does this mean for observability of the system?\",\n", + " \"answers\": [\n", + " \"All state variables can still be observed through back-calculation.\",\n", + " \"Only the \\\\( x \\\\)-state is observable, not the full state vector.\",\n", + " \"The system is fully observable because \\\\( x \\\\) affects all states.\",\n", + " \"Observability is irrelevant since we have a model.\"\n", + " ],\n", + " \"answer\": [\"Only the \\\\( x \\\\)-state is observable, not the full state vector.\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Why is it helpful to define the new inputs \\\\( u_x = I_p - I_n \\\\) and \\\\( u_z = I_p + I_n \\\\)?\",\n", + " \"answers\": [\n", + " \"To eliminate the need for modeling the current directly.\",\n", + " \"To improve sensor accuracy in measuring position.\",\n", + " \"To decouple the \\\\( x \\\\)- and \\\\( z \\\\)-dynamics for simplified control design.\",\n", + " \"To create a linear system out of a nonlinear one.\"\n", + " ],\n", + " \"answer\": [\"To decouple the \\\\( x \\\\)- and \\\\( z \\\\)-dynamics for simplified control design.\"],\n", + " \"when\": \"initial\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"The decoupling transformation allows us to analyze \\\\( x \\\\)- and \\\\( z \\\\)-dynamics separately. Since the dynamics for \\\\(z\\\\) are inherently stable, we may still stabilize the system.\"\n", + " }\n", + "}\n", + "\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/chapters/pid_control/aligning_expectations.ipynb b/book/chapters/pid_control/aligning_expectations.ipynb deleted file mode 100644 index 31c066d..0000000 --- a/book/chapters/pid_control/aligning_expectations.ipynb +++ /dev/null @@ -1,24 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Aligning expectations\n", - "\n", - "The Intended Learning Outcomes (ILOs) for this section are as follows. After successfully completing this section, you shall be able to\n", - "\n", - "1. launch simulations using the Maggy simulator,\n", - "2. locate the control algorithm implemented within the Maggy simulator,\n", - "3. tune the parameters of such a controller gradually to achieve stable levitation in simulation" - ] - } - ], - "metadata": { - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/book/chapters/pid_control/checking_prerequisite_knowledge.ipynb b/book/chapters/pid_control/checking_prerequisite_knowledge.ipynb deleted file mode 100644 index 82d558f..0000000 --- a/book/chapters/pid_control/checking_prerequisite_knowledge.ipynb +++ /dev/null @@ -1,159 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "auto-execute-page", - "thebe-remove-input-init" - ] - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n", - "[notice] A new release of pip is available: 23.2.1 -> 25.0.1\n", - "[notice] To update, run: python.exe -m pip install --upgrade pip\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: ipyquizjb in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (0.3.2)\n", - "Requirement already satisfied: ipython in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.32.0)\n", - "Requirement already satisfied: ipywidgets in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.1.5)\n", - "Requirement already satisfied: requests in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (2.32.3)\n", - "Requirement already satisfied: colorama in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.4.6)\n", - "Requirement already satisfied: decorator in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.1.1)\n", - "Requirement already satisfied: jedi>=0.16 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.19.2)\n", - "Requirement already satisfied: matplotlib-inline in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.1.7)\n", - "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (3.0.50)\n", - "Requirement already satisfied: pygments>=2.4.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (2.19.1)\n", - "Requirement already satisfied: stack_data in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.6.3)\n", - "Requirement already satisfied: traitlets>=5.13.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.14.3)\n", - "Requirement already satisfied: comm>=0.1.3 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (0.2.2)\n", - "Requirement already satisfied: widgetsnbextension~=4.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (4.0.13)\n", - "Requirement already satisfied: jupyterlab-widgets~=3.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (3.0.13)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.4.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2025.1.31)\n", - "Requirement already satisfied: parso<0.9.0,>=0.8.4 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from jedi>=0.16->ipython->ipyquizjb) (0.8.4)\n", - "Requirement already satisfied: wcwidth in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->ipyquizjb) (0.2.13)\n", - "Requirement already satisfied: executing>=1.2.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (2.2.0)\n", - "Requirement already satisfied: asttokens>=2.1.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (3.0.0)\n", - "Requirement already satisfied: pure-eval in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (0.2.3)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install ipyquizjb\n", - "from ipyquizjb.questions import display_questions, display_package" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Checking Prerequisite Knowledge\n", - "\n", - "The skills that you should have before proceeding with the rest of the section comprise a series of ILOs. More precisely, before moving to Subsection 1.3 we should ensure that you are able to\n", - "\n", - "1. list the various logical components that form a PID controller,\n", - "2. describe which tradeoffs associate to increasing or decreasing the various coefficients associated to such components.\n", - "\n", - "To ensure that you have these skills, please answer to the following quizzes:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "thebe-remove-input-init" - ] - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "98f08123390540b7803b800cd597cb2b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "display_package({\n", - " \"questions\": [\n", - " {\n", - " \"type\": \"MULTIPLE_CHOICE\",\n", - " \"body\": \"Which of the following components is responsible for reducing the steady-state error in a PID controller?\",\n", - " \"answers\": [\n", - " \"Proportional component\",\n", - " \"Integral component\",\n", - " \"Derivative component\",\n", - " \"Feedforward component\",\n", - " \"I do not know\"\n", - " ],\n", - " \"answer\": [\"Integral component\"],\n", - " \"notes\": [\n", - " \"The integral component of a PID controller accumulates the error over time and works to eliminate the steady-state error. The proportional component responds to the current error, and the derivative component anticipates future error.\"\n", - " ]\n", - " },\n", - " {\n", - " \"type\": \"MULTIPLE_CHOICE\",\n", - " \"body\": \"What is a primary tradeoff when increasing the proportional gain in a PID controller?\",\n", - " \"answers\": [\n", - " \"Increased steady-state error\",\n", - " \"Increased system oscillations\",\n", - " \"Decreased response speed\",\n", - " \"Reduced integral windup\",\n", - " \"I do not know\"\n", - " ],\n", - " \"answer\": [\"Increased system oscillations\"],\n", - " \"notes\": [\n", - " \"Increasing the proportional gain can lead to faster responses but also increases the risk of oscillations and system instability. It does not reduce steady-state error or windup.\"\n", - " ]\n", - " }\n", - " ],\n", - " \"additional_material\": {\n", - " \"body\": \"A PID controller consists of three key components: the Proportional (P), Integral (I), and Derivative (D) terms. The proportional component responds to the current error by applying a correction proportional to its magnitude, providing immediate corrective action. The integral component addresses the accumulation of past errors, helping to eliminate steady-state errors over time. The derivative component predicts future errors by responding to the rate of error change, which helps to dampen oscillations and improve system stability. Adjusting each of these components involves trade-offs. Increasing the proportional gain can speed up response but may cause oscillations. A higher integral gain can reduce steady-state error but risks integral windup, leading to overshoot. Boosting the derivative gain can stabilize the response but may also make the system overly sensitive to noise. Understanding these dynamics is crucial for effectively tuning a PID controller.\"\n", - " }\n", - "})" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/book/chapters/pid_control/intro.md b/book/chapters/pid_control/intro.md deleted file mode 100644 index 36ba84c..0000000 --- a/book/chapters/pid_control/intro.md +++ /dev/null @@ -1,9 +0,0 @@ - -# PID control - -This section follows a four-steps structure (each step being a subsection): - -1. [Aligning expectations](aligning_expectations.ipynb) (listing the ILOs and setting the stage) -2. [Checking prerequisite knowledge](checking_prerequisite_knowledge.ipynb) (doing quizzes to ensure readiness through self-assessment) -3. [Working towards the ILOs](working_towards_the_ilos_of_this_section.ipynb) (engaging in hands-on activities) -4. [Reflecting with metacognition](metacognition_and_reflection.ipynb) (reinforcing learning through reflection) \ No newline at end of file diff --git a/book/chapters/pid_control/metacognition_and_reflection.ipynb b/book/chapters/pid_control/metacognition_and_reflection.ipynb deleted file mode 100644 index f898340..0000000 --- a/book/chapters/pid_control/metacognition_and_reflection.ipynb +++ /dev/null @@ -1,30 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Metacognition and Reflection\n", - "\n", - "Learning to tune a PID controller is not just about applying formulas or adjusting parameters—it’s about developing a deeper understanding of how each component influences system behavior. As you’ve worked through the simulations, consider not just what happened, but why it happened. So, how did changing each parameter affect the system's stability or response? When faced with unexpected results, what was your thought process in diagnosing the issue? Metacognition is about thinking about your own thinking. It's about recognizing when you truly understand something and when you need to dig deeper. By regularly reflecting on how you approached each problem and the strategies you used to overcome challenges, you can strengthen your learning process and improve your problem-solving skills.\n", - "\n", - "Take thus a moment to reflect on your experience in this section. Write brief answers to the following prompts:\n", - "\n", - "- What were my initial expectations about how PID parameters would affect the system's behavior?\n", - "- Which aspects of the simulations surprised me, and why?\n", - "- How did I decide which parameter to adjust when the system did not behave as expected?\n", - "- What strategies did I use to verify whether my understanding of PID tuning was correct?\n", - "- If I encountered difficulties, how did I work through them? What would I do differently next time?\n", - "\n", - "After writing your reflections, discuss your insights with a peer or in a group. Compare strategies and consider alternative approaches. This reflection will not only consolidate your learning but also develop your ability to approach complex systems thoughtfully and strategically.\n" - ] - } - ], - "metadata": { - "language_info": { - "name": "python" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/book/chapters/pid_control/working_towards_the_ilos_of_this_section.ipynb b/book/chapters/pid_control/working_towards_the_ilos_of_this_section.ipynb deleted file mode 100644 index 3975e6a..0000000 --- a/book/chapters/pid_control/working_towards_the_ilos_of_this_section.ipynb +++ /dev/null @@ -1,206 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "tags": [ - "thebe-remove-input-init", - "auto-execute-page" - ] - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n", - "[notice] A new release of pip is available: 23.2.1 -> 25.0.1\n", - "[notice] To update, run: python.exe -m pip install --upgrade pip\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Note: you may need to restart the kernel to use updated packages.Requirement already satisfied: ipyquizjb in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (0.3.3)\n", - "Requirement already satisfied: ipython in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.32.0)\n", - "Requirement already satisfied: ipywidgets in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.1.5)\n", - "Requirement already satisfied: requests in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (2.32.3)\n", - "Requirement already satisfied: colorama in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.4.6)\n", - "Requirement already satisfied: decorator in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.1.1)\n", - "Requirement already satisfied: jedi>=0.16 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.19.2)\n", - "Requirement already satisfied: matplotlib-inline in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.1.7)\n", - "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (3.0.50)\n", - "Requirement already satisfied: pygments>=2.4.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (2.19.1)\n", - "Requirement already satisfied: stack_data in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.6.3)\n", - "Requirement already satisfied: traitlets>=5.13.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.14.3)\n", - "Requirement already satisfied: comm>=0.1.3 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (0.2.2)\n", - "Requirement already satisfied: widgetsnbextension~=4.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (4.0.13)\n", - "Requirement already satisfied: jupyterlab-widgets~=3.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (3.0.13)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.4.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2025.1.31)\n", - "Requirement already satisfied: parso<0.9.0,>=0.8.4 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from jedi>=0.16->ipython->ipyquizjb) (0.8.4)\n", - "Requirement already satisfied: wcwidth in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->ipyquizjb) (0.2.13)\n", - "Requirement already satisfied: executing>=1.2.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (2.2.0)\n", - "Requirement already satisfied: asttokens>=2.1.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (3.0.0)\n", - "Requirement already satisfied: pure-eval in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (0.2.3)\n", - "\n" - ] - } - ], - "source": [ - "%pip install ipyquizjb\n", - "from ipyquizjb import display_questions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Working Towards the ILOs of this Section\n", - "\n", - "We will now guide you through a couple of hands-on learning activities.\n", - "\n", - "**Overview of the tasks:**\n", - "\n", - "The first task makes you set up the simulator for modeling of the system, and do some initial testing on the system. The simulator is mainly developed in MATLAB and can be extended to Simulink for easier visualization of the different modules. The two last tasks make you create a new simulator (based of course upon the one that already exists), and with that simulate a version of the system with limited degrees of freedom.\n", - "\n", - "\n", - "**Task A: downloading the necessary software**\n", - "\n", - "We start off by assuming that you have MATLAB and Simulink properly installed since the previous lab. It is then time to download the files of the simulator itself, that can be found in the dedicated [GitHub repository](https://github.com/Hansolini/Take-home-Maglev-lab) and can be downloaded directly through the browser as a zip-file or by cloning the repository.\n", - "\n", - "\n", - "**Task B: introduction to the simulator**\n", - "\n", - "All the files of the simulator are located under the folder called *simulation*. The live script, *main.mlx*, provides a basic intro to the different capabilities of the simulator. To be able to run the simulator, you might have to locate the folder *simulation* in the file explorer to the left in MATLAB. When you found it, right click on it and choose `Add to path, selected folders and subfolders`. Once you are done with you should be able to execute *main.mlx* as a normal MATLAB script (check [this guide](https://it.mathworks.com/help/matlab/matlab_prog/live-editor-introduction.html) if you feel unsure about live scripts).\n", - "\n", - "The provided live script simulates Maggy using the *ode15s* solver (technically, a variable-order solver well suited to stiff systems. In practice, something that works properly for our case). You may note that *ode15s* takes some configuration options when called, such as initial state and duration of simulation - together with the function we want to solve. The system simulation itself can be found in the *LQR*-section of the live script, where you can also find the variables for the initial state vector and time duration.\n", - "\n", - "The state vector contains 12 state variables, but the tree first ones, $x$, $y$ and $z$ (in that order) are the ones we will focus on for now. These variables describe the position of the levitating magnet, and can be thus used to instruct MATLAB to run a simulation that starts with the levitating magnet in a specific position.\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "thebe-remove-input-init" - ] - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4d690d6c99f34b39b4b3be5781e7e3db", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HTMLMath(value='

By experimenting with different initial state vectors (more precisely, x, y…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a23a09e9fcf949db8b1b83add68bc744", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HTMLMath(value='

Revert back to the original initial conditions of \\\\(0.001,-0.003,0.04, \\\\f…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "display_questions([\n", - " {\n", - " \"type\": \"TEXT\",\n", - " \"body\": \"By experimenting with different initial state vectors (more precisely, x, y, and z coordinates that are different from zero), try to answer the question: is there an initial position of the levitating magnet for which its following trajectory goes towards infinity in some direction? If so, which initial position is that?\",\n", - " \"notes\": [\"Yes, when applying a deviation in the radial directions (x and y), the closed-loop system becomes unstable and the LQR is unable to correct it sufficiently. (Note that the open-loop system is always unstable.)\\n\\nThis is due to the LQR being based on a linearized version of the system. When the initial conditions stray away from the operating point of the linearization, the system model no longer corresponds to the actual system and the controller cannot correct any deviation.\\n\\nThe figure shows an instance where the system becomes unstable, with initial conditions (x,y,z)=(0.005,0,0).\"]\n", - " },\n", - " {\n", - " \"type\": \"TEXT\",\n", - " \"body\": \"Revert back to the original initial conditions of \\\\(0.001,-0.003,0.04, \\\\frac{\\\\pi}{5},0,\\\\ldots,0\\\\). Try simulating the system for a different length (i.e., change the time duration for the simulation). If provided with a longer duration, does the system continue to oscillate or does it seem to converge as time goes on?\",\n", - " \"notes\": [\"The states do converge if you increase the duration of the simulation.\\n\\nThe figure shows the result of a simulation with duration 5s, where the states clearly converge to the equilibrium.\"]\n", - " }\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that you have learned to launch the simplest simulations, let's delve a bit deeper into the machinery they implement. To do so, we can inspect the first couple of illustrations in the live script, that show the different modes we can run the simulator in. Namely we can find 3 modes: *Fast*, *Accurate* and *Filament*. The main difference between the different modes is the way we model the magnets, either as thin wire loops, thin current sheets or filaments. We will focus on the two former." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "tags": [ - "thebe-remove-input-init" - ] - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7785e48c3a814a14b2aec2108bd060a3", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HTMLMath(value=\"

Before trying them out, can you think of any advantages that you may get by…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "display_questions([\n", - " {\n", - " \"type\": \"TEXT\",\n", - " \"body\": \"Before trying them out, can you think of any advantages that you may get by employing the 'Fast' mode over the 'Accurate' mode? And which disadvantages may you instead get? After having thought about these, try to verify if your intuitions hold by doing some different simulations with different setups.\",\n", - " \"notes\": [\"The main advantage of employing the 'Fast' modeling approach lies in its name—it's fast. This makes it well suited to a simulator environment where we want to limit the computational complexity to make the simulator as fast as possible while maintaining the model's similarity to the physical system.\\n\\nThis comes at the price of simplifying the entire model somewhat, causing the simulated system to sometimes deviate in behavior from what we might expect to see in reality. Some of the system's dynamics are therefore lost when using the 'Fast' mode over the 'Accurate' mode.\"]\n", - " }\n", - " ]\n", - ")\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/book/chapters/robustness_and_model_validation.ipynb b/book/chapters/robustness_and_model_validation.ipynb new file mode 100644 index 0000000..530c42c --- /dev/null +++ b/book/chapters/robustness_and_model_validation.ipynb @@ -0,0 +1,180 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init", + "auto-execute-page" + ] + }, + "outputs": [], + "source": [ + "%pip install ipyquizjb\n", + "%pip install ipysim\n", + "from ipyquizjb.questions import display_package" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Robustness and Model\n", + "\n", + "In this final task, we will explore the robustness of the closed-loop control system. Robustness refers to the system's ability to maintain acceptable performance in the presence of uncertainties, such as modeling errors, parameter variations, and external disturbances.\n", + "\n", + "## Small & large perturbations\n", + "The simulation below has fixed controller gains, but now the inital $x$ and $z$ positions can be adjusted using the sliders.\n", + "In addition, both the original model and a linearized approximation are shown.\n", + "Try to vary the inital point and answer the questios below.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "from ipysim.simulations.simulate_maglev_with_noise import maglev_with_noise_simulation, plot_maglev_with_noise\n", + "from ipysim.simulation_ui import interactive_simulation\n", + "from ipysim.params import default_params, default_state0\n", + "\n", + "sliders_config = {\n", + " \"init_x\": {\"default\": 0.0, \"min\": -0.01, \"max\": 0.01, \"step\": 0.001, \"description\": \"Initial x\"},\n", + " \"init_z\": {\"default\": 0.0443, \"min\": 0.01, \"max\": 0.1, \"step\": 0.001, \"description\": \"Initial z\"},\n", + " \"noise\": {\"default\": False, \"min\": False, \"max\": True, \"step\": 1, \"description\": \"Enable noise\"},\n", + "}\n", + "\n", + "# Run the simulation UI\n", + "interactive_simulation(\n", + " simulate_fn=maglev_with_noise_simulation,\n", + " plot_fn=plot_maglev_with_noise,\n", + " params=default_params(),\n", + " state0=default_state0(),\n", + " T=5.0,\n", + " dt=0.001,\n", + " sliders_config=sliders_config\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Region of attraction\n", + "Region of attraction tells is a measure of how far away me way perturb a system from an equilibrium point before it can no longer is able to stabilize back to the equilibrium.\n", + "\n", + "Try varying the inital conditions to explore the region of attraction, and aswer the questions below.\n", + "\n", + "## Noise\n", + "One of the most frequent problems faced when implementing a controller in practice is noise on measurements.\n", + "Try pressing the noise button in the simulator, and redo the region of attraction analysis above.\n", + "\n", + "\n", + "TODO: Either skip this task, or fix so noise is added \"realistically\" to the measurements in the simulator.\n", + "TODO: Add a linearized model to compare with in the simulator.\n", + "\n", + "## Quiz" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "display_package({\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the purpose of evaluating gain and phase margins in a control system?\",\n", + " \"answers\": [\n", + " \"To measure how fast the system responds to inputs.\",\n", + " \"To assess how sensitive the system is to noise in the measurements.\",\n", + " \"To determine the system's robustness to modeling uncertainties and delays.\",\n", + " \"To compute the exact position of all internal poles.\"\n", + " ],\n", + " \"answer\": [\"To determine the system's robustness to modeling uncertainties and delays.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"When initializing the system far from equilibrium, what do you typically observe?\",\n", + " \"answers\": [\n", + " \"The system always returns to equilibrium, no matter how far.\",\n", + " \"The system becomes unstable or fails to recover if the initial state is too far.\",\n", + " \"The controller automatically adjusts itself to handle large deviations.\",\n", + " \"The behavior is unaffected by the initial condition due to linearity.\"\n", + " ],\n", + " \"answer\": [\"The system becomes unstable or fails to recover if the initial state is too far.\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What best describes the region of attraction for the **linearized model**?\",\n", + " \"answers\": [\n", + " \"It includes all possible initial states.\",\n", + " \"It is small and only valid close to the equilibrium.\",\n", + " \"It is larger than the nonlinear model's region.\",\n", + " \"It depends only on the proportional gain.\"\n", + " ],\n", + " \"answer\": [\"It includes all possible initial states.\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Compared to the linearized model, the nonlinear model’s region of attraction is usually:\",\n", + " \"answers\": [\n", + " \"Smaller, because nonlinearities destabilize the system.\",\n", + " \"Larger, because it includes more realistic behaviors.\",\n", + " \"Identical, since they share the same controller.\",\n", + " \"Not well-defined for PD controllers.\"\n", + " ],\n", + " \"answer\": [\"Smaller, because nonlinearities destabilize the system.\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What effect does adding measurement noise typically have on a PD-controlled maglev system?\",\n", + " \"answers\": [\n", + " \"No effect, since PD controllers reject noise.\",\n", + " \"Small effect if \\\\( K_d \\\\) is low, but potentially large oscillations if \\\\( K_d \\\\) is high.\",\n", + " \"Increased steady-state error but better damping.\",\n", + " \"Increased overshoot but improved settling time.\"\n", + " ],\n", + " \"answer\": [\"Small effect if \\\\( K_d \\\\) is low, but potentially large oscillations if \\\\( K_d \\\\) is high.\"],\n", + " \"when\": \"retry\"\n", + " }\n", + " ],\n", + " \"additional_material\": {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"Robustness is about how well a controller performs under imperfect conditions. Phase/gain margins quantify tolerance to uncertainties.\"\n", + " }\n", + "})\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/chapters/simulator/maglev_dynamical_system_simulation.ipynb b/book/chapters/simulator/maglev_dynamical_system_simulation.ipynb deleted file mode 100644 index f1ae747..0000000 --- a/book/chapters/simulator/maglev_dynamical_system_simulation.ipynb +++ /dev/null @@ -1,220 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "auto-execute-page", - "thebe-remove-input-init" - ] - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5VFc41Ojgoxe" - }, - "source": [ - "# System Description\n", - "In this example, we simulate a magnetic levitation system (in 2D), as illustrated in the figure." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "6wJKYwoqghR8" - }, - "source": [ - "![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcAAAAGlCAIAAADifrHNAAAgAElEQVR4Aey9fZQdxXkn3H/5nI11zpqTbGJC2Hitl7Pi4ICBM8nhY2MSXtZB2mVMAtbiIIGxbPBrFGGTsexgbEKQN6CsDUwcvIvZZIhNZJsJ2CTEw4Id8AQMlj3gIONZvgxD3+5pddPqq+653FZf9cvcn1Qq9det7q7uqp7pe3RGfftW18dTVb9+6vlUwvbTUqClQEuBlgKFKKAUeqp9qKVAS4GWAi0FwhZA20XQUqClQEuBghRoAbQg4drHWgq0FGgp0AJouwZaCrQUaClQkAItgBYkXPtYS4GWAi0FWgBt10BLgZYCLQUKUqAF0IKEax8jFLBt23Ec8rW9yEsBz/NUVfU8L++Dxcr7vt/tdg3DUFXVsizP84IgKFaVhE8FQeB5nmVZmqbpuu44ju/71fWzBdDqaLtaavZ9X9f11TJa3uN0HEfTtH6/z7viaH2+7zuOo+u6pmm2bfd6vWiJFfe91+thyNUhaQugK27ViBiQruurYUNyJ61t24ZhVMoiBUHguq5hGKsHN+PThJcHeNJut8uR424BNE7t9k5uCnS7Xdu2cz+2ih8YDAbG8DMYDCoiQ6/XsywL5/T29QYi93o927ZVVTVNk4vMpAXQilbv6qo2CAJN06rDghVGTaBnRa+cIAi63a4+/Liu205KfPEMBgPP88CVO45ThiFtATRO3vZOEQoYhsHllV6k7UY94/s+TtPce93v98Fe2bZdg1CVe//rr9D3fVDMsqxiFGsBtP5ZW5ktQvW5MsfGb1RAT9d1+VW5XJPneaZpaprGV8DHt5PS1jYYDMCzF2ACWgCVdlob1rHBYKCqapnTUMMGnL+7QE++fLrneTit8602/+BWwhMFiNkC6EqYeEnGYFkWd95KkqGV7wZ39Cyw28uPYjXUAHZe13WWd1ILoKthSdQ0xl6vZxhGTY01qhm+6NlCZw2T3+/3TdMcCaMtgNYwF6uoCU3TKrVqbCIpOaJnv983DGPkrm4ileTsM3lXpamYWgCVc+Ka2qvWrTMyc7zQMwgCqIlYzpWRPrRfS1LA8zxN0xIraQE0kSztzYIUaN06acJxQc/BYOA4jqqq3W63NeqkyVvndRrlWwCtcxZWRVutWyemmQt6gvexLKs1b5Bz87QAKue8NLhXrVtnGIbl0dP3fSgx0qRvDV4iK6jrLYCuoMmUYyitW+dgMED4n8IT0u122zN7YerV+WALoHVSe7W0VcCjY8WQpqSfu+/7CDLSGjM0Ykm0ANqIaWpYJ1ezW6dpmpZlFZswwngWe7x9qn4KtABaP81Xfour1q0T8T3TNLYZEx8EQct4ZtBH2p9aAJV2aprdsVXo1um6brGYflC1t2lRmrjiWwBt4qw1oM+rza2z1+sV8MIaDAa2bdeT0qMBi6aBXWwBtIGT1pAuFwCUhows2s1iRkvQF5mmWeDIH+1B+10QBVoAFUT4VdDsKnHrhNq92+3mmlIc2/M+lauJtnANFGgBtAYir9ImVolbpzX85JpjZOKUOU9R/+hPN/bxPI8usmqZ6BZAc638tnA+Cqx4t04kWGeHj8FgYFlW1Zk4GScpCIJ+vw9sNIcfTdPU4ccwDNzBX8dxIhBqWRZdAE+pqooHbdvudru9Xm/Fu1G1AMq42NpiRSiwst06+/1+LjkvbJUsy2IH3CJET3+m3++7rgtbK1VVNU0zTZMGu5Ie94PBAGwpAWXDMFRV1XXdNE1Aaskm0gcn5pcWQMXQfZW0uoLdOgeDgaZp7MHloGiqKBNn2nIKgsDzPMdxAGSGYdi27bpuv9+vE8R93/c8r9vtIiKfruuwclsB3lYtgKatvfY+HwrQbp11blo+vU+vBbxb+u9H/QIjJ3a0Perh/F96vZ7jOLquIwF6t9uV6igNPLVtW9d1TdMsy/I8r6GcaQug+Zdn+0QeChC3Ttm2cZ5BRMu6rmsYBuP7AAr3qtETuc4ty4Ig0nEcqUAzSsHD34MgcF3XsixN0wzDcBynWWxpC6CHZ7L9nzcFwFPArfONN95QVZURcXh3hHN9vu+rqsq4z4GejIULdJTGzUazcmEY9no9uBUgllV1RCtA57RHWgBNo0x7vywFYMZk2/bevXsXFxdVVS1bowTPw+qTMflot9vNpWXKNb5erwd+E7i5Ml5OoEC/3ydI6rquzKf7FkBzLdq2cD4KQHMCGxdd1/M9LGVpx3FM02TpGiCAOxsVBAHMSHVdlxxcWKiUXYZ+SchpNtsCaPYMtr+WpQDB0BWQ8Rh2SywMURXo2e/3wXLats0dl8tOc5XPDwYD13X14cd1Xal47RZAq5z5tu4hBXzf73Q6i4uLjaYH4syzHN65oydJrrvK88r1ej0YQjmOw/Iaq2G9tQBaA5HbJpb1A2mJYZtCHcbDO0f0hIJI13XaFKwp5Kqun77v27atqqpt28JhtAXQ6ia6rfkoCjTarZPx8M5R5w4FlGmajbBGOmqma/kSBIEMMNoCaC2z3TYSho126zQMY+ThnRd64sDeQifLpqFhVIhstAVQlmlqy3CgQHPdOhExJJsEXNCz3+9DVdJyndnUjvwKGNU0rX4ZcQugkblov1ZIgSbK8oD72VpvWBqUsbMJggDqkaodliqcXdFV9/t90zRrlhS1ACp62ldT+8Sts0GDtiwrO1sR0LMw8A0GA5KMU8ghtEFzwdJVIgCpR7/UAijLpLRl+FCgcdk6oTvKwDU4JmUjbAbtcGY3TbOe3Z7Rk5X0E/1OqnpcLYBWTeG2/qMo0KxsnbquZ7OWuWIy0YRAZOVcAfHox9vrkRRAyqmqY1e3ADpyItoCPCnQoGydCLmUMfjCWeBhFSswsnLGoFbYT8g1XV3uqRZAV9iCacBwqouvwXHwiJecoQ2H2j3jdJ/YmcFgIH9CpMSeN/cmEgFUxIq2ANrchdHUnjciWyfCp6eROFdEO1IJyWPcSjwJTWq7gGPCSGPevP1pATQvxdryZSkgf7bOIAhUVU2DOXaneJpSruuqqlrdWZJuq71OpAAWHl/JSQugiaRub1ZLgZqN9fIOxh5+0p7KqzgaDAZIX5FtTJrWXHufIwWgu9N1nddctADKcXbaqlgpILNbZzb7ibhq7KJPCOBM02R/hJWIbbmiFIBmKdu+grHuFkAZCdUW40kBmd06M0S0eUWfMCMtbCXKk+JtXUdTgNfUtAB6NF3bb3VRQE63zgxkzyv69DxPVVUubE5dc7K62oFOr6RItAXQ1bVo5BmtnG6dtm2n6XkY44GCwrBV4iVok2fWVlhPBoOBaZrsCVbjw28BNE6T9k4dFJDQrRPSz0RhJUzfE3+KEwsG9i16xikj550yKr4WQOWc01XRK9ncOtOU7zCqZwm2BCVvGY6G78QHQdBn+DC+GPj2TaraCudPbQFUqnlcXZ2Ryq0zQ/lu27ZlWSPnBoFFhKCn7/u9Xg+2DTiTIhOqpmkmwweFVVVFWcdxut1uv99Ps4QdSYomFigW0bUF0CbO9crpszxunWmWVSMDMmEygJ62bdfDzfm+77ouZAWqquq6bppmt9t1XRccZ4ElMhgM+v0+gBgCX03TgKqO4/R6vRWPpwUwtAXQAiutfYQbBTJshri1wVARDulxqSU07yM16QQ9GZoqXgSgaVmWpmm6rkMAkuGtX7wl6skgCACpiPes67pt257nrVQwzYuhLYBSi6W9rJ0CiEZce7PRBl3XNU0zeneYxynxPl2yavTs9XrQcmiaJhy8CIirqmoYRrfbjb91aOI08ToXhrYA2sQpXlF9lsGtM7EPGVJRMgHVoSdwU9M0wzAcx5EQp0gPdV2XJ1E7mZoyF+wY2gJoGTq3z3KgQJrwkUPVbFX0ej1d1+NlIVWM36fvQGND3yl5HQSB4zhILdftdhtxUiZICueIeqTAJek88nFGDG0BdCQl2wLVUiDD+rLahg/XnmhNBVTNxoLCAZUPt3zU/71eD3JG27Yl5DeP6mvKF8/zmj4EemQsGNoCKE2x9loMBQS6dabB98hkHo7jcLFYGgwGCFCCFrMhW8z05GwVTDQsqKrWceXsWu7iI9+RLYDmpmn7AHcKgHPhXm0YhvPDT0bNiQKE7GjKYRiy8CYZjeIn5D4D0LBY6Y+sUKoCkReDVH3L1RlgaNojLYCmUaa9Xx8FqnPrnJ6enpqayhiJrusRLmlkMg9YhpY5ZdPQGWk9o6sN/Ql5hhPVdE0ZkWEYtm0n9rYF0ESytDfrpoBt29zTLYADnZiYSBtMovqo2+1m+B2VzAJPuFfTNFc8dNJkJ+namzhqmAPTwyHXLYASUrQXIimQiGXlOzQ/P58BoHH1UbbpEoyWCsf3RBZ4wzCaCCLl5yIc2tVqmmZZViOsC+ghpx04WgClqdRei6RAFW6dCwsL4+PjiaNKlBukxRNBDZZljbSrT2wrCAJ4EFXBZSe2KO1NJDjRNC0tbKC0PU/sWAugiWRpbwqggDP8cG9YUZIXeTwgaTb7mTeZBxkIEkjU5iZP2pX5ot/vG8NPGmcnc+fpviWvLbpEe91SoB4K+L5/1113cW9rfn4+sc647VQG+5k3mQdaDILANM24niqxP6vwJoLIFRaJyECxFkBlmIW2D4co8Hu/93s/+MEPaiBH3Pwzg/3Mm8wD/Qfj6TjOCjDtrG5G8I4xDKOhrGgLoExrAyHCEJamO/xAHMYQa/FIEcuy8Gy32+31eoXDjjH1uJmFvvWtb91yyy019N113YiqPdEgFD1hjAdKuk1y565aZREhBeNFt9tVVbWJAuIWQI+aYhIP0bZtHL4Qa9YwDAAhQUASeBE4yPLX8zzyOGozDAP1I54jEvIAW4/q1qr5YhiGoig1bKTI+R22n4mq4VzJPMIw9H0fseZaxjPXsm0o3VY1gPq+D1AjWAmgLBmYNte6QWHgr+u68IEBsJIouZ7nNfSAU4AUW7duffjhhws8yP5I/Pye5nrEnswDrSMTZw0vAPbBNqgk4dwbtNpXF4AGQeB5HqJt03G8e72ehHNG8jRYlqXrOokNvoLD2YZh+PDDD1933XUct/3CwkJEjxTXv6fpeazhh7Eztm1XYYnF2PqKKQbNUlN8W1c+gJIQsLquw+8Y+V4ad8JCxgXwStrwAztwCaG/zGZONM8sU+H08EPXYFkWHWQeTjJ0AVyzH97LZ8eNt76a74DyjWDkVyaADgYDz/NIHO8VCTTkxQAwFR6rnOOG5+vWOTs7u2PHDrp7qqrS4k7TNGk8RUn2wzuJqdy4VzJNE9muIRJN80CXp7crCkB93+92uxAgmqbpuu4K487S1g0BUyRakDOAeVrn4/f5unVGvDkjqUDh2x7HPsdxImr6eD+hMkKmjcRf25tlKNCIN9NKAFDf90kQb9u2myI9KbO2Mp4lKXSQ/6uh1OAoTIwAKHL2EgImZrUDqtJcKilPX6BYI06adLcbdA0M5RJ3taJRNxhAadxsOs9VxewS+oBFapZNIke3zqWlJdqbk9YXpVkvsSTzKB+WqYpJX3l1wndeWgxtHoAGQdDtdpE0psVNlg1DkLRByb90XX/3u9/NMjqWMtPT0ygWBIGmaeQRz/MMwyBfcZGmU6KLtehJU6OG65GR4WvoQ2ITTQJQOuNKQ0+miXNQ281+vw9Tm0Yk/6rCrTNiwJSoPhoZ+rdFz9pWLN2QnBjaAAAlKVYase3pKZfzGiYKJPnXSEmfqFFU4dZJ6/fj5vQIWJkdsK5FT1HrIQxDy7LiJwaB/QnDUGoAXQF5CsXObnbrQRCAIU1kxLKfreHXKtw6dV0nhhmu60asZCASzRAWo0D9gSxhApzmLhw3IahhdoQ0QfTyQlpPbFRGAKXTUbmuu3rWR+IMVX0TDClkyrJRm69bZ0QAahhGRBCU5tCJKahn9/b7feJebJomQiXACe1IWJqjryJlut3uCvb9rWcW2DedXABKJ9uKLG72IclckjARcHsnsUVGXpDoTYSB4j5Mwu93u11JXlpPPPHEN7/5TV4jpQWgETANwxDcZQZ5TdNksQzN29vBYNDr9Wj3YkTt8jyv3++zTwS4VIBvxPe31+ux15O3//WXx9zFfR/q74lER3hynLRtO+MMJYRGeRvFUgZEIuodPNlh5Q7ugQ5tNxI9wRnhwUhV3AM4EUWTbdvCxaO83DrhzQlaYTbj5/eMcHZhGPLKAk/WUsTpowr3Ytr3F2tvxbiWQBItA1CI50ABnaqqyrBjyfrOddHv97EhyZkL3AoOU/1+P4OvydUQXbjSAE7yTAqt9qGHn+t6ZmZmcnKSzuYWOb9nSz+RBZ7L64QY4cE4tzbeEHwuRN66rne7XS7DyTULfAtznJQyHRMJoIPBwHGcJkInojrBrgLvdnA3/X5f7LpMC+BUbKMSGBV4qOfi1glnJFVVsVXi5/cM6ScvZkceIzz4qiGwjiQH4WIQxv1YUKAbYgCUyDobxHUCNJFbEalZcewqQPTaHgHfAXRA+D64uuaSiBHpiigYLe/WOT8/f+211xILmHg4ek3TEs+DxZJ50PNLlrpsRnhQHhqGAYY015KgByj22jTNiClFzf0RAKDgvU3TTFyyNY9/ZHMQ8CMUXtOjOvX7fQKmhmF0u1122UK/34fpaP08i+M4zz333MiZyiiwsLDwX/7LfyE7LR7OjmBrpJJc8UAjzxLotCxL5qVOZlbUCzJCt1xfIXsRqHCuFUCRy5R2Rs5FrNoK4+VsWRaO5/JzmnkpQyRieDGwR2Dp9/u6rtPCxLxNFyj/8ssvl3frpDOFRMLZRdJ7kB7iTV+ANSPQ2awDFiSkjYPRfr+vaZoo0VlNABoEAQ6/MoeuoXET0fBEzQrZwzVcwFPeMAyi1hjZKPJNWpZVG33Ku3US0I+Es8P2iw8ZctICnCOIY5pmbcSJd77wHd/3RZ0zCvcZNhLZ/mNlKs9+tg4AJdmfC7zMs3vP61eI1cFvep4nbT95jTexHrjMgicdGaUFMXI0TavHLae8W6eqqpjWSJwn2raJJotpmnnzlTflgEUPM/GanDPYJTyJ9dR2s7younBXqwVQLClpkz4TmxJd113XbSLLUHjiMx70fZ8x5giZ3wKcWkYH4j+VdOtEeHNUS1hRGM9HjvMo47quruvs71HYk9T2OonTp4o74HuacqIXdZCvCkDJkpLzzN7r9SDiXAF2+1VsHtRJW95kvF1waHUchx1xCvS5jFsnnKwIYpLW4+p44pLE/koAOjf0zE5IkXgRBIFpmtIyQJE+w5srcrPqr5UAKI4AEi6p1su+wHoi0bBM00xTd2KnVaoefOaZZ5588skC/UeMJYgaCJKinkT1kW3b7C6b3W5XVVU5uYRitIo/1ZQx4iCftkTj4+JyhzOAEsaz5mGMpAVRjGagwMhKVnMB+t2TZslUKStaxq3Ttu3HH398dnaWzucBC/nInOIkyMJKI4l5U7izyDDzfgWXbVkWC2XyVs6xPNwu6uwkTwCVk/Ek7jS2bTdFKM5xSXGvClHcITWOr9RKWdHCbp2maX7961+fnp6mX5+O4xDLUEIlwzBY2MmmAAoZV/mLprwwWNKxlKcGqYEbgELkzLL4SNtVX9DQmSHCq7obVdQfBAEJ7DTyoooOZFtfgxXlrqAv7Napadru3bsnJiaILj4Mw7jAgSWZRxiG4FK5j66KaeJeJ7Y5u4CYewdGVoiDRW37nQOABkFgDD/y8Hcwsmmilz29Pnzfh+8QicakaRqCP8KR+eiwkMnfkOQZT6EExwBOgFFd1+OHet/3sSr4LuVibp2qqsKbU9d1UJjWyxOaj0zmEYYhrOvj4yWVrPgLz/NUVZWZAvbwU89ElAXQXq+naVpei7nqxkZknQ1yAgE1SPAx5C2A6zqsEbvdLuKBlnlFoX4akYGtwOIyUXiJ/WNc8O04jqZp8fuFF8Bzzz03Ozub63Fg5fz8/GWXXUbO7BFrUJZkHgQ9y8xCrp5LWxhcnrQYimQtfN/caXNRCkC5b4+0XjLeb5aXfRiGvu8jDh6ifAIuXdet84hEAjjBBYXgad4+4PwbD3HA9xVbwK0TbDKSG5Nzd4TZzA5nh+WH1dWiJ6ghOYYmCrgZYSRXsYIAShLe1wPzI4eUwQSNfLbmAnAYtW2bDlCSF62q63MQBIifAv4UInlG1KDZf1q/RIQ89M3CQ8jr1kmMPZ988knQOVc4O/SzRc/4fMmMoWVsNuIjzbhTBEBBOHIayqi9hp9q9iksPCIwm0ClpkR1KhZzhIS/i2gU4d3EiMUZdM7r1omA/2EYEg0SgVTSSlo4OxRo0ZMQKnIhM4bWIwnNDaBSiZCxsuuMahFZQCO/0g7mBWJxjqy/tgIkBQVjzJFEf2ouiyevWycAFFsd5IqHs8sIRdGiZ/YakxZD65GE5gNQXkxE9pSw/FqpvSFLB7LLwOw8V4ij7Arl+TUIAtd1ydCyOUo4sdD+1FyOL7ncOmH7CUkoyBjxf0+0IkBJ3/dVVZVHwCLPMqB70u/3VVXNXgl0+dqu0yLFcOwAK4ASM1oZhJ6VeryUJC6SsqmqGmFzSlYr4eOIg6dpWppRPfocf9VBJFrGrWVhYeG1115jpAn0Wt1uF7YiEJeTZzNsS6XK/kg6LOcF+HQZwIGmD97WXCTvdLX0NROAQmVUZsXTTZa5ju/GMrVxfBaqIWRXXwEZu3JRhuRDzjAdi5jWk/dxscWdS0UAALVt+5VXXkEyVNrqDvLo+Hix5umS8TLtHZoCMmQoovuDa9M0KzW3Gg2gXM5c8YEVuEMMYortugItsjyCmHiw/uFo8MjStFRliO4obsmEfhJdPDnrlZEIsbt1QneU6M0JMVnicrJtO0MwKhXl5emM8AxFcVLA8zh+n9edEQAK9IyoU3m1zV4PUbVLhVC0qygBBfZBrciSsGTSdT3tzQ9fQMIUgDMtQL2Mo3eEsEjGqev6P/7jP05OTtIC0LRc8DiQJgJrpPL2K00BmNOSyaV/EnhdzHuNscNZAIplJJwccAo0TVOeBU1Dp2xyH8aJr7oY7Ooj9upoFAp6IhEqvMwYNwYANO7NmegOH4Zh4WQeVZO0EfWLCmycQRzbtqsTxaQCKBeLk4xRMf6E3UUcSBifqq7YyvCyr44+kZrT3JOIDBS8ZzEMnZmZue+++yItxr+C5dQ0bX5+/uMf/ziJ9Qkcj5cvkMwjXknanXjkF3nYgrQ+570vJLBxRidhSlERnZMBFAu6wMEqYxgFfoKMTBIjEtrNpuU6c80mzunxANv0cR7ColzHHRa3TqibYMNkWdZpp51GXsaJjAkstHKNLq2w7/ue5wFN4KpL4hvQcV/o6DAQ7Eqy4NPGxXKfMSogS1VcyoDyVWBoMoAyHo64jC2xEuIqWsWYE1vMvkk4KeEvlex+Jv7a7/d7vR7seLB1yX7G7k37C1EmCWjieV6/3y82I3j9qKoayfyBEx9OWAUwdKRbJ6CTGIFu3bqVwFN8kZc/vJPErtrwA6V/r9cbuWwQnxCBEYgTbXPzdEl1kIeZKlJGFlu9idsKN5MBdOR8Z9RY/id59P6I92GaZqIsr/xIq6gBzuyIgAegNAwDLu1IcI9TJEvTiKeXHcApFzNOslvTnCa085Bx58XQkW6dgE5iBEq8ORPP75ZlFRaWeZ6HLFtc/HRJwARN08DN5aIzy+RWXcZxHCItqbqt7PoJgIIP5QtuyQCa3aFKf4X0QLjeH8nF4o40lY69cOVBEGADI0AJ4JKF8SnWIo3RhNVyXZdxaQK86BM9EYkGQZALQ0e6dRIAhXGupmkYcjycHZimvBwKSRiF9Ep5H2ehf0MTILIEuGIZfvkyruuqqqppmud5YCw4vo3kAlCgpwy2SvFNXn4iudeAsEl0VCdGCOPbEwj7ILDWdZ3F5Z+c6IlEMgxDREf0hx8sd5Z+bt269ZlnnkkrSQMoOcgn6t8zHDoTK6ctMWogO21uTKQQiR2T5yayQwvvD84f8Vcml45JBKBlzKq50AKVkLx4MnDBiePq9XqglWEYjuPUsHsTu5F4MxJ0yvO8DKaMRK0nQyDqeHY+FLmXEzuD9BsQ+0IKfN999y0tLcXD2UHGnVZJ5D5B/wzPq8gjvL4STSbNv/OqvIp68r6WqugDQjH0ej3DMLjXLwuA2rZtGAZH1roYpYjNqfCexPvv+z7BTfnVC5GYIxlMUyRrLvzNPM9jxNBst05wnXCOchzny1/+8szMTDycHfs+R/fE4hdBcDpKS3zByHAn15up6g7TPhS82hIPoET+lcGq8Bptdj2QldCHyuzy9fwKfQKiH8nGb7JQAGdPRAlwXTdxlpF1g/hKEOiE+D8DfNGBDLdOGkBN0zz77LNPOumkiP874ybHQpVHnUjiQhD+nWU66i/D/nKqum9p3nFl2hUMoJKYK5G9IdVapMVetNq6zHwLfDY75gjx1gVcAkNt22YxSe71erfffnvi0GgAffXVV5Xh59vf/jY90Sw7HCom4j2V2JaQm3jrSytuQiIpkstPCIlIo2meu6RAgQuRAAr0tG07kSspMJhij0iY47tmBUUxuhV7KntogEscAnJh6Ac+8IE9e/bEu0QD6P333w8APfPMM5eWllCYhf2EI4C07zAJF3BkIiRh2yORDCOdLPZVGIAS9CzWb15PwWNVnhc4jS8SymF5kT1DGQIxNHg9mIjCZcgwjIwX7TnnnPNLv/RLCwsLkR4CQDVNC4LgvPPOA4B+8IMfnJubQ8mRxzpkr6I51kgTMnyVRw6WSI1sRV/iIxXdJIbAvOoXA6CSoKcken/M5Sr0sicwGlFnEzjwfZ8sFagZ09b9xo0bFUU58cQTIxgKAEVUecMwJicnFUVZXFxEPVDHp+HyYDAwTTMbuNP6I+S+VOuZpgBsQmVgCAzDGClSp3s+8loAgJItMbJz1RUge0OGSUVScuQakqQ/1VE+XjN5c0R0yjALhfOoruuvv/66YRhpqQy3bNkC7vLUU0+lHWAAkQBQ0zTn5+cVRXn22chysboAACAASURBVGfRjYzkt1ilDUJPjAjhBVj55YP75u+7+arNl158zroTNn7ph68H8dnhdScx8gCvytnr4Z7kQwCAGsMP+5i5l8TekEQhQCz2+b4YuROt6gqhU9Y0jXajICHBIA/dv38/0ofEO6Moyi//8i+/7W1vo9ETxeDpD1YUAPrcc8/hp7g7PO43FD3ReRa127Bk75XpiUvueKYXhgedx3eccfwZO5/yUEUFfzGDFVScr0pEG8j3TGbpugEUB7G0Q1NmV/n8SFQTfKorUQsOquwuNyWaasyjCJNMW1livuAnqmkaOCwaZDG2hYWFf/iHf1AU5fHHH4+MFgAKDezPf/5zRVFmZ2fDMMywrBa+SiNDyPvVcRxd10fsMufR69ddevdLbwwrd3bvPE85+449FfKgYafT2bdvX96x8C2P9yjHOmsFUOHrkuxGjhQsVhUUu8ItENg7j3BB8CZGiDY6Jlv8GsmECwRwinuCkXceuUjkHJeWln7t137tpptuigyKAChiqSiKMj09HYZhmvWonLl9IoMa+XXkXguevu3U4z/3mHtwWNWBzvSVyjHXfseqEEEXFxdVVRVrzAC3i5HUYy9QH4B2u93Rb0X2jucvCVM+sfOHGCWWZem6LvmZHQFKgJXAINM0EZ+NjuoUjxBMouchcINpmgjlQEKcsMh5iWQDhYncHKb1kIfGOawvfOELiqIQEyWsERpAu90uAVCo5iPrCOdflh5GHpTwa2aGoiFirt25+wA6PnAe+fSxypXTnUPfqxhOp9PBXIjdg4nzXni8NQEos1ym8EBGPEikaSPKVfyztPbYGDeJokYClAArywMKHcAJUcVGxhwhrCgO7ARDsZYSFUo/+tGPFEV57LHH6Gk0TVPTtH379oEpPu200yYnJxPP7+BwJX+x0UPLvobuO8VEDyznhm0378Tn5m0bjqkYQIGeCLFYOGxg9pBZfk1LesjybLxMHQCKkPoC16Uk6Am1stjXb3wFIAsQIrEjnT17YLrE2lhuIsYoIgdblpURcwS+55B1EAzFaabT6cSJuX79+m3bttF9gCkS1K+maX7wgx/csmVLYmwewzBkc+SlB1LgGi/sJKX8EECPHOHDA7t3rn3HjifewIm+QFMjHkECVATn9n3fcZy4IHtEFZx+xnrjVFlYOYDCjiS+0HkNYGQ9MqCnbFZThGh0GOAMFCPluV9AUIBjPnjSeBM09QiG2rYNmVoEHb7yla8oikLr4iMAesEFF4yPj8ftAbvdbhXReuLDqflO2riWZaDKxXfN94b98V/ddcW66x91KusctDdV+ALl7TIOInmfSitfLYBiuQtk13EoEwjfiGkPG8+4zC5tVqq+T7zsqwsDnHcII2OO0GahOL/DHi5iqrmwsKAoyq5du0gHHMdZXFwEB6qq6jXXXHPcccchVScpA/4ogsXk16ZfJGco8p7aecax6655QD1w8OD+p7/8we3TrwBMKxmu7/sQBHH3BcrbXZKeIO+DieWrBVDLskzTTGy4hpsyoCcEdilyqBpoEG2CdhWVEy9IzJGIXT3CUsDqCy/m119/XdM0gCM9zrPOOuukk04id7rdLg2gcEaKLEsouMgjK+wCB/nY+zt4/Ydf2njCGkVZs/aCG+6b35dxen/qqac+/OEPv/Wtb73jjjtKEsc0TVGHd/ScryVThQCKeNSxaStJf9bHZUBP2CqJXS6EXoBOTdMcxymvFCLVVnRBehuBUUwrRKK6ru/bt09V1U6nQxN5ampKURTi04l1CPsBVVUBoLSsExp/UQu1IgJGqrWHn8jNkV8ty/r85z9/7LHHvvWtb/3whz/81FNPjXxkZAG+J+iRzcULNANA06XX8RHxvzMYDHRdpzcJ/zZG1SiPYzLxlYxkxBw1AvG/J8IoiTBCwLQz/BAEtCxLUZTPfe5zGACxiNq3b5+u6w8++KCiKD/5yU/I8FjC2ZHCDb2AjCLvi/OFF164+OKLaXlI+eHjhFG+nsI1NABAYT8hSvJI9AyFSVz+wZFmzOWbYKyBWOzn3TyM9ddQDCueDomGKYY9iqZpsKulFUeXXnrpr/7qr6JveJfDKJK4wxNvTpZwdjWMsYYmWJhQLjxm9lji+VSyy3P/FdH/eFVbyRE+04KXV89T67FtOyLhSi1azQ+SoCfJOCTQgIwjgSFNtiwLbwJgKNQjkIRqmkZkzRG3TlVV9+7di4Xx3HPPKYoyPz+Pvo0MZ8dxCGKrymBCiYjzN3/zN2voZBWpNXJ1O6JCzPVspDB/ABUr+oTRBjnNRUZbw1dJ0JMkZK5hyLU1QUzrcbiBaAKZ9TRNgzAU8Lq0tLRu3bqbb74ZfSOm+6Zp7tu3jzgjgTml+u+99J3bt21Yq6z5nSv/7PPXb7ti86Ubxq56gH8qMqrJOi/jsYi4izhZhsPXlJ2lxUgZeQEUNvOi1LswuhbVOtyrI1Y1kZmr4SthPAXSodJhQqZJgmnhjfX6668vLi52Oh1ykKfdOpFRChyo67oEQOOAEoYRH8dKh5Kv8oWFhYiXar7nwzD2wggnJib4ijhZupQWhYDlWS5lJAVQnKpEqW6gUqC1sVxozV6JDLwnzrmipoCdViVLRnJYEYNQXdeJRp526zRNs9Pp7N27F+ZKiqJMTU2lpPOUDkAty5qZmdmwYQO6XYZ0MzMzuq6XROEyHcCzwhXxkgIoAk+Up2+BGsRityS8JzE1L0DA2h7xfb/f77uui1101F9H/ck/fOna3/uPyv+z9Zs/euK+2z/94Q1njm28efrRh/5u57YLTl97+sYvPmYciXaBfGpwoDIMA2ahtEZ+/fr1l112GeJVq6pqGAbioVxyySVbt271PC/J9UgWAF1aWpqdnb322msRKHrd8HP++ecXmCki4jz22GNfeuklTdMEyrjCMIynlS4wqDKPyAigOB2IUvWKVRyB7xM1dkR4gsOiwD6kLWg4a4I9hywSOsajoPPQF/Pn//cV/YVvXPm2Ey+68Z5H9/xc/9nff+o3//05f/qPr+z39/9savMxazdPv0o1FCx+f/LqP/nEhz71j/ZgAHxEyB/EnSRunb1er9PpLC4uIuwevDkjyY0PVyseQOfm5mCsqijKcccdd+GFF37iE5+44YYbrrjiClr9dbjDWf/fcccdv/iLv/gLv/ALxIrTcRy8SwRiKF9Doqzxp/wmHYDC7pLoQFO6XdVt4JeoBYHWBQociV2kKAokzisCRpCoTq7rshoDLIe1OGfn7v3DAE7Pf/W/vfv9fz23HOVk8ZEd/+E/bLr350eaO/jSrg9cc+8L//yZT/z9zy0LMhzEXup0Or7vw63zjjvu8H2/0+lomkYA9D3veU+KLngIoGtO33Dp5uHn8qt3zVcYI/PIYMKFhYWpqan3vve9YDnXr19/1VVX3UB9rrvuOkVRJicnqYdGXM7MzHziE5+gHwGAisXQFkCj04bIj9G7tXyHWRnr5uTdJeGCV2JMzntkBeujXdodxynyXnEe+eSxywA67MGr05tP3zz96nKcPWf2T9/xjovu/KFlWYck3dZ3to39xfe+e/vnH10+myM+iKZpCJiG4zlx60QsNcDr7bffrihK0vk9rF+JBBHnZZddBtw866yzrrjiijexkkLOI5fnnnvuySefnDY3u3bteuGFFyK/WpY1NjZGbiJuy+LiIghVZIJIXUUv+FpiFuiFXBwoNO+iDo8IkFWAiOUfEct3kzAlohj/CAFpL/tS77PO9GblMIAefP7u8VMOHduXOdPj/+udz+79+Q/+/rt7NF33Xrxn8+9d+dn/9cTrQy9uSAngOICDvOu6xK0Tdk6ADxyQU2Lc1HSEh4jzxhtvJCLOTZs2bd++/QhYJl29yZOSlCSE/rSIc2ZmhtwnF1u2bCFpnCEsxssDwmhSrM4LjhCWt9t8I0JxsAMVGIgBUSxFHV3F+guA9xTl7kWvWtrhksN71HjgqrGr/g5h1oKnb/vtS27b/fpyc4OXp684VVHWbdj+td3GG71eb+8zd46v+5Pv7XVJZ4ChyAgEbdLevXsVRfnjP/7jvXv3kojoX/va1xRFSdnDlQMoRJzvete7IiLOJMBMuHfcccfdeOONGPLMzAyLo/r09DQ5xeu6Dot6QjQhFynEr6MvfAUIZQFUoCccDu9CziBQ7Ao0+ZQEPWHZrqpqJORHHfvgoLn77onf+/XPfPvnnRd/8qz1Rh+NAkP37t1LIp/DrZPI/lRVjeTmPLq3QwA99baneQs+R4o4E8Ay6db69etJ2pIXXniBxYpzYWGBnOIh/YiHQz2aCJV/awF0mcTweS91XisxUwI5X5gciMJuvDmE855wWyC+lSVmsuijB1994KNnn3PlZ3bc8+OXhx7xOIsAQwm/+e1vf1tRlCeffBJiUFVVI96cRZtnei6XiDMJMI/cu+iiizZt2vSmRl5RlMSjekaHxsfHSXiqMAxTLBAyKuD8k0AARRBxXuMpxYE6jkMcP3h1iLEegQ6jbagUkpBZoNtCZJ1EumRZlmEYwNDXXnvtN37jNz73uc/B11NV1ZdeeikuSYxUWPJrMRHnEbCkrj7ykY+cfvrpb3nLW9asWfOmOf0NN9ywbt062Leyd3JychK5SPEIzMbYH+deUiCA8h17cQDNiE3AndyRCsVyvtbwE+lSbV8Tk6nV1jo0V7quE0/KOpse2RaYYkTtg3sSMPR//I//oSjKSy+9hK+e5xFvzpF15i1QUsRJIecN27dvX7NmzVve8pbTTz/9Ix/5CPlp48aNkbQlIzs5Nzc3MTFBigmPKScQQB3H4eiqVxxABZ6gWQJzkbXC9wJbVJTaCodTUa2TmPCS6P0TZxZWsaZpQtAB5fvDDz+sKMoDDzyAU7zjONwBlJeIk6AkLjZt2hS5c8MNy8Ca161zaWnpzRiphGJ8FSmkWsYLTA1jYe7F+IYyOULTXB2FEFDIThbYNDhfUedWsf4C8MDTNE2UyJt9fZIoTW+88QaRe55//vmXXnopMtTbtr1hw4YdO3aw15lWkq+I86yzzorDZeKd0047La9b55YtW0gQP76mPGnESbsvFr75KtAKAqhA9lNg0wIP71C7CwQveQLsp23LyH10uNvt4tgO4/k9e/YgYtP73//+D3zgA5FH2L9WJOJkB9ACbp1TU1O0GFTgIVosgPIdeBEA7fV6uq6zrzaOJQVaTYnlfMWmLIfoQJTVQeH1A6N6GM/v3r1bUZRbbrkFXoxwhy9QM0cR5w033LB27dq3vOUtJ510Ei3iTGQ5IzcLuHXOzs7SYlC+OJKLkgIlsGBEcvU2u3ARABWYQ4bO65A9MO6/6rouSvYnMMxVGIYI8iREXFN+EoGhkISeccYZJ554oqqqbybp3LZtGy0THNlQRSLOvLgJGL3uuuuuuOKKdevWnXzyyeyx6SI+nQIBlK8efOTc0QW4Y3duABXIAwr0uBfYNDhfDh4+9DpivhYeKoW5p6kFbdteXFxUVfUv//IvFUXZvXu3ruu33norC4BGRJynnXZahqN6hEmMfL3oootOOumkkc6akaciX6+66qr169cff/zxiqKcfPLJU1NT7AAahuHY2BixOxQIoHz14KkTn/QD36TwYRjmBlBR7KdA0yWxTQvkfIHdjTu5xzeObdu6ru/Zs0dRlI997GOdTgeGTfGSuBMXcW7cuLEY9sGKc83wc9ZZZxWr5BOf+MSFF164bt06OM7feuutxLc9bQiJ9ycmJsiDAgGUrx48caRpNy3L4uuBkg9ABUo/BfKAAv0FBI5aEn+ntJ2Q6z7ibauq+v73v//YY4/tdDqPPPJIYmzNiIhz/fr1iMUZ4QQZv5577rnFRJyof/v27Zs2bTrttNOAm9u2bZudnc3FckaoND38EGPeyK+1fdV1XdRbmXvT+QBUVApDgTygQH8BNC1qqQkMc1XFTg6CoNPp/O3f/q2iKA899NCPf/xjGkAjIs5zzz03EouTETEjxf7oj/4ocoflK0Sc5557LnDz/PPPn5mZIUfvMsSZnZ2F8dZK0oOzE6QK+9McAIoDHXt3OZYUyIgJNNq3LCsl5BpH0iZXheSmyb819m6v13vxxRdPOeWU7du3P/XUU4qi/PM///PMzAyJxVlexHnRRRexQGRambiIk3ZgL0/4+fn5LVu2hGHIXZfC3jeBJqie53FPeJ4DQC3L4ugCxU7xMAx1XRdiAimQ/RRoNSU2tWquhZG3sGmaN910k6Io99xzD/g7RVHWrVvHS8RZjOXkJeIcSQ3ij8RdlzKyaVLAdV3btsnXOi+qUF6xAii4XyG2LCnJv+qgvED2U6C/gMCmq57UH/3oRx/72McIdJ522mllRJybNm2SSsTJQj3YHghMLCwwEFQVfBgrgAqEElF6/9XJfsJMTcibkmX/FysDEef5558P6Px3/+7fnXjiiYqiXHjhhWmn6erux0Wc09PTXESc2cSZH37OPffcRx999Mknn0TevexHqvhV0zQhYn1sZ+4jYgJQ6HCEmCL2+31RXk/dblfUWUMgDyjqdcV9ZSPqZaKI803cVBTllFNOeVPBzQiUsOI86aSTGMsnFouIOCcnJ/mKOLNpePPNN7/97W8/8cQT3/nOd5555plCvEK4OwJlD5n+lW8YUFIzE4BWIXwlPci+ECV4Faj3Fyj9FDjR2csg168jrTgRk/jtb3/7m5aViUhHbkasOLmIOG+88UZijJlrXCULW5YFBvztb3/7vffeW7K2Yo8LzAhfkeiACUANw+BrfcpIfXDdQo6TAqHEtu3VpqxjXA8ji8GK8+STT0a6oQwrzne84x3/5t/8m1/5lV8hWJl4sWbNmgKO6qgqYsV52WWXlbTiHDn8kQWuvvpqRVGOP/54TdNGFq6iAHc7dvZOpmSxZq8gueRoABXIdQs8RIt9ZwiRlgh00k1em8x3LcuampoiIk4WK873ve99YMfeDGuUCJ2Fb4oScbJQa3Z2VlGUT33qU0JCMg4GA1VVhfBDvV4vJYs1C9myyowGUNu2RVkjVqE1yyLG4d9W5ztDlJfEYarn/n9paSlRxDkS+6677rpTTjmF1sVDxLlmzZqRz2YUgIjzuOOOg6N6zSJORvLBj0AIiok1p6lI5jsaQEVpzQS6jTrDD+OK5FtMVLgpvDOE7KsCBJydnaUzque14nwzzDtBT1z8wi/8wllnndVoEScjGT/+8Y/XoPFP7ExFUsjEtuiblerARwCo2JeGKFGgqHeGQJMDx3FEmRzQaz37en5+fnJykkXEmcEn3nDDDcgpFMFQ8pV+ltykL1AgIuKkC0RGQf9ErkeWGVkgEk2K1Exf1FNJpJXErwLP75WC2AgAFfXSCMNQ0zQhokCBnK9YaYkQ67zEzRa5WUDESYNg/Brh3GmgYTenl1nEGaFb/KtAdxiB+vdKZVNZAIqXhhAUq/SlEV9Y9B2BThqiOF/f90UZ29KUj1wXFnHGETN+Z/369QRA37yOF4jfaYSIM0LDyFeB5wxRsqmq3xlZACrQlGcVcr4CUUygtUNkh+NrSRFnHPsid97Mh3HDDTds3bp106ZNI3nPiKO6KCvORELlulmpKDC7JytYNpUFoAKNtlbh+V2g5so0TSF2LZFdx0vEGYHL+Nf169fDhB5yzHiBG2644brrrqNjccpgxRkhV96vAkOaiXKHgSSwUtlUKoAKPL9XZ7Q1cs0JRDHDMEShmCjrPEwHdxFnIiDSN88991z6CB9hQq+44go6Fmc9juojV2bJAgI966o+RGdQpoYzdCqAipVCitK/i7I8xesqYylU95Oo41WlIk4aLtOuIQPdtGkTOdGvX79ecivOwstAIPspVjVatQtlKoAK1KVwD7vPuOzwqmQszLeYwAC3FQVZyKBP1SLONMSM3AeAbt++nU431FwRZwbBBcYVE9h0PeY0qQAqUCMsylG3fighi76KUK+k8uyL2nLM1ibijAAl/ZXwm8irThTxF1988f3331+Rs0o2/Wv4VWBwL4HsZ6XWS2TWkgFUoEZYYMBqgUy3QDVO1U3XL+KkEZO+hvnne9/7XiLiVBRlenr6u9/9rjr8cM/3QLaZwAvXdXVdF+JjJjCuWG2CqWQAFWjXIlD1L0p0EIZhRaFiWPZtRTlm4yJOwv3RoFbb9datW88777xjjjmGOKqD/ZyZmVEUZc+ePcDQqkVmLDPCsQykUkLS4YRhKJDzrYf9TM0LXzVXkrFERBkwVRSwOmOk5CeBsldgN1/2JCLivPDCC4slQ+eCrRkiTgDowsLC9ddfTwC00+lUavVCJr2eC8MwREUCEhjcq86mkzlQUXYtAkUHAtU4KyPHbFzEuXXrVi4gWKASFitOAGgYht1uF+wn/hqGwfeNUg9WxluxbbuiGG7xtiJ3YDUlyiyvzqwKyQAqiu4CBaAC8xQKbBocaGT15/oaF3Fyj7CZC0ATrThnZmamp6cj46IBtNPpEAxdXFxcAcJQ13U1TRP1JrCGnwjB6/nqum6d8JUMoKLYfoEenLUJTeLLSKAKvgyAWpZFZ1QXLuLMsOIcGxubmJiIUJ4GUF3XCYCqqrq4uCh/bKrIcOivnueJsqJB0nlR2F2/v0AygArkvUUJvAVqkARKnMsAKJKMr1u3Tk4RJw0oiQwRAdCHHnpIUZQXX3yR8KGdTscwjIZiqOd5qqqK2kdiD++2bdcc7TQZQIVw/gK9ccrgCL1Ri11XpAdn7Iyqqowl48VuvfXW448/Hp48uQ7aJQuziDjjvY3cIQA6Ozt76qmn7t69W1VVTdPAilqW1UQMBXoKtCUwTVPUiwdWUzVHj0sG0MhSq+drv9+vU3hBD6o2qzG6UXItkPkt+eaYm5tTFKVOoWeiiJNQMtcFAVAY7YH91HUdGNrpdPbv398sDMXJXSB6CrQ5DcNQ1/X6XSEkAlCBGqSVoQfPBR+kcBkONAzDk08++U279JIc5cjHt27dGhFxzs/PkyGkXczPz4+NjaXlEI4AKHDTHH6IPBRxbRqhl3ccR6DcMwxDMICijMBEOftLBKAC0/k2Wg+eBh+M90vyv1NTU4qiVCQGjVtxzs7OMo4rDMO5ubnx8fGlpaXERwiAWpblOM7i4qKqqqZpapoGnZI2/Pi+b9t2SSoldoDXzcFgAIGDKPAKwxA5tUQxv2hdyPAlAlCBosDa/MET90xJHjCxTvabJcm+sLDwpgbmzTRtI7lI9gJxEefMzEwaDrKPNFKSAKhpmk8//fTVV1+tqqqu64ZhwDIUqiSwn67rqqpa/wkx0uf4V0ifLMsSordAfwaDgUCL/cFgIOTwjrFLBKCifJDgcybK8KCkFDK+o/LeKR8B4Pzzz0d8YnaITCsZEXFOTU1Vp1QlAKpp2ve+9z1FUWZnZ4GSlmWZpqmqaqfTAXM3GAx83zcMwzTNmtUUaRM6GAxwbBcL60BPUYqjMAxt2xZotysRgApkxEpyYWlLnPG+wIHDD6ek2S/cySNhidMgMvF+MRFnBnnn5+dHIi8AFLYfS0tLe/bsgR6p1+upqnrgwAFIQmmTpsFgAOa02+0K5PjCMIS3ogxojhdMxlxU+hP0ZgLnQhYAFaiCBwcqym5OOAdaXoFmWZaiKBdeeGEiOGbcLCnizNiZ48NPRoHlMBDDD4aPcARATOSPdF3XcRwYNhnDD2GyfN+HqFSIyA8dFpWjLUJSeIuKwi+IPgXu3NRgIhEy1fC1/DYu00lRvv/os1gOlIv57bZt296M5Z6BlfRPVYs4l5aWpqen05TvZJ0AQKE/xPIDgL7++utIxzAYDDrDj67r+/bti5g0ESBzXbceBEG4Bk3TROVrIKTDhVj0hOhAOClk4UBXsx5cLIDCgK7ka3x2dlZRlKuuuooGyvh1nSLOyG6PfwWAInxiv99//vnn77zzzk6ns7i4iGRkQRBAdwQ+FE7WpmnScAkY1TTNtu2KtMBBEHS7XX348TyPbj0+qHruDAYD0zTFWnclepfVM3y6FYkAVODLRCyEiW0dYviSxIdbZ1qCde4iTnoFF74GgCISa7/f/+Y3v0kCg4ah/f27rvvgb69VlHdd/tWfvDb0jod/5BA4Fvc/tfMMZe3Gu+cPDJsPggD6HF3XHccp+TbCiADfhmGoqmrbtkAlZ4TCYP0iL5JImaq/Oo4jFr7JAGUBUIFxlIVLIQWaH2AdcEmDeuuttyqKQrt1VifiJMs3cmFZ1uTk5Ej1EZ4CgML5DRzogw8++OKLLx6G1KU9f/uhNYqyZuNXf6h2NE3bu3cvLNVt44d/eeE7FeW3d+7eH+lAr9dzHAfuTAgn3O/3GbX2g8Gg3+/DnQQ12LYtCctJhomAk0QcTO7XeQHFESNVq+6YLAC6mvXgYscehiHEoCVXJHHrrFrEmbElYNXP4qRElEiwQABsQTXU6XSGLKT32M0XXfLh/7ZO+f0v/ACy0GWTJl1X9z58/f97/Y3bfv3Mz//L3rTOBEHgeZ7jOKhTVVWYQMFVHHbHcJ6hfZ/wq+u6FUkD0nrLeL/X6wmXwIoNNBUnVAugyzQRe4gWDqBhGHIJJHjyySe/aRAKzu7888+v1IozvpTDMFxaWhqpOyIPop+AKiCaaZrwRxpaVu594Jr3//nDD9525rH/8TP//H+HEKppmqU/fuuGK+99efbz73znxXf9iN0CrH/4Q9Cz2+32ej3clkGySSiTeAEZhVhJglh/p0SyyAKgYl3lxAKoQB9Wsib279/f6XRKbuOpqamTTz55cnKSkQckrQu5AICiaXgTvPbaa0888YSqqsuwOHjuzvM+etfTL6nTHz3mmI/ueqnb6XR0/bWffv3ai29/Qu38n5vf+c5Lv/Hi0MDJGDLvBw90/vm2y8+/YNuNO2/6+OUfvurSDX/5dCBkZJwbDYIAwxTLF0uInhKZMYmFMLGti3UkxW7r9/sIJFwGQ7l7W3JGgqOrowEUh4C/+Zu/URTl5ZdfXhaMOo98ct2OBxcWvb3fl31usAAAIABJREFUveldx56x86nXLKvz4oOf+90/vv9Fw977vc+94x2b7v15GIaH3IH2zt523jnXPPDKUK20f/fOc5SNu149eHSTDfyGyPbsjHZFQxSOnmk2v7JwoGIhTGzrAtMxkeWOOJIQ1ZXBUFJhzRcTExNTU1PsjQZBQAMotENPPvnkX/3VX/30pz9dXFwM9txx9qm3PeG4lrWw547fV47Z9m1t/4+/ctUldz6lLy46r8/++clr3//Xc6BVv997/t4/+pXjr/sXD2r5IYBunu6wd0i+kkEQmKap6zoXo4Iy4xOOnuhA4hBaAF0mi1gAFZhKj6wJOrGaJAYipG8jL94UfY6Pj8ezHmU8aNs2AVDiSqBp2r59+4ahmF61vnPtMZunXxsMlpXyC/d+8Jh3jH/xrz47fst3XuoMVeQ/uucDv7H+yz9aPJSB7sBr935E+fef/Yefd4YGYY0H0G63q2ma4zjC36bC0RMx9lsONGM3CQZQILjYlYpz6OvDj8DArFmTNOo3dgECUlgTACVuxKqqdrvdvXv3qurzc7e+99hPPuIcUq+9+tj1ZyvKmdsfWTSXFfG6aT5z50W//ut/+pg+zHw5GAT9p28/Uzl185dmf6Yvvvijb9126UlKMzlQ4mUvVuKJ2RYeInpkqJSWA12eKbGunGEYGoYh9qCEvExAlpL2TKOATvzv9vBDAJS8MACgy+dW7Ydfff9v/+HfzQfDsB2GsejP3/W+99017x+Ef6emzf3d5Scob333H1z7pQd/ZixLAPp7n73rwycoirL2gqv/4s4//9DJysa/eaXfFz9a5h4Q59Q0bou5Jj4FhaMnNma20WsLoMuTXS1+vf7Yzss3X7rh9DXLu+ucizeTzwc2nH7s8jbePP0z2y7pC3T0mvX23DE+BIi1m6dfPfqn4bfgX+84+5hhgSunO8tiOxISDeCS8IistxYWFnJ1jbwkCIASEy5VVe+77743fVIjgr+Ip0Ov1+t0lk3rwbb7vg9NC2Xioz5w5btO2fmEusyrmtT9XD2tr7DneRB3SgKdRDUnlgtmcfZvAXR5mdZhidmZ3jzEyqMUCwf3LbMtp972g67H6D+TuqsOvvrAR09XTvj4Ax0fZQ6+umujcgRAD3a+/dETjjnho9/uHFIN+6/u+qCiHAJQUu2IxLCxVsiDQi6mp6cVRcllNQUHIWJIj1AA/vCj6/pDDz106aWXPv300/T7zLbtiBoaEeyJzHQwGHiu9i+P7DZdNwzDg4sPXHXMOTc9YZO4c4j4K1ZKE5+gwWCALEa6rssDnSTAvtiTEAt6tmZMhxZVHWxCIoAup5KZu+28//4v3gFN0+JLPMedOLQtt5gBoAc601fGARTcqK7ryU3HW0kuV9Pdubm5yclJ9sYg4AOQgQNFIDuk9AG22ra9uLhIA2g85yBEY3v37jUM4/XXXzeMxTee+8oFx/znrV+e/u5DX79103svv+uZ/ZQNEwmkZNu2WFkNaNXr9Wzb1jStjpXPPj3D1CCGYYgNsI/oEIyq1JYDXZ7eOiwx0wA03PfETX8y3TnA35XgaACNLeNUAAVLHuG5Yo837wawkuAXANTzDvH+wDhk6FxcXIwMP3KoJ1mAsNuH3Mpr+txD0/fe+zd3f/Of5l7u+4fOATSZEHMEcZUcx6n/fNrv9+Gqr+t6t9sVy+LRlME1hJ70qytepoY7jLwnetIC6DIdRACo8diX7ltWUoT+q7tuvGOPx98fqQSARrCmhlVbQxOmadKwCAAlAlDiYYn9E8kS4ThOXJngeR7i1eNXwrPABoiIleND832fxBxBxJDqsAxe+eA3ESyqfuCOUyByZzAYoIfk9RYpUNvXXOjZHuEPzUsdpuwRDvTgy7suv3U3zK6HvRiGRFroPH7ntgsu2XbTzTd95tM7vvGv5tO3/+edy6WW7bqx42EcE9UC6d/Zdsrwd0qmSQOo9Z1tUBodsa0BB7rxlqlbP37N9bfsvHHbxX/4ybse7xxYPnkGe+44c1jdO2/+p6e/+tkrLz77mLFPfvuVl49uJaqqinSSfF278/uvPHLbNZ/8s503bb3gd7bd/aztdx7Zec32m3beuO2CDVfdfdRpl3GrzMzM5BJ9drtdAnBoAuQkCiLHcYChjz322NVXXx0BUHLSj3QP531N0zxv+RVoGHDrXM7xq+v6yKMoFFCWZSEVqGVZ3W6XPYBTpDP4GgRBv9/vdruodtl/37Jc160OoxO7wX4TdtBi4+Oht3nRswXQQ7NMLAHZZz13yaMA9A3jqS9tXDeExiMVvfHjr3/yd479wy//676h9Kz3ytc/PX7+u9aSUgdf3rXxHZR1YUQLFPkahjSALqs2Io8DQE/Y+OWnD0nr/Pm7Lzn1vJ0/cCC8O/jyXb//7992yu/+8b3PLz7yJycoZ3zykcUhv3yU6imiqoq2cvD5u8ePP/b8zTfe9xJ8HJ++bYNy+vsu/+y3XllG6oND88nxO/Z4R8hw+OrNqPLj4+NjY2NTU1MRG08kEWGXfiaG8AGAIpwdUSTatg3F1PPPP3+4I4f+NwwjUdMCMSjBUDg1IcYVIIxRC+/7fmIAJxxNAO4k+Ei/3+/1ejTXjAjHiP0MXtvzPAmZzQhVR3LrkfLVfS2Ani2AHpmOyp2RAKCHzJiGBkxHoHHYDefRPz7hbSd99rtHsMR97PrjFarUq9Ob11IAGhFiRr7GADTMfnx5yzuPfPrYNZfe/eIbww4Ny//qxIPq6+HB/a8+tzDE2bytDCs5ZefuN4DKePy8nbudQ6SPoPzhCQGKAeMURYm7ac7NzTHaLcCVJY5iqJwctCGDNk1z7969CwsLcZ0eciUd7uCR/8Gc7tu3T1VVYtJEkAsh4CzLKsAAIlCT67oEKBH7jvwl913XReEj3ZL+Cky6aZqEVqK6XCbAviwy0LiQvmZq8tfhRAZwFAcaht5TO8/7C+oIf9B97HO/ppx69fRzR547sHvn2joBNByyk8eP3/38EO2G2LfxnrlFgxL/FQLQqNwgRc5wZOTh2NgYQU9cUD/muMxwBES1BNfwBjVN03Vd5DSONAOPz0RTJIRiATMFRhIMKWogAj4C1pGaV9tXqQhSMsC+LABahyVm5jqt3J4jAqCh+sDE/zwU7sx7/L/fMPPcslHROZ/5p/97RAtZO4AOT/0Esg9xrK8NBsj5M6RfkwAU6HmEnkcvABqXiQwnA0Czo6ZCSgCLet/3wXjSiIkmhDMKR9NAwDeQyLZt8uoS0InDTZYPsN8C6CFa4jR0mLAV/B8F0CNNDOb/+vI7fuI89rnjldP/v2/8q6qqh2RtYgD0aA50yDxS66wmAJ2cnKQ50ImJCdBrbm5ufHyc5fAO9KR45yMExxUNoMSbE5zjk08+eeedd0YfOOTWacTv4w6EaARDEzsAnJXh3Jo2iuruwwi3Wq+/PL2Pv+TyPH2orCwAioi2BQbA65HKFfGpANp/Zdc113xHD51HP/Mfjx278aGXh9l1lzH0jSduegfhB8MwKsSEEpwch/NCW6x8ePCNJ3a8IyIDPXz6PhxVYe9y2CHaf2l5XEfM9UOYBxx+KtbnWKORxw9P59LSEsHQiYkJokSanJwcGxsjXw8Xj/7f7/fpQ3T05zCMhLMjyw+Z4xAYNLEVorWP1wlNFLJ7QZUEokW0/4PBAId9SbiwxIHwvUm470QtHN+2GGvDFMQl44yPk2KyAGjlDCAZccoFXKRTfuRxOxlAg/3P/s3lJ5x/29NuGPZe+PrV/+Ftm+744cuapqnqSz+752MnKDSADhFz/O6XhhLKg87jO844RlE+uOtV2GyPxKZDR/LDvqQo/zuffcyAfic8uPjI9vHL797TOzTcSPnl1EmG0fnXv75MUT4CD/rlgsuIufaw2DRwnrj5DEWhYglHKhnZydGkTsQ1+jHENs3eq3Q4OzoYAgD0+eef//73v5/YUNytk2768GtmObIBUccnWjjSMCpci0IPge+153mGYcjpKsqF7BIBKG3kzHcWGWurSo+UGkzkcISRNVsfMJZN6vtvmI9/7U8v3bDp49dff+PExI777/7cO2kADQ/uf+buqzYsJ4245fprPjX1T1/54PAceszZt3/tq1dvvvicExTlhHMuvnLnY6/M79q++eJz1ipr1p7zB5uv3vXTn+66evMfnLN2zXI0k8u/+NjrQRge6ExvveCvvvfD++66a9eDjz76rf950/U773sOJk3B/OHya07fcOnlV+8amvwP746fvVZR3vnbf/DhnY/hMBvsf/arV/3O72+76ZZbrr/2U1+97yuXrh32avz2Xf/rSKObt+96bm7XkU5uvnrX3HOHOqksN3KoDca5Si5GtBPZewPqIHKEJ/FAwSghKFGaVUbcrTPSFQQTcF2Xtp3CdVwaS2BUuA4gMoqSX5eDA3geyWVfsjaOj0MYNdI+l71FWQAUq5a931WUJE4pVVTOUidhww+9saMyUJY66igDOKg52u7IqEvs9tjw1yQASqQ3WIQEQBMV7gg+ku0wQ1T/NIb6vo/EnPFq6aAeruvGC9QxqZzagLuqhF72CPKgqiqt2Ss/aIkAlJg0lx9VsRrSDP2K1VbgKSKRQXixUFYAXT6415vvYWlpaWxsLM1yfjAYHEpMNAyGlE15Em6KACh8kODR6zgO8PT5559/9tlnE6tKdOuMlIxgKGaWMMhkoiNP9Xo9y7JUVbVtO61M5BFJvoLlNIzl0Ki2bWefAOrvMyw9qzhiygKgwvNqABTi5tP1TzZaXGZCndmj7UBF9SW1XWici1mJp1aa9MObmpmJiYlE301weaZpMprFIBv7sg/J8EMLQIk3Z7fbveuuuxQleXekuXVGOt7r9VRV7fV66CGRyUL5m8G/B0GAKHMAI5mRFLgJ0If2TEL2GQS3bbuKviUvkchSqOdrtn6znj5U8Y4q1PNAfejmjf/1zGVp4hGpZaGaKn4I3B+YJkYI49UjImVjhxhgn+/7s7OzANBvfvOb999/P7oEW2AIUh566KFvfOMbafZSaW6dkaGRIzwYUiIDJQzRSFFAJOZIFRAQ6TPLV0A8cBOWszVPPUsnC3jTMlZLF5MIQGWQozvDD00ggdeIwiuwA+xNB0Fg2zZgtOrjWxkFBYm3PzMzAwBVFOXBBx/ESPH6BICmKZFQkl3aQ2Ooruu0XSp+YlFowEMU/lGGYUDOUDOYwsPKtu1hTr3lACWe59XcB/YFiVDWCKRSaSclAlAiispFJr6FhyGRUi2l+bY1sjYYM1Y6/SP7kKtAEAQw3zEMg1f4H8uyZmdn0Y2SYYDBBoJXWlpaOvHEExVFec973kMO1wBN6BKzATTDrTNOMYKhcbNQRF/XNI1ds4EYIgBTBHwqH8Ap3mdEmPY8DxIPbfgBZap+QSZ2JtdN3/drS8gsEYASb5BcxOJeWAZJAhmUZVnCrbtIZ9gviDLEMAxsb/ZnIyX/7M/+7M1MKC+99BICvpUJA4zOkPphqH/nnXcCUmlvTvi2k5KJF7lsNgiGItp5RFIE06gCLjppAZzAi5AII4lxRhD1Dj+RwE62bQN6VFUdJh81u91ur9eT84QenxciUOp2u/VwHhIBKFnBcbrUeYc4pdTZaFpbkNllS8rSnhV+fzAYgGc0DENVVcRYA56mjQi7GoyPNUwg/NOf/vR73/ue67olGR+oZWiaLCwsKIry6quHku6RUzlESaqqTk1NpemRcELMZTdCYyiUb4TzRa+4uCcBECGFABoidBOmYOjjdugPLI1IYCcac0uSmiZynde1qTTpQUkEoDIo4sMwlOoUTzIU1fM6pVcG3+vBYIAov47jkMiV9H7GNdnV3W6XYzjLtPfQZz7zGXJ2JhkBkONaVdXZ2VnaizROkLyHFdpFCvKZyPECdk6qqmbo6OPdaO8I9LKXC0ALnGKqWD2dTieNRaqiuZF1RnJRjCzfFohQIJGAg8Fg9+7d5M1E1h6kn9kyUNSf7dYZ6QO+gg8F7xkEgTH8RA7I0MhpmlbbOTSxq424SSwxIux8bZ2XC0AlOT7DHphsrdomI62hNAYqrfzKuL9ly5aZmZnyY4kn80Cd5MyOr2A84c7EeBga6daZ2HliY49f4QIQt8SCJqSF0UQa0vmiRUEnOiYXgEbWdBrtqr4PgVEkiE7VjWbXD2NgeTA9u7flf4WAkujfC1eIk3KiUI+25STyd+LNySjfLBbfExhKTJoyLL1p+7AIo1qYJo1+sIwRWxUDlwtAsbCqGGeuOmEjoqqqVBiKcJO5BtLowmlG7OyDgtdmIocCYCVVdbtdiCNhCkIiM0xPT5NQpKQwfcHi1kmXJ9c4vxP3mGzTenKotywrzquSOlf2hZxe9nIBaBiGJAiYwNWgaVqn00EsGZJnUWB/SNOGQWfXILfbi2QKZJCLqIzwpGmawFnor2kAzVDEl3T/jZuFQo+cpkFaSTFHkics5S6xipPQy146AM1lXpdC8LK3VVVdWlqCjhXpGcrWyOn5DJaKUwviq1kafsr3I4Nhhxk8fSJWVRVf4c3peR47/0uLAgp0G749RMjAEqWFAMrKZkh934eAGC55csqvpANQ4WJQ3/exeQqfzgrsIvZHIioI9gebUnJqampsbIwdvxLH1e12dV1P23IIZ0ceJAJQhKrzfR98KCmQfVF+xYLxpM/m2awo+gOGlARAoh/P7rDkv0ZiqZBXi5zdlg5AoXEWSKwgCLDxEKOe5lME9opuGmF+JF9YdIdzXU9NTWWLHUfWRpusxwuTcHbkJzoAAqyXcgFoLrdO0mjkAnokEm0EwgGklU+U4dKPQzgIF3XbtiV3Uad7Tl+D3ySjaMr7QDoAZQlYS9O90usChn6V9odUno0RpNgqvBhJGRLOjhDHMAxsV8KKIlIGCszOzk5PT5PCiRdc5E6IuByJLdLr9eBSyfK+BO9G/L5KOtEmjpTvzSAIIC2Bny6CpPBtouraZARQmiOoevzZ9YMdTjsJZj9b9a8jkaLqDkhY/0iaxNlPOhcWEX3SgcGmp6ez9UgF3DrTSIfYIhFPeZL2g6js0x4n94kTra7rcKIFmMqwkhFZio7qxCvuDBl+FRdppJMRQPHWrYIKBeqMqGsL1FDdIyPxorqmq6h5dnY2MY8bY1ss1Iizn7QEk8QDoyHMsqzEQM6RXuV164w8Tn91XTeeeYJYMuV1TwKXBw9ahAixLAshQli4WrpjBa7hwuu6bqQD5YMbFOhM4Ucgkk58XEYAlcSYCfSSVhKK7tHu1YkT3JSb8/PziqKMPCynDQdLPBsR4uwnEhETISNhPFn8OCM94SvtSct9Bvuq7IzNkY5Fvvb7fc/zAGfD5K/Lxs4kzovneQhHksZwRWojX/EUwh10u13LsogxtWma4EL6/X7eakn9oi7gKkoWRrwbkgKoJD6doBeJwhsnnwx3oH8gKCBDlwr0YWlpaXp6uhgHirzB2eiJlEemadJ9i+h/4M1ZTI1ZzK2T7kzkmhzn42EZAKO8cgUD+6A3A/AR7CPRXkjQJnIB8CUFIKiNAHHj4JKeAkYve0kBVKpTPHbUyP1JU7/m64hrYM2tC2wODjwsDmOJk0iEnogfrOs6LiI4u7CwwHKKL+bWmU09cNa0dp6UZ9zhpHzhCxzDCY+JC5m3Q+GR4sFchE0GUBmoI4NLEpmJuOyM/CTJRdytRZKOVdcNnHMZVSuWZRHfc9Il2gaexPOmpaIoidDL5Km0i4oMh0nQpsRdiRyibcyRtElhv1/Myz4ZQGU4D1rDD/v4Ky05GAx0XZffNg2HWfn7SU/W3Nzc5ORk3sN7oqaFrpa+TkyOEjGxIKZIcSPQ+fl5FuFssbM/3c+M6263q6pqIitKuGZN0xzHkdByOWNcMvxEUtHADy1Xl5IBNP6uzlUpl8KyqUeaEg8J/Uzzp+YyNXwrGR9+2OskwsFEjiyxnsT0fBF/JHLiKbCLSKM0S0tu8rqAoahhGGkDJ6GbVraLJy964sVTMhliMoBCGMSxowWqAouhqqoM7DD6nxiXt8DQqn6ExZ+66j6w17+0tMTuuInXQ8TaPLstxAONl6FFlnQYMPp+/KnsO/Hjf3b5Ar8i80fGC5KOOVImhVSBvjXlEeItqut6XrOwyBiTAZSjUVukPfavOLNAzScJhuKMFteKsg+qzpIs/tR19qdkW3graJqWS0Dh+76qqnGWLaKlpIEvzYaJBeUjav2SQ057nLwgs0nR7/fBXsmfgjhtpNzvQ22oqiovJj0ZQIk8iPsA2CvE3CPVeOIRjL0qjiWRm6wp9hlBEMCfmmT+4UiK8lUxyj2JK04G25XWmUgmTlIsssKJ72aaNdKOHTvGxsbI4xkXkZozSpb8iXh5Zgs9oRtZeTFHclGPJMRGwm2O+zcZQOkXcq6OcixsmsspVYkjUJyJ4NhWrqqacpAngwIoyKYEsyxLUZSRMefhX2SaZoEFkHZ4h3MEvYvIkYs2bCIEDMNwdnZ2x44d9J20a8/zGKPZp9XAfh+vFsYkdMRTXtO05sYcyUWcCG5mv2nYa6ZLJgNopfpEuvmMa9jiRSKHZ5Sv7ScQJ/v0VFtn2BsiPhWS9Hx+fj47bB06THK9sY8UJTOSeUTsjWiuk3hz5m2OLk/gmL5Z3TURbjCeMwiSwk2+WV6VI8kIX3vLspBRompH+2QARUgksTuNvC5ItPCRtKutAFQZpIe1tVu+oVxGwuWbK1ADuCpd18totGF2lggocOik+Vk6eE2G0x77WPi6dTK2i1BSudyTcLqH6RthS5u4quHvTwKU1MlfpwIovaoYp7CiYtjzFVVeuFrHcWo7qRXuZNqDOGbKZjbo+z5RepTU1GUYEbuuG3E0ooUb8OZMoxvjfZqlZXyEVzFyzshLQMK4acMPAo7I7L0Ov3vLshBCFKJn+r3Ii6TZ9aQCKMnvmv18Pb/meq/W06UwDDNS7tTWhzINAbA0TYNkvTbWI+IZCTNmZKDiYgeelscYtIpYKdHSquw1nyvSc6SVMtNU4FkiOM4Lo2jL933P85ATpf4ATonjRWYdhCkhSXPBadYPmnQPUwFUqpBInudFuAZ6DKKusfckMbEqTASc42iZUdUrcsuWLWNjY/1+33Ec7hHIIV1JG0L8NEM8OBHWM8NWaXp6mlERH4ZhRMxaeHYKP0hMF8oLJegATggwitAhkBf3er1+v59G8Lz9932/3+/3ej3kSTVNE3CpaRqUt67rFnsr5O0JY/ksABUiyknrt9hXelqv0swM08rLfJ+OwqtpGs5EHBcrYlJ0u90HH3zwnnvu0XWdewRy2MNnyO7jRxkSjj4MQ44xwPBypRX9QqaeGNWXESjHe04HcEJ8JgCrqqpAOhK0CaIAeMfSf0nYJ5QksZ3I4ygMdI53QJ47WQAaMTYW22k5mVCwLcQLUCyJOLYeOcQZhoGdgPf/SFQl8Xtc10UcFhIa3XEcz/OqEBdAcZTmLY6ZirjY0ed37rlk+GJWycklykPXdSuF9SAI6LhNnufRuEmuSeBRFK5iPZSkGOPjWQAq1Sme+/pmJBBLMSiUKl2XLN2orgwOcTDLJacqEgsy8QKcBcx4e70eryNe2hgRjCo7hkOc/aTP73AiSqu/wH0ZjKkj3Sahm7jImiOVr86vIwBUHl18Igchz5xB4r6CMbQ8qZeWlnbs2LGwsFC+qngN4JHj98mduPI9YqsHcCHlEy9YEsyRB4HIEvJWtLVDhriDDKS9yKDACAD1fb/T6ciDC3EmImNsNf/UYmg2wWdmZhRFYYlMnF1P/NeRlE9M5kEHEIHaJ+P4j0anpqZGJpiju1ebWyfdKOM1EY9CGC0h0DMORGyxEQAahiHsGCTBUIhlJelMfOaM4Ufa7sU7XPOdubk57i2ORM/EZB5ATMdxSH9YtJSWZeXioOt06yQDyXuBmCOwZmtoTvm8Q+ZYfgSAwmsYTlGS4AJ85DmSgGNVqzAsPEfqFaiKBT3T0gLSqj+UKdCBkY/QrYwsLLAArNmQDamN3sQ+ESMAtN/vExUBS+YZ9oYLl4TlkLQnjhZDC89s3gdZ0BN5N2lOE61EeMO0GCJ5uxQvL5UtYLx78Tu0p3yLpHH6RO6MANBer6eq6t69e5GZMlcg20hLHL86jpNh8MyxocJVMe7twvU368HJycmJiQmOfWbPJQe7+vjhKRJggV1YubCwMDKCFD1SgW6ddDcKXANJwZOapll1VI4CPaztEd/34+9gtD4CQGHEJ5VBaBiG0AlIrkAEhlZtvlPbGirT0MTExOTkZJka6GfB47O8y2EZGncVi1u5s8dPYg8MSvpM+9qTmw26oGOO6Lpu23av14u/kxo0IpauIkAJwulCz5b41AgAJa8d2RaB5Nok0NpxnKaIwBIXh4Q3SSZOlr45jpPoAYzjFKkhF5M4Pz+fiwOFCivbQJX0RP4L3/fBVEEvAl8yaeVpeekZieqEc0n26EYAKHk40Ywub//4lm9EYGPZUuPxnYKaa8N5fKSxEXoFKyWygElXcXyh71dt7BxneElnGn2BeEg44+u6zt33twbiEPdi0zRJGKpcAVJHACgZQ3zZkZ9EXWBdjnQrFNU90i528orhQci4WC7yMmsZdSKZWvw8nvZIWjKPOCvAYsCU1grjfancOhn7nKsYouFBbCVJAKfE/hOfOiAmQkqXcS9mBVAZAszEKdKUDEVBEMBElGZ84sNZYXdmZ2dZknaMHHWBPMY4ZibWHIHLiDl94iPxm7msQUfGeYrX3/Q7NE6lBXCqdC8gqhM88W3bJnBJojrwci/OAaBp9nRiJ9uyrKYwdxCJSq774jibCwsL5XVHEHqyqIxIz5HMI3F/xsPZFYg7NzExsWXLFtIcy4W0bp0snedSBoiGYCKRCEwkdBMiJ5CAIyRyDQKO0H9JGVwAIukoDQi4R0fAqUidmwNAEe+LUQLFhegslTRCI08GAilegeySpIZVdYHU1omZOdLokJHMA87YOa4+AAAgAElEQVTvESFAAe3o7OxsgRcDu6VU2tBW5H0SuAsSVRoZCSwShCUXCEVKCtNQWzOV8gGonOJwoFIix1EzNVmaI0m95ZfesgynojK+70PokZdxyEjmEWc/i53fiw251+s1NwdMsSGvhqfyAaicTCjks81ana7rIiXRirSnm5mZKaM+AuNZ4KyTLROPR6IpcH4vAwqtTVsZ6sn5bG4AhYBJwm3fuAxFhBVdeVLRsbGxYq5HSC1pGEZexjMMw+zsAHH2Eyf6Ag0V3smNc+ssPNLV82BuAA3DEKJZ2WgE8UJEwiVbJ+P9gfzBNM2miCDiQ4jfmZ+fz6unDoIA+XVzSTxJ09miz0TpZxn/ulwJ5kgns5PWkWLtRYMoUARAAVUSbnhwx3XyFFxmGvm/VFW1bVtC1p7LGDMqIenPygw/+/yRyH5C55vRsYyfpqamxsfHMwqk/VRAZ5VWVXtfBgoUAVBIQuU0HkJC1ybCEGHBut1uE/tfYDUT6DRNs8xrb2Tolrj0U5RdEdKiFKBV+4icFCgIoHLahILEI7eTnDOBXvm+D6PfJsLo/Pz8+Pg4S8x5GjpLWiNAHZfxyom7HsGyPdFNvuq1IacdS9WjXsH1FwTQtCjfklDKNE3J491lE4oECbdtW0JRSVrnZ2ZmxsbGlpaW0gqEYRgEAZwyy+crBw5mq7ZhJhzHaIG+lQKbzpiX9qdiFCgOoGlLs1g/+D7FkqORb4tV1IZDvaqqlmU1RVOfgZ54K0DUG0e0AgSEFWc2ZRJDx3Ix/5yZmZmamirQ7eqCNxfoTPtISQoUB9AwDGF2V7IHFT0OtWxaGNSKGq2iWjr5V7fbbRBDCmpU1H+AYLbRRVryAi7mRAUCgxKCqKrauHmsYm2vgDpLAWgYhoZhFLM7qYF2LHushm7waqLX69m2jTiMsiX/siwrwnsiCq9lWVVw0Iwzm5g+i5f6KD5k9olu3TrZaSV5ybIAmhG4QYaRM+40GbrK2AcamPD2koGXGR8fR3wN5IEguFkF0EN2NNIIBKZLceVSt9sVLh9v3ToZV7v8xcoCKEyahK/IDEKvPAzFYOOJFjzPEwKmrut+8YtfnJ2d1XVd07RKM5ExSrczQsxEwtllrJxKf8rWfVXadFs5RwpwANCMxcqxo2WqWqkYSmhCJ1pAbHBoup977jlShuMFIui4rmvbNqI94rDMRTWU0U9G9ERshMSXeiQZZ0ZbLD+xpPdYGH7itXGRw8arbe/UTAEOABqGofwZilY8hpJ14/u+53mO4zz44IO33nqrpmmmacLrxvM8BFUkhUdeoHw8MC3qRBixkZVwKYAZHHlyD8MwQ6wUt6gv07eJiYmR/kgzMzPT09PxVlq3zjhNmniHD4CmZd+WiiLYgStAL89I1a1bt/6n//SfgiDo9/uu60L2RwedVYcfwzBImMWMXxF7sd/v01ICy7Kmp6cj6iPG7uUqxo6eGU7xuZLHsXTvTceBubm57JKXXHLJOeeck1imdetMJEuzbnIDULhYVH2IK0ncXDkdS7Yl9nHLspThZ2RYOTrQd17+dHJyUlGUvHFD8lIm1+khLRMn3vHZZk95Ozay/Pz8PGYh0TurdescSUD5C3ADULiF6Loe13tKRQX2rOJSdTtvZ6amprB1t27dmvdZ9vJLS0sjAZq9tsSSudKaZhze8VPNi/MLX/jCW4efL3zhC/HRtW6dcZo07g5PAEWku0ThvVR0GQwGOKvWvJ1qI4JlWaeeeioAVFGURPants6UaQh+7ozHGigz03jMRJvQMn3Ds5ZlpTHg5BCAiUjcF61bZ/kpEFsDZwDNXsRihxppHdEnywQBilQo21fsW9l6xd4fqPjZJygjmUd17OfE8JMxqOxZaN06M0jXiJ84AyjRgbKve4FkAoOTxrMI7BiXprO3bskmJiYmEpXLJavF4xCzGIbBfkTITuZREfsZhmGakp3QIXsWeLlFkebai5opwB9AEaipKRmKwJusSNV89tYts84syxobG6sIQDEjLOZKZAjQMqWd9KtjP0kHMi5GzkLr1plBPfl/qgRA4SOfaw8IpFQQBMbwQxvoCOwPr6ZHbt0yDS0NP2VqSHwW9v+5zgRgVzMy0ImVM46chdatM3ElNOVmVQDaIGEopspxHE3TsmOjNWVS0c+RW1eq4RDNXl7hT4bok1iGCBwpyyy0bp0CJ6hk01UBaLOEoSAi8rs5jsMueitJ/UofZ9m6eTuwtLSUqE3OW0+kPChfICdStugzMZdcpOnyX3fs2JGRgpRlFlq3zvKzIKqGCgGUBAxtEB6BD5Ik3kTJNcGydfM2MT09zddyfjAYFOb9IdzM4Fi73W4NeTsmJyd37NiRRkmWWWjdOtOoJ//9agEUsZqaolAiswXtfNNZUZatS4bMeDEzM5MBFoyVkGLwrSyW0nmkexKESGmaJdKHqi8YZ6F166x6Iiqqv3IAbZZCiVA5CALTNBvNijJuXTLkOi8Gg0HJLPCGYWQojuRJHMs4C8StczAYrCRBfJ2LSkhbdQAo4jtkL3chgx/ZKJIkW5bVRAU949YdSQTuBQhVC8t2srPAE/m7DLPGOAvErdNxHOFcM/cZX8EV1gGgYRiOPHBJS2LCK1X6Aji4/4Xv3rV9w9pjTvjo1+d+fP/t27dsGDt74y33PvrwPTu3ve/0Y8Y27nzUOJiPSIxbl7HS2dnZ8uqjfr9fnq9nSVs9kj9lHDVjsenp6bQEc2mzcGTGr7znice/fusnP3Teu3/r92+8+++//qX/fvV4sRln7G1bjCMFagJQYKiqqg19u5KdX9Xx6oDVMT3rO9cec+zlt/2fPXsPvLH4yI1nKBtumnlp/0HnZ3ddcYxy5XTnwKGJP7DwyF985vpbbtx2wYar7n5mfwqwpm3dAqsHbt2Tk5MFnsUjyDCqaVrJ9xALetaf6zAjMGjqLFAz/uf3PfGvr7y0Z3r76cq52+95ImHGwzA8sPj0rk9fsHP34UVQeCraB3lSoD4AZcnizXNkFdSFNDtcEpon9u7A7p1r1x7eIp3pzYdBc/n+4evlnfTApz/2wGsHw/Dg4gMfPf7Su198I7G21K2bWHrUzcIc6GAw6Ha7yGZc+MyO3uHsn6F2D8NQiO4ogzfPngUy48vpAufuvEjZdOfcK8toedSMh+HglUf+1513fPI/k9Uxarra32uiQK0AugIwFI6qCPPOm5seOI98+liyRVIBtDd/1yXvuv5RZ3mFvDq9+fTN068mLpbsrZv4CN+bgE5kSSovjmRBT8QDk8oFLnMWjppx+2d3X6Rs+t/PvJYAoMsTc6AzfSVZHXxnqq2tMAXqBtCVgaEEGrhyo8s7RDm8RQ6+dPf4Ya5zyI9ccte8bTz9+DN7j5zhDloPbz/lirtf8BKnP3PrJj7B7SZ3+jCiJwzyS/K53KgwrChzFqIzvl65/CtPL78Ok2a8BVC+M8OnNgEAChOTFeC+RsNELvftlKkLjAc+PvaHX5sPln8Pnr79ty+4fff+wfKx9JV7rzhhjbJ2fPtXf2gcgMjz4IHO92+/5k/ufnZfigg0zNy6KV2I3Z6bm5uYmMg4okaeILJO27Z5ceiIqZx9cieH96qE1JFxxr7OzMwkxpbOnIWEGf/OC6rv+0kz3gJojOgS3BADoCsGQ7FvIRvVdd113VrYn2D/s3/3uc/fP78/COZ3ffG7exMXUubWTXwi4eaOHTvGxsZYsh71+32kg7dtu/yBnXSFPSJ9tlM8qbCii7TAoHlnId2tswXQiqauVLXCAHQlYShmoNfrmaapaZpt2yPZpRKTdsB4dMfvrMHGVBRl/I491R7hs9nPwWAArbeu691ul+/7gx09hR/e54ef+LTmBdBkt87BK4/85S3Xbz7jmA3bbt75zaeH55J4W+2d+ikgEkBXHoYuH72DAM7dYEg58mJ5F0ferZu3/l6vB5bTsqwqDs6Qe7LUDM07S8m8YyxfvsAstG6d5cleWw2CARQBR1aAPDQ+YTS+eJ7HlzWLNxe/U2Dr0pWkMZ69Xg9emJW+IRi1Ruiw2MM7TbT4dYFZIG6d8draO7JRQDyAEr08L52DVCQeDAbIe6OqqmmaruvWxpMW2LqEdEtLS2NjY8S7Bg7aBDcdx6lSRhEimAtjEyMj2pFBVX2xsLAQf+sUmAXi1ll1h9v6y1NACgAFhqqqykOXXZ4mldRAkFTTNF3XHcfp9XqVsqUFti4ZuWVZ4+Pje/bscV3XNE1VVeEcyQhqpJ4CF7mS/WUn8yjQeplHtmzZEg8MWmwWxEbRL0OE1fasLABKAkC4rrvi56Df7zuOYxgGgAlgyp0zLbZ1+/1+t9u1LAtAb9t2bfIHhB1gzyU3MplHzQsp0ZKp2Cy02TprnrvCzUkEoCTmiFSeJIUpy/IgjsaI+6uqKhycut1ur9crz+uxbN0gCICY8DEHoAM0uQN6NkGAhqZpsnPltm3XEC85u9sjf2WZhXglbbbOOE3kvCMXgMKsEine2DeSnJQt0Cvf9z3PA57quq6qqq7rpmk6jtPtdj3P6w8/jDXTWxdACawEg4mDOSSztm27rgsZ9MLCwvz8PGMTvIrhJJ7rxQktk/yLhJ6FXORqs3XmIpeowtIBKDDUtm1d18tzYaLIyqtdIGZ3+DGHHxz81cMf3Ez8i62LguBtI1iciD4TExOKosSVIbxGFK8HUJhLdCOV6DM+IvpOYQBts3XSZJT2WkYABbGgil3BaqXya2IwGABhE/8W27rz8/OJLonle5tYA2xmcxlgID53LsBNbLqKm1u2bImkPCk2C+jbijTvq4LsAuuUF0CJWslxhoGHBBKpmU2X2bo1jJjkMc4rbDVNM9dhv4axkCZ27NhBbL9ws8wspLt1kgbbC8EUkBpA4dhjDD95t5lgukrQfJmtW3X3kVCzQB5jloDKVXc+V/1lZiHZrTNX823hiikgO4Bi+IUz31ZMPamrz7t1d+zYMTc3V8OQut2upmkFhDOQljbrVZp3FiL0b906IwSR7WszADQMQ0SLKMCzyEbx2vqTa+vOzc0pilK19DMIApwnCqgH+/2+qi6HequNgFwayjUL8RZbt844TaS60xgAhXa+fEoyqahfaWfybt2FhYVK+wOtYDGJdoOSEk5MTExPTxNK5p0F8iAuWrfOCEFk+9okAAXtyD5MtMKRjb4C+1Ny63LseRAEZd58CLYkp9o9TqVIYNDys9C6dcaJLM+d5gEoNEtlNqQ81K+0J4xblyVYcpl+lnzhwUNJWrX7SMowzkJGPZ7nye9wldH/lf1TIwEUU4Kd2UpF0xYo49admpoaHx+vAkZ93y/5nms6eoYhh8QqrVtn2gqX4X6DARRSUYS9KKDSlYH6MvRhx44d8RhCJTuGbFGqqpaMUd84o6WSdEt7vHXrTKOM8PvNBlCQr9/vw2c8l0OLcNKv1A4gQ5RpmiXtjZqLntPT03wNwnq9nq7rK3XBNHpcKwFAMQGwLuSb0azRU1t/5/v9Ps7s5bNrNBc9wzBMDAxacjpat86SBKzo8ZUDoCQKiaZpJU+OFdFatmpnZ2d5iT5JNmMulG80eoZhuDD88J3u1q2TLz151baiABREge6iKTAKVU8T/4LagE5VVXlp84SgZxPpz6gk5IUUbT2JFEgG0OZajZBBkuOk5Pql5m7dIAi4i02EoCfRlTdxLsiCby+EUCAZQA3DWAEYinhOyNXO5WhZxQxh037vT9/boH/oM7jOkpoimqSi0JMAKMcp+Ns/Ovsb176HY4XxqjALNAHb6/opkAygsL+zLGtlePuAG5XzUN9cAOUInWEYCkTPKgD0rHW/vOXcE+Kox/FOC6D1w2W8xWQAhUIGcR9WBoaCG7VtG3yTPDEp6gfQyQ/91o3/7d1ldjLfrYu3NXsuufgiLn+H+yxMfui3Jj/0W2WIPPJZvrNQnoars4ZUAAU5xPIFVUxJEAQIjmeapgziUe5bd+TGW3fcvz1r3S+PLJZRgOPWleSsU/8sZJCX8SeOs1DFRlsldY4AUJytVp4NGrK0G4ahaZrjOHxPo7mWTv1b91uf+t2S4jleW9f3fUmk7fXPAiNKZhTjNQu5lmtbOEKB0QAahiG8zlekn4/v+7Zta5pmGIbruvXLK1bt1kWEumLR7SKLuPzXimbhW5/63QwELPlTC6Dl5718DUwAGoah53mqqspw5i0/5sQaPM+zLEtVVcuyPM+rDUkr2rolN2f24+W3rmzLqYpZWHfcv/2jDSdmU7LMr+VnIXEjtDdzUYAVQMMwlIplyDVI9sI42hMkdV236tN9FVs3cVt+61O/u+64f/v/t3f9r1GcaXz+gAXJDy2IPVBCyhYU21p/qBEvYtNShKYiYbWFoIcQA7XqFb8cF79Uowdu6RnzQw5KuEbONpRbejQcxqu2V7vYQj1caeTY9rSadHfHcabbnezsdDYz+153HzNusl8zM+/szOwzyDj7zrzP+7yf530+eWfe93nf9/rWlb27qESTrguzRx31QkPDCoe3rDI5WFfdKCatUL9T4JNVEFgEgepbvPE8b1sHrYrqVG8VMynHcalUipLD03Ddso73Xt86/7IllrxUGnZdTdMEQeA4zjmzIKAV2WaFsqYxlmjYClQdp9mEL45A9RXkHOgD9Cwny3IqleI4LhaL8TwviqKFZNo8rgtDRs7869s8VqDnJs0pedEECjAZ3ljR1SirqipJUjKZZFkWyDSVSsmybOY1v0lcF/YEdMiQUWkjbBIrlFYcU0wiYJBAYV46zAEyqYFLs2uaJsuyKIoQKqrzaTqdVhSl/k8cNrjuR2/91pI3d/1NE3Su33DO35WakhW2ta84vGWVjpu1F4u1Qv32wifrR8A4geqfRDmOM9MFq19XJz+pqqqiKLAJLc/zscLBFw6xcMiyrBSOBbWg5LrFvrr52Sf8y5YUp5i8rt91YTs557cQSlbY/OwT9AI667fCgiaHPy1EwBSBgh7Qv/DwDCdjcGuapigK9FKho8rzPHxIBXpNJBI8z1Ny3WKKPLHt6WDPmuIUk9d1uq7+2l5/f9wY1OZz2WAFk5iXZq/TCubBQQlVELCAQPXXeYOLj+TI1E0yNVNQMkcSCZKroq+HbkGn1ZOuq2masdd2QKP6mUYT8KQVaACFMhcgYA2B6qPzLMsudoR6cpj4GMLAvzYyMtksBAqWoOS6J7Y93e5/HOZyT/S/UNp/MZMCOi9oSfrPbDYLW1QZ+LBTnTqrl6srYOCCkhUOb1nlX7bEv2wJjS+hoLMBkA3gg1kqIWAZgUIBi90EPCeQC/8ks4TkZshIX9OxJ42F1D5/+6UT254uZiLL42GqEBlMz0in05UaXPV0kNxR4ahSbnWxNe+CZDN/VErzHt6yCsTC2XIOBbGGoa6JCT5QDwIWEyiMLC16N/BZcvk0+WuT9T3BPDRct93/eLHrMgxT6t5mUkD4guYF0zxNThAGyTp/trW1rVixQv9ZttwFahj7CZLNYFKa179sCYiFs7XjeJ+//RKIxd06jVncqlzWEyhotqArmslUVjhHvnmHHP9i7s19liQNdl8qF+HgOzRc12YC1b94iqJoEmlAQ2fMxx57jGGYDRs2QArcNVlE2ew0rAAyi8+lJGsmBSR7b6W0sgZybCItAoWuqCAIiURCluVTpyogkCOTI2TdXnLtOrl+ndz6lnx4mIxEKzzsxWQarrvg5XFb+wozjlqaF3QGayiKYviLZ6k9QbJOoM8999zy5cvb29vdSKBvbn4KqgNnSh9SUoWjFElMsQcBigQKFZBl+e7d+wxD7t7VSqsUnyCBbtLTQzpaC+NIPrL7QyKXPufdFPCuUpIymaJz6Lb2FZQGkVRVhT+QFs5gK2acStc02gINK0z0v6Bz6Jubn6JkBVjihwYmKLMeBKgTKCHk4sXcr4Psx49nSnd2SyfzI0jNfNBwXZPkWzM76AxxaNbO8axEmsXpNFqLe61ACGFZVpabqtdBowkYlGkHgW7alO9d+v3kxx8FlmUt7LAYrLSTsrnXdZ22opIZq7rXCrDeuTf20DVjwUblpU6g0ejcHE+GhEJElmWWZTmOW+x00UYBRLtcV7subXAIIYIgrF279tKlS1TLcrUVVFWNxWLWvgpQRdtLwqkTaDic502YJ697AYzR8zzvpV6MsWbhatc1VuXF5urq6kICLf2uAi0HwHTIDomLtawHnqdOoIAREGgxXpqmwaTrZDLZzNEUSKDFraJR1263giRJPM83Cr1mLrdhBAqgwxRC2Ku9OWnU7a7rDedxuxU0TYvFYs3pQY1tgQ0mUKi8qqrJZLI5adTtrtvY5mtV6R6wQjKZxLBOq9pD/XIcQaCgrv5Sz/N88wwxecB1629thp8cHR3t6uoynL1mRg9YAYZna9YUH7AWAQcRKFQMaBRG6pthwpMHXNfaFllWWigUQgJdMI4ELacYLgzrLEbDnmvHEahebUmSOI5LJBKiKHr44w4SqG7xBl54wwoY1ml/E3IugQIWiqLA51FBEDwZbuEN17W/4VpbojesgGGd1raKeqQ5nUChDqqqiqLIFg6PdUi94br1NDUnP+MZK2BYp83NzB0EqoOid0hh5rAHoi8847q6jShdCIJw4MCBGzdu0JDvGSuk02kM66TRQirJdBmBQjU0TZMkSRCEWCz2q19JkuReJvWM61ZqYValZzIZhmFCoZBVAovleMYKGNZZbFYbrl1JoDouqqqm02nY6hKY1HXDTZ5xXd0o9C4EQaAk3EtWwLBOSo2krFh3E6hepeI+Kcdxoii6JcreS66rm8N1F16yAoZ12tn8PEKgxZDJspxMJlmWTSQSgiCk02knkym4rhvPxZi7/dqN+IPOpchjWGcpJvRSPEigOljwgg+rputk6rQYJy+5ro48vYtwODw6Omq5fI9ZAcM6LW8hlQR6mUCL65zNZmGAkmXZWCzG83wqlZIkycmdU13/bDYrSVIqleJ5PhaLsSwLHuIK5fVaWHIxNDTEMDY1WksUbogQDOu0DXab2mLpcna21bC0IE3TFEURRVEQ8ivkx2IxjuMEQRBFUZblhndRFUWRZRnUg/ExlmVBPUVR3DvfoNQQBlKEwmEgY7NlwbBOeyzejARaiqyiKJIkiaLI8zxwViKR4AuHWDiAWC3kVqVwAFECV/I8n0gkgM15nhdFUZIkC0ssrTWmeBgBDOu0x7guIdBq+8oXAZX7mXx8nLT6yMaTJP4LISqZfJ/87gLJ5ooequtSVVWdVYFYdW6NFQ7YyxdIts4z9HYhO8dxxQQNXOm6OVh1QYkPNQIBDOu0B3WXEOj+/eTdd8n0dC1QFJKUyOw9sm8d2f0RuXGeHPuYzKi1chm5n81moRdZ/7kJP1kaQbZWnkwmMzo6Sm9OaK3yXXMfwzptMJW9BAqfQs2ct28nly6RmhOq718k/hayb5zMLrrvaQPoWIQZBKanpxmGob1LkhkNHZIXwzptMITbCPTJJ8nQEAmHq0Kjksm/kcCLxH+I3G/ybeer4uTam+FwOFPnVx3X1tG84hjWaR7DmhJsItCaetR4YM8esmlTvu9Z221yJP4v8vsPiXSb7F5LdrxP4lFy6SbBnmgNiPG2BxHAsE7aRnUJgUaj9QKR48ixt0hUIqTApBuXk1eOk+jP9WbH5zyGQC5157OR/kBX4MDJYPDkgUBXoH/kszupJvl7imGdtJuzSwiUNgwo320I3CgcNbSenb5yaqu/++y1/JQMOH6JXzvb7d966sp0zY87ufgnfW0tbX2fxGvTbTY+vr+NWdM3PlX72TlVbPgfwzppg4wEShthlE8FgV27dtXYJSmXjJzr9rX0jt2T52sg3xvrbfF1n4skq5OdBwiUEIJhnfOtb/EvJFCLAUVx9iAQjUbD1cYSc9noSJfPt3LgmlSqkHRtYKXP1zUSXfwE4VJhDk/BsE6qBkICpQovCm8UAsmvBjoY5vkjV8suISpcPfI8w3QMfJU0pV9uZurmf25OzVTvyZoqworMGNZpBYrlZSCBlscFU92NgBoZfMbHMDvHprLlKpKdGtvJML5nBiOq+u3w+pb8akytpy9HPjjc272hZcO+T36YFSb2FpKZnlD8oYjcbDw8vDuwo//0wN7XAv1/GjgcfP9sr9//x79/AM+29oSmCCHqreH1hfWdWoNf3rsyuO/gyeDAnlc27j0/+XNDqBbDOsu1AWvSkECtwRGl2I9AJpOpuEUSN97rYximNxQvO1Y0Gw/1Mgzj6x3n8noX+LRl9boD//jx/qcH21raDl7+iRCS+2EssPwRgWaj57f7H34TyN0Z2+5fe/TfP2Xj17/8biZHclNjAeYhgeZF5r4/3/WbpS/3nPj4TkGDmcjgZmb98C0qYXE1sMewzhoAmbiNBGoCPMzaUATC4TDDMOU5NB7qyfcBaxDoHDkCn8L7vjoz9f3Uw/DfqVBP69wzRIuOvPiIImeuBzuYpX+4ktIeYpAvsYhASSHv6uD1X6DTCUVU0oc6jhjWSQliJFBKwKJY6ghkMpmhoaHpsiskPHyF7x6JLhiCB62kW8NdD1/h8wnAbqXv+6YJ9NHrf4MJFMM6KTVHJFBKwKLYxiLw4MrBNQyzeu8EW04PdmLvaoZZf+QqX7hbid3mESjJTY33rV159Iv8LPzZ6PnA6s7g149m5JftgTqGQDGss1wzsCANCdQCEFGE8xDISZFznT5m6b4JoWTgJidM7FvK+DrPRaTq79fzCZSkIuf2796zq7f/9Mndr+88e+l28UJfziZQQgiGddJopUigNFBFmQ5AICd8E+zy+QLDkzPztZmZHA745k2kr68HqkYGt49E5755zpdJiOMJFMM6F5rMit9IoFagiDKcicDs9OWjL7dsPDZ+e+5VO5e6PX5sY8vLRy8Xh3LWSaDfDnf0DH769XU4og/mDfA7nkAxrJNGI0UCpYEqynQMArCYSHdnZ2//mTP9vZ2d3QsWEyR68W0AAAJHSURBVFGjY2/0dHe0MczSNZtf63ljLFqYaVRI3trR6mNaO7p3/PnqTyohqcjgq/nJUfrhWxsIXonPZqJjh3q6O1oZX2vH1h3Bqw/yIufy9hwa+++NoiJenyuhARBhWKfloCOBWg4pCvQkAtLtsTc6912IcHPrksw+iF69cGjjylfPf1fptd5pQGBYp+UWQQK1HFIU6EUE8vOiNgx8tWBdxMK7/6OhdhdUHMM6rTUSEqi1eKI0ryKQigxuff7QxXjRJjG5mchfAhudtoRddQOkUqlk0twKANULaLK7SKBNZnCsrmEEZu9HQu/0BXYeGDgTDAbPHOkL9BwZ+ex/Tl9KZH59MaxzPh5mfyGBmkUQ8yMC7kIAwzottBcSqIVgoihEwAUIpNNp3BTaKjshgVqFJMpBBNyBAIZ1WmgnJFALwURRiIA7EMCwTqvshARqFZIoBxFwDQKSJHFcYSlU16jsUEWRQB1qGFQLEaCHgKZpiURCVRuxvDO9WjVCMhJoI1DHMhGBRiOQTCZFUWy0Fq4vHwnU9SbECiACBhDAsE4DoJVmQQItxQRTEIGmQIBl2Wy27KZ7TVF9SyqJBGoJjCgEEXAfAhjWad5mSKDmMUQJiIArEcCwTvNmQwI1jyFKQATcigDHcbJcdt89t9bIZr2RQG0GHItDBBAB7yCABOodW2JNEAFEwGYEkEBtBhyLQwQQAe8ggATqHVtiTRABRMBmBJBAbQYci0MEEAHvIIAE6h1bYk0QAUTAZgSQQG0GHItDBBAB7yDwf3idCP5V0T9yAAAAAElFTkSuQmCC)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5_Vl7TgSBxRV" - }, - "source": [ - "The system consists of one levitating disk magnet that is free to rotate and move in space given the force it feels from two permanent/electromagnets placed below it. Our goal is to use the sensor measurements of the magnetic field in the origin to control the current in the electromagnets so that the levitating magnet actually levitates.\n", - "\n", - "Given a state vector \n", - "\n", - "$$\n", - "\\zeta = [x, z, \\theta, \\dot{x}, \\dot{z}, \\dot{\\theta}]^\\top,\n", - "$$\n", - "\n", - "where:\n", - "- $(x,z)$ is the **position** of the levitating magnet,\n", - "- $(\\dot{x},\\dot{z})$ is the **velocity** of the levitating magnet,\n", - "- $\\theta$ is the **angle** of the magnet w.r.t. the plane (CW),\n", - "- $\\dot{\\theta}$ is the **angular velocity** of the magnet, \n", - "\n", - "this system can be described by the following ordinary differential equations:\n", - "\n", - "$$\n", - "\\begin{aligned}\n", - "\\begin{bmatrix}\n", - "\\ddot{x}\\\\\n", - "\\ddot{z}\n", - "\\end{bmatrix}\n", - "&= \\frac{1}{M}\\sum_{i=1}^{n_u} \\mathbf{F}_{i} + \\mathbf{g},\\\\\n", - "%\n", - "\\ddot{\\theta} &= \\frac{1}{J}\\sum_{i=1}^{n_u}\\tau_{i},\n", - "\\end{aligned}\n", - "$$\n", - "\n", - "where\n", - "\n", - "$$\n", - "\\begin{aligned}\n", - "\\mathbf{F}_{i} &= \\frac{3 \\mu_0}{4 \\pi d_i^5}\\Biggl[\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right) \\mathbf{m}+\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right) \\mathbf{m}_i+\\left(\\mathbf{m}_i \\cdot \\mathbf{m}\\right) \\mathbf{d}_i-\\frac{5\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right)}{d_i^2} \\mathbf{d}_i\\Biggr],\\\\\n", - "%\n", - "\\tau_{i} &= \\frac{\\mu_0}{4 \\pi d_i^3} \\left[\\mathbf{m} \\times\\left(\\frac{3\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\mathbf{d}_i}{d_i^2}-\\mathbf{m}_i\\right)\\right].\n", - "\\end{aligned}\n", - "$$\n", - "\n", - "Here, we define the 2D cross product as\n", - "\n", - "$$\n", - "\\mathbf{a} \\times \\mathbf{b} := a_1 b_2 - a_2 b_1,\n", - "$$\n", - "\n", - "and\n", - "\n", - "$$\n", - "\\mathbf{m} := m\\begin{bmatrix}-\\sin \\theta \\\\ \\cos \\theta\\end{bmatrix}, \\quad \\mathbf{m}_i := \\begin{bmatrix}0 \\\\ m_i + kI_i\\end{bmatrix},\n", - "$$\n", - "\n", - "$$\n", - "\\mathbf{d}_i := \\mathbf{r} - \\mathbf{r}_i, \\quad d_i = \\|\\mathbf{d}_i\\|.\\quad \\quad \\quad\n", - "$$\n", - "\n", - "Here:\n", - "- $m$ is the **magnitude of the magnetic moment** of the levitating magnet,\n", - "- $m_i$ is the **magnitude of the magnetic moment** of the supporting magnets,\n", - "- $M$ is the **mass** of the levitating magnet,\n", - "- $J$ is the **inertia** of the levitating magnet,\n", - "- $\\mathbf{r}$ is the $(x,z)$ position of the levitating magnet,\n", - "- $\\mathbf{r}_i$ is the $(x,z)$ position of the supporting magnets\n", - "- $g$ is the **gravitational acceleration**,\n", - "- $\\mu_0$ is the **magnetic permeability of free space**\n", - "- $\\mathbf{F}_i$ and $\\mathbf{\\tau}$ are the **force and torque** from the i'th magnet acting on the levitating magnet,\n", - "- $I_i$ is the **current** in the i'th solenoid/magnet\n", - "\n", - "This system is naturally **unstable**, meaning that without control, the magnet will fall.\n", - "\n", - "A magnetic sensor is also placed in the center of the based of the system, and its measurements can be modeled as\n", - "\n", - "$$\n", - " \\mathbf{B}:= \\frac{\\mu_0}{4\\pi r^3}\\left[3\\frac{(\\mathbf{m}\\cdot\\mathbf{r})\\mathbf{r}}{r^2}-\\mathbf{m}\\right].\n", - "$$\n", - "\n", - "## Control Strategy\n", - "This system can be stabilized by a **Proportional-Derivative (PD) controller**.\n", - "Taking the measuremet in the x-direction, $y = B_x$, as output, and letting the currents be given by $I_1 = - I_2 = u$, where $u$ is our control input, we have a SISO system that ca be stabilized by defining\n", - "\n", - "$$\n", - "u := K_p y + K_d \\dot{y},\n", - "$$\n", - "\n", - "where:\n", - "- $K_p$ is a **proportional gain**, which counteracts deviations from the equilibrium point, and\n", - "- $K_d$ is a **derivative gain**, which damps oscillations by reacting to the change in position.\n", - "\n", - "By choosing appropriate values for $K_p$ and $K_d$, the controller ensures that the levitating magnet stays levitating.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "e2dxuZSuGdrU" - }, - "source": [ - "# Simulation Example\n", - "The following is an implementation of a simulation with a PD controller for an instance of the maglev system." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "thebe-remove-input-init", - "auto-execute-page" - ] - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4bc6bb094dc34d6ea11659887f711f0c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(FloatSlider(value=600.0, description='Kp', max=1000.0, step=10.0), FloatSlider(value=30.…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d9949e3c6a754e319a516b46b68aca50", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Button(description='Evaluate', style=ButtonStyle()), Output(), Output()))" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "%pip install ipysim\n", - "from ipysim.widgets import interactive_simulation\n", - "\n", - "def evaluation_check(sol, t):\n", - " z = sol[:, 1] # Extract the z (height) position\n", - " return 0.02 < z[-1] < 0.03\n", - "\n", - "# Run the interactive simulation with evaluation\n", - "interactive_simulation(\n", - " T=1.0,\n", - " Kp_default=200.0,\n", - " Kd_default=40.0,\n", - " evaluation_function=evaluation_check\n", - ")" - ] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.1" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/book/chapters/system_description.ipynb b/book/chapters/system_description.ipynb new file mode 100644 index 0000000..4fc5889 --- /dev/null +++ b/book/chapters/system_description.ipynb @@ -0,0 +1,352 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "tags": [ + "auto-execute-page", + "thebe-remove-input-init" + ] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[notice] A new release of pip is available: 23.2.1 -> 25.0.1\n", + "[notice] To update, run: python.exe -m pip install --upgrade pip\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: ipyquizjb in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (0.3.9.dev0)\n", + "Requirement already satisfied: ipython in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.32.0)\n", + "Requirement already satisfied: ipywidgets in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (8.1.5)\n", + "Requirement already satisfied: requests in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipyquizjb) (2.32.3)\n", + "Requirement already satisfied: colorama in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.4.6)\n", + "Requirement already satisfied: decorator in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.1.1)\n", + "Requirement already satisfied: jedi>=0.16 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.19.2)\n", + "Requirement already satisfied: matplotlib-inline in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.1.7)\n", + "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (3.0.50)\n", + "Requirement already satisfied: pygments>=2.4.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (2.19.1)\n", + "Requirement already satisfied: stack_data in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (0.6.3)\n", + "Requirement already satisfied: traitlets>=5.13.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipython->ipyquizjb) (5.14.3)\n", + "Requirement already satisfied: comm>=0.1.3 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (0.2.2)\n", + "Requirement already satisfied: widgetsnbextension~=4.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (4.0.13)\n", + "Requirement already satisfied: jupyterlab-widgets~=3.0.12 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from ipywidgets->ipyquizjb) (3.0.13)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.4.1)\n", + "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (3.10)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2.3.0)\n", + "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from requests->ipyquizjb) (2025.1.31)\n", + "Requirement already satisfied: parso<0.9.0,>=0.8.4 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from jedi>=0.16->ipython->ipyquizjb) (0.8.4)\n", + "Requirement already satisfied: wcwidth in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->ipyquizjb) (0.2.13)\n", + "Requirement already satisfied: executing>=1.2.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (2.2.0)\n", + "Requirement already satisfied: asttokens>=2.1.0 in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (3.0.0)\n", + "Requirement already satisfied: pure-eval in c:\\users\\jørgen galdal\\documents\\lokalskoleprogrammering\\cyberbook\\.venv\\lib\\site-packages (from stack_data->ipython->ipyquizjb) (0.2.3)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install ipyquizjb\n", + "from ipyquizjb.questions import display_questions, display_package" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# System Description\n", + "\n", + "The 2D model of Maggy that we will analyze is illustrated in the figure below." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```{figure} ../_static/2D_Maggy_Model.png\n", + "---\n", + "name: 2d_maggy\n", + "width: 70%\n", + "align: center\n", + "---\n", + "2D Model of Maggy\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The system consists of one levitating disk magnet that is free to rotate and move in space given the force it feels from two \"hybrid\" (a combination of permanent and electric) magnets placed below it.\n", + "\n", + "Our goal is to use the sensor measurements of the magnetic field in the origin to control the current in the electromagnets so that the levitating magnet actually levitates.\n", + "\n", + "Given a state vector \n", + "\n", + "$$\n", + "\\zeta = [x, z, \\theta, \\dot{x}, \\dot{z}, \\dot{\\theta}]^\\top,\n", + "$$\n", + "\n", + "where:\n", + "- $(x,z)$ is the **position** of the levitating magnet,\n", + "- $(\\dot{x},\\dot{z})$ is the **velocity** of the levitating magnet,\n", + "- $\\theta$ is the **angle** of the magnet w.r.t. the plane (CW),\n", + "- $\\dot{\\theta}$ is the **angular velocity** of the magnet, \n", + "\n", + "this system can be described by the following ordinary differential equations:\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "\\begin{bmatrix}\n", + "\\ddot{x}\\\\\n", + "\\ddot{z}\n", + "\\end{bmatrix}\n", + "&= \\frac{1}{M}\\sum_{i=1}^{n_u} \\mathbf{F}_{i} + \\mathbf{g},\\\\\n", + "%\n", + "\\ddot{\\theta} &= \\frac{1}{J}\\sum_{i=1}^{n_u}\\tau_{i},\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "where\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "\\mathbf{F}_{i} &= \\frac{3 \\mu_0}{4 \\pi d_i^5}\\Biggl[\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right) \\mathbf{m}+\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right) \\mathbf{m}_i+\\left(\\mathbf{m}_i \\cdot \\mathbf{m}\\right) \\mathbf{d}_i-\\frac{5\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right)}{d_i^2} \\mathbf{d}_i\\Biggr],\\\\\n", + "%\n", + "\\tau_{i} &= \\frac{\\mu_0}{4 \\pi d_i^3} \\left[\\mathbf{m} \\times\\left(\\frac{3\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\mathbf{d}_i}{d_i^2}-\\mathbf{m}_i\\right)\\right].\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "Here, we define the 2D cross product as\n", + "\n", + "$$\n", + "\\mathbf{a} \\times \\mathbf{b} := a_1 b_2 - a_2 b_1,\n", + "$$\n", + "\n", + "and\n", + "\n", + "$$\n", + "\\mathbf{m} := m\\begin{bmatrix}-\\sin \\theta \\\\ \\cos \\theta\\end{bmatrix}, \\quad \\mathbf{m}_i := \\begin{bmatrix}0 \\\\ m_i + kI_i\\end{bmatrix},\n", + "$$\n", + "\n", + "$$\n", + "\\mathbf{d}_i := \\mathbf{r} - \\mathbf{r}_i, \\quad d_i = \\|\\mathbf{d}_i\\|.\\quad \\quad \\quad\n", + "$$\n", + "\n", + "Here:\n", + "- $m$ is the **magnitude of the magnetic moment** of the levitating magnet,\n", + "- $m_i$ is the **magnitude of the magnetic moment** of the supporting magnets,\n", + "- $M$ is the **mass** of the levitating magnet,\n", + "- $J$ is the **inertia** of the levitating magnet,\n", + "- $\\mathbf{r}$ is the $(x,z)$ position of the levitating magnet,\n", + "- $\\mathbf{r}_i$ is the $(x,z)$ position of the supporting magnets\n", + "- $g$ is the **gravitational acceleration**,\n", + "- $\\mu_0$ is the **magnetic permeability of free space**\n", + "- $\\mathbf{F}_i$ and $\\mathbf{\\tau}$ are the **force and torque** from the i'th magnet acting on the levitating magnet,\n", + "- $I_i$ is the **current** in the i'th solenoid/magnet\n", + "- k is some gemoetrical constant determining relation between current and the magnetic field produced by the solenoids in the model.\n", + "\n", + "A magnetic sensor is also placed in the center of the based of the system, and its measurements can be modeled as\n", + "\n", + "$$\n", + " \\mathbf{B}:= \\frac{\\mu_0}{4\\pi r^3}\\left[3\\frac{(\\mathbf{m}\\cdot\\mathbf{r})\\mathbf{r}}{r^2}-\\mathbf{m}\\right].\n", + "$$\n", + "\n", + "In the following, we will use this model to analyze the magnetic leviation system and design controllers for it." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4a7209af585348548736b694566eb789", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Output(), Output()), _dom_classes=('ipyquizjb-render-math',))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display_package({\n", + " \"questions\": [\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What type of system is this magnetic levitation model?\",\n", + " \"answers\": [\n", + " \"Linear autonomous\",\n", + " \"Linear non-autonomous\",\n", + " \"Nonlinear autonomous\",\n", + " \"Nonlinear non-autonomous\"\n", + " ],\n", + " \"answer\": [\"Nonlinear non-autonomous\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which physical quantity does \\\\( J \\\\) represent in the system model?\",\n", + " \"answers\": [\n", + " \"Mass of the levitating magnet\",\n", + " \"Magnetic permeability of free space\",\n", + " \"Inertia of the levitating magnet\",\n", + " \"Current in the solenoids\"\n", + " ],\n", + " \"answer\": [\"Inertia of the levitating magnet\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"What is the direction of the magnetic moment \\\\( \\\\mathbf{m} \\\\) of the levitating magnet?\",\n", + " \"answers\": [\n", + " \"Always vertical\",\n", + " \"Depends on \\\\( \\\\theta \\\\), rotated in-plane\",\n", + " \"Opposite to \\\\( \\\\mathbf{m}_i \\\\)\",\n", + " \"Parallel to gravity\"\n", + " ],\n", + " \"answer\": [\"Depends on \\\\( \\\\theta \\\\), rotated in-plane\"],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"TEXT\",\n", + " \"body\": \"What is the physical significance of \\\\( \\\\mathbf{F}_i \\\\) in the model?\",\n", + " \"notes\": [\n", + " \"It is the force from the i'th supporting magnet acting on the levitating magnet.\"\n", + " ],\n", + " \"when\": \"retry\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Which of the following best describes the magnetic field \\\\( \\\\mathbf{B} \\\\) measured at the origin?\",\n", + " \"answers\": [\n", + " \"It is the total field from all magnets including supporting ones.\",\n", + " \"It is only affected by the electromagnets.\",\n", + " \"It results from the levitating magnet's dipole field.\",\n", + " \"It depends only on gravity and mass.\"\n", + " ],\n", + " \"answer\": [\"It results from the levitating magnet's dipole field\"],\n", + " \"when\": \"initial\"\n", + " },\n", + " {\n", + " \"type\": \"MULTIPLE_CHOICE\",\n", + " \"body\": \"Why does the model include a cross product \\\\( \\\\mathbf{m} \\\\times (...) \\\\) when computing torque?\",\n", + " \"answers\": [\n", + " \"Because torque is always perpendicular to force\",\n", + " \"Because torque results from the interaction of dipoles\",\n", + " \"Because the cross product determines angular velocity\",\n", + " \"To cancel out the gravitational effect\"\n", + " ],\n", + " \"answer\": [\"Because torque results from the interaction of dipoles\"],\n", + " \"when\": \"retry\"\n", + " }\n", + " ]\n", + "})" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/figures/logo-wide.svg b/book/figures/logo-wide.svg new file mode 100644 index 0000000..e29f7ed --- /dev/null +++ b/book/figures/logo-wide.svg @@ -0,0 +1 @@ +logo-wide diff --git a/book/intro.md b/book/intro.md index d5ec3d9..7ecadc5 100644 --- a/book/intro.md +++ b/book/intro.md @@ -1,5 +1,14 @@ # Maglev Example Assignment +Welcome to the Maglev Control System example assignment, hosted in this Jupyter book. -This is a test for example +This book uses interactive questions and simulations running in the browser through *Live code* and an in-browser Python kernel. +Note that *Live code* may take some time to start, depending on your computer, as it initializes the environment and imports the necessary Python packages. The more computation-heavy interactive animations will also take some time to load. + +```{Tip} +If live code doesn’t start automatically, you can click the icon in the top right corner to launch it manually. + +``` diff --git a/book/references.md b/book/references.md index 5fd6c7d..c08a1d4 100644 --- a/book/references.md +++ b/book/references.md @@ -1,3 +1,4 @@ # References :::{bibliography} ::: +Omega Bulletin. (2025). Magnetlab - Regtek [Logo]. Omega NTNU. https://omega.ntnu.no/ombul/144 \ No newline at end of file diff --git a/book/some_content/maglev_dynamical_system_simulation.ipynb b/book/some_content/maglev_dynamical_system_simulation.ipynb deleted file mode 100644 index 1844b33..0000000 --- a/book/some_content/maglev_dynamical_system_simulation.ipynb +++ /dev/null @@ -1,508 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "5VFc41Ojgoxe" - }, - "source": [ - "# System Description\n", - "In this example, we simulate a magnetic levitation system (in 2D), as illustrated in the figure." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "6wJKYwoqghR8" - }, - "source": [ - "![image.png](data:image/png;base64,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)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5_Vl7TgSBxRV" - }, - "source": [ - "The system consists of one levitating disk magnet that is free to rotate and move in space given the force it feels from two permanent/electromagnets placed below it. Our goal is to use the sensor measurements of the magnetic field in the origin to control the current in the electromagnets so that the levitating magnet actually levitates.\n", - "\n", - "Given a state vector \n", - "\n", - "$$\n", - "\\zeta = [x, z, \\theta, \\dot{x}, \\dot{z}, \\dot{\\theta}]^\\top,\n", - "$$\n", - "\n", - "where:\n", - "- $(x,z)$ is the **position** of the levitating magnet,\n", - "- $(\\dot{x},\\dot{z})$ is the **velocity** of the levitating magnet,\n", - "- $\\theta$ is the **angle** of the magnet w.r.t. the plane (CW),\n", - "- $\\dot{\\theta}$ is the **angular velocity** of the magnet, \n", - "\n", - "this system can be described by the following ordinary differential equations:\n", - "\n", - "$$\n", - "\\begin{aligned}\n", - "\\begin{bmatrix}\n", - "\\ddot{x}\\\\\n", - "\\ddot{z}\n", - "\\end{bmatrix}\n", - "&= \\frac{1}{M}\\sum_{i=1}^{n_u} \\mathbf{F}_{i} + \\mathbf{g},\\\\\n", - "%\n", - "\\ddot{\\theta} &= \\frac{1}{J}\\sum_{i=1}^{n_u}\\tau_{i},\n", - "\\end{aligned}\n", - "$$\n", - "\n", - "where\n", - "\n", - "$$\n", - "\\begin{aligned}\n", - "\\mathbf{F}_{i} &= \\frac{3 \\mu_0}{4 \\pi d_i^5}\\Biggl[\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right) \\mathbf{m}+\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right) \\mathbf{m}_i+\\left(\\mathbf{m}_i \\cdot \\mathbf{m}\\right) \\mathbf{d}_i-\\frac{5\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\left(\\mathbf{m} \\cdot \\mathbf{d}_i\\right)}{d_i^2} \\mathbf{d}_i\\Biggr],\\\\\n", - "%\n", - "\\tau_{i} &= \\frac{\\mu_0}{4 \\pi d_i^3} \\left[\\mathbf{m} \\times\\left(\\frac{3\\left(\\mathbf{m}_i \\cdot \\mathbf{d}_i\\right)\\mathbf{d}_i}{d_i^2}-\\mathbf{m}_i\\right)\\right].\n", - "\\end{aligned}\n", - "$$\n", - "\n", - "Here, we define the 2D cross product as\n", - "$$\n", - "\\mathbf{a} \\times \\mathbf{b} := a_1 b_2 - a_2 b_1,\n", - "$$\n", - "and\n", - "$$\n", - "\\mathbf{m} := m\\begin{bmatrix}-\\sin \\theta \\\\ \\cos \\theta\\end{bmatrix}, \\quad \\mathbf{m}_i := \\begin{bmatrix}0 \\\\ m_i + kI_i\\end{bmatrix},\n", - "$$\n", - "$$\n", - "\\mathbf{d}_i := \\mathbf{r} - \\mathbf{r}_i, \\quad d_i = \\|\\mathbf{d}_i\\|.\\quad \\quad \\quad\n", - "$$\n", - "\n", - "Here:\n", - "- $m$ is the **magnitude of the magnetic moment** of the levitating magnet,\n", - "- $m_i$ is the **magnitude of the magnetic moment** of the supporting magnets,\n", - "- $M$ is the **mass** of the levitating magnet,\n", - "- $J$ is the **inertia** of the levitating magnet,\n", - "- $\\mathbf{r}$ is the $(x,z)$ position of the levitating magnet,\n", - "- $\\mathbf{r}_i$ is the $(x,z)$ position of the supporting magnets\n", - "- $g$ is the **gravitational acceleration**,\n", - "- $\\mu_0$ is the **magnetic permeability of free space**\n", - "- $\\mathbf{F}_i$ and $\\mathbf{\\tau}$ are the **force and torque** from the i'th magnet acting on the levitating magnet,\n", - "- $I_i$ is the **current** in the i'th solenoid/magnet\n", - "\n", - "This system is naturally **unstable**, meaning that without control, the magnet will fall.\n", - "\n", - "A magnetic sensor is also placed in the center of the based of the system, and its measurements can be modeled as\n", - "$$\n", - " \\mathbf{B}:= \\frac{\\mu_0}{4\\pi r^3}\\left[3\\frac{(\\mathbf{m}\\cdot\\mathbf{r})\\mathbf{r}}{r^2}-\\mathbf{m}\\right].\n", - "$$\n", - "\n", - "## Control Strategy\n", - "This system can be stabilized by a **Proportional-Derivative (PD) controller**.\n", - "Taking the measuremet in the x-direction, $y = B_x$, as output, and letting the currents be given by $I_1 = - I_2 = u$, where $u$ is our control input, we have a SISO system that ca be stabilized by defining\n", - "\n", - "$$\n", - "u := K_p y + K_d \\dot{y},\n", - "$$\n", - "\n", - "where:\n", - "- $K_p$ is a **proportional gain**, which counteracts deviations from the equilibrium point, and\n", - "- $K_d$ is a **derivative gain**, which damps oscillations by reacting to the change in position.\n", - "\n", - "By choosing appropriate values for $K_p$ and $K_d$, the controller ensures that the levitating magnet stays levitating.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "e2dxuZSuGdrU" - }, - "source": [ - "# Simulation Example\n", - "The following is an implementation of a simulation with a PD controller for an instance of the maglev system." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "LQvXtNshIf3a" - }, - "source": [ - "### Imports & Function Definitions" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "id": "KVshwKaJIfOV" - }, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from scipy.integrate import odeint\n", - "\n", - "# Utilities\n", - "def cross2D(a, b):\n", - " return a[0]*b[1] - a[1]*b[0]\n", - "\n", - "# Magnetic field\n", - "def field(state, m, mu0):\n", - " x, z, theta = state[0], state[1], state[2]\n", - " r = np.array([x, z])\n", - " r_norm = np.linalg.norm(r)\n", - " m_vec = m*np.array([-np.sin(theta), np.cos(theta)])\n", - "\n", - " B = mu0/(4*np.pi*r_norm**3)*(3*np.dot(m_vec, r)/r_norm**2*r - m_vec)\n", - "\n", - " return B\n", - "\n", - "# Sensor Measurement Function (and its derivative)\n", - "def maglev_measurements(state, m, mu0, eps=1e-6):\n", - " \"\"\"\n", - " Compute the sensor output and its time derivative.\n", - " The measurement is the x–component of the magnetic field.\n", - " The derivative is approximated by finite differences with respect to [x, z, theta].\n", - " \"\"\"\n", - " y = field(state, m, mu0)[0]\n", - "\n", - " grad = np.zeros(3)\n", - " for i in range(3):\n", - " state_plus = state.copy()\n", - " state_minus = state.copy()\n", - " state_plus[i] += eps\n", - " state_minus[i] -= eps\n", - " y_plus = field(state_plus, m, mu0)[0]\n", - " y_minus = field(state_minus, m, mu0)[0]\n", - " grad[i] = (y_plus - y_minus)/(2*eps)\n", - "\n", - " state_dot = np.array([state[3], state[4], state[5]])\n", - " y_dot = np.dot(grad, state_dot)\n", - " return y, y_dot\n", - "\n", - "# Force & Torque\n", - "def force(m_i, m, r, mu0):\n", - " r_norm = np.linalg.norm(r)\n", - " term1 = np.dot(m_i, r)*m\n", - " term2 = np.dot(m, r)*m_i\n", - " term3 = np.dot(m_i, m)*r\n", - " term4 = 5*np.dot(m_i, r)*np.dot(m, r)/r_norm**2*r\n", - "\n", - " F_i = (3*mu0/(4*np.pi*r_norm**5))*(term1 + term2 + term3 - term4)\n", - "\n", - " return F_i\n", - "\n", - "def torque(m_i, m, r, mu0):\n", - " r_norm = np.linalg.norm(r)\n", - " r_hat = r/r_norm\n", - "\n", - " tau_i = (mu0/(4*np.pi*r_norm**3))*cross2D(m, 3*np.dot(m_i, r_hat)*r_hat - m_i)\n", - "\n", - " return tau_i\n", - "\n", - "# Plant\n", - "def maglev_state_dynamics(state, t, u, params):\n", - " # Unpack parameters\n", - " M = params[\"M\"]\n", - " m_val = params[\"m\"]\n", - " l = params[\"l\"]\n", - " g = params[\"g\"]\n", - " m_sup = params[\"m_support\"]\n", - " k = params[\"k\"]\n", - " J = params[\"J\"]\n", - " mu0 = params[\"mu0\"]\n", - "\n", - " x, z, theta, dx, dz, dtheta = state\n", - "\n", - " # Positions of permanent magnets\n", - " r1 = np.array([l/2, 0])\n", - " r2 = np.array([-l/2, 0])\n", - "\n", - " # Magnetic moments of permanent magnets with control input u\n", - " m1 = np.array([0, m_sup + k*u])\n", - " m2 = np.array([0, m_sup - k*u])\n", - "\n", - " # Magnetic moment of levitating magnet\n", - " m_lev = m_val*np.array([-np.sin(theta), np.cos(theta)])\n", - "\n", - " # Position of the levitating magnet\n", - " r = np.array([x, z])\n", - "\n", - " # Compute forces from permanent magnets\n", - " d1 = r - r1\n", - " d2 = r - r2\n", - " F1 = force(m1, m_lev, d1, mu0)\n", - " F2 = force(m2, m_lev, d2, mu0)\n", - "\n", - " # Total force (including gravity acting downward)\n", - " F_total = F1 + F2 + M*np.array([0, -g])\n", - " ddx, ddz = F_total/M\n", - "\n", - " ddz += -5*dz # Hack to introduce damping on z\n", - "\n", - " # Compute torques from permanent magnets\n", - " tau1 = torque(m1, m_lev, d1, mu0)\n", - " tau2 = torque(m2, m_lev, d2, mu0)\n", - " tau_total = tau1 + tau2\n", - " ddtheta = tau_total/J\n", - "\n", - " return [dx, dz, dtheta, ddx, ddz, ddtheta]\n", - "\n", - "# Closed-Loop Dynamics\n", - "def closed_loop_dynamics(state, t, params, Kp, Kd):\n", - " \"\"\"\n", - " Computes the overall state derivative with a continuous-time PD controller.\n", - "\n", - " The control input is computed continuously as:\n", - " u = -Kp * y - Kd * y_dot\n", - " and then fed into the plant dynamics.\n", - " \"\"\"\n", - " # Compute sensor measurement and its derivative\n", - " y, y_dot = maglev_measurements(state, params[\"m\"], params[\"mu0\"])\n", - " u = -Kp*y - Kd*y_dot\n", - "\n", - " # Compute the plant state derivative with control input u\n", - " return maglev_state_dynamics(state, t, u, params)\n", - "\n", - "# Simulation\n", - "def simulate_maglev(Kp, Kd, T, dt, state0):\n", - " t = np.arange(0, T, dt)\n", - " sol = odeint(closed_loop_dynamics, state0, t, args=(params, Kp, Kd))\n", - " return t, sol" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "EGe_3LGjIjGb" - }, - "source": [ - "### System Simulation" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 362 - }, - "id": "KzwiUI7ZI0jW", - "outputId": "860156d5-61c1-41c9-ae09-d4287f659cab" - }, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Physical system parameters\n", - "params = {\n", - " \"M\": 0.075, # mass of levitating magnet (kg)\n", - " \"m\": 9.375, # magnetic moment magnitude of levitating magnet (A·m²)\n", - " \"l\": 0.046, # distance between supporting magnets (m)\n", - " \"g\": 9.81, # gravitational acceleration (m/s²)\n", - " \"m_support\": 0.6250, # baseline magnetic moment of supporting magnets\n", - " \"k\": 0.0377, # scaling factor for current-to-moment conversion\n", - " \"J\": 0.12e-4, # moment of inertia (kg·m²) (simplified)\n", - " \"mu0\": 4*np.pi*1e-7 # magnetic permeability of free space (H/m)\n", - "}\n", - "\n", - "# Initial state: [x, z, theta, dx, dz, dtheta]\n", - "state0 = [0.004, 0.0243+0.02, -0.2, 0.0, 0.0, 0.0]\n", - "\n", - "# Control parameters\n", - "Kp, Kd = 600.0, 30.0\n", - "\n", - "# Simulation setup\n", - "T = 1 # Total simulation time\n", - "dt = 0.001 # Time step\n", - "\n", - "# Simulation\n", - "t, sol = simulate_maglev(Kp, Kd, T, dt, state0)\n", - "\n", - "# Extract control input for plotting\n", - "u_array = np.zeros(len(t))\n", - "for i, state in enumerate(sol):\n", - " y, y_dot = maglev_measurements(state, params[\"m\"], params[\"mu0\"])\n", - " u_array[i] = -Kp*y - Kd*y_dot\n", - "\n", - "# Plot results\n", - "plt.figure(figsize=(12, 5))\n", - "\n", - "plt.subplot(1, 2, 1)\n", - "plt.plot(t, sol[:, 1])\n", - "plt.plot(t, sol[:, 0])\n", - "plt.xlabel('Time [s]')\n", - "plt.ylabel('Position [m]')\n", - "plt.title('Position of levitating magnet (x,z)')\n", - "plt.grid(True)\n", - "\n", - "plt.subplot(1, 2, 2)\n", - "plt.plot(sol[:, 0], sol[:, 2])\n", - "plt.xlabel('x')\n", - "plt.ylabel('theta')\n", - "plt.title('Phase plot of x vs theta')\n", - "plt.grid(True)\n", - "\n", - "plt.tight_layout()\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting ipysim==0.0.12\n", - " Downloading ipysim-0.0.12-py3-none-any.whl.metadata (639 bytes)\n", - "Requirement already satisfied: ipython in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (9.0.2)\n", - "Requirement already satisfied: ipywidgets in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (8.1.5)\n", - "Requirement already satisfied: jupyter-bokeh in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (4.0.5)\n", - "Requirement already satisfied: matplotlib in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (3.10.1)\n", - "Requirement already satisfied: numpy in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (2.2.4)\n", - "Requirement already satisfied: requests in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (2.32.3)\n", - "Requirement already satisfied: scipy in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipysim==0.0.12) (1.15.2)\n", - "Requirement already satisfied: decorator in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (5.2.1)\n", - "Requirement already satisfied: ipython-pygments-lexers in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (1.1.1)\n", - "Requirement already satisfied: jedi>=0.16 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (0.19.2)\n", - "Requirement already satisfied: matplotlib-inline in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (0.1.7)\n", - "Requirement already satisfied: pexpect>4.3 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (4.9.0)\n", - "Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (3.0.50)\n", - "Requirement already satisfied: pygments>=2.4.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (2.19.1)\n", - "Requirement already satisfied: stack_data in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (0.6.3)\n", - "Requirement already satisfied: traitlets>=5.13.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipython->ipysim==0.0.12) (5.14.3)\n", - "Requirement already satisfied: comm>=0.1.3 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipywidgets->ipysim==0.0.12) (0.2.2)\n", - "Requirement already satisfied: widgetsnbextension~=4.0.12 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipywidgets->ipysim==0.0.12) (4.0.13)\n", - "Requirement already satisfied: jupyterlab-widgets~=3.0.12 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from ipywidgets->ipysim==0.0.12) (3.0.13)\n", - "Requirement already satisfied: bokeh==3.* in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from jupyter-bokeh->ipysim==0.0.12) (3.7.0)\n", - "Requirement already satisfied: Jinja2>=2.9 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (3.1.6)\n", - "Requirement already satisfied: contourpy>=1.2 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (1.3.1)\n", - "Requirement already satisfied: narwhals>=1.13 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (1.31.0)\n", - "Requirement already satisfied: packaging>=16.8 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (24.2)\n", - "Requirement already satisfied: pandas>=1.2 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (2.2.3)\n", - "Requirement already satisfied: pillow>=7.1.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (11.1.0)\n", - "Requirement already satisfied: PyYAML>=3.10 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (6.0.2)\n", - "Requirement already satisfied: tornado>=6.2 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (6.4.2)\n", - "Requirement already satisfied: xyzservices>=2021.09.1 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (2025.1.0)\n", - "Requirement already satisfied: cycler>=0.10 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from matplotlib->ipysim==0.0.12) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from matplotlib->ipysim==0.0.12) (4.56.0)\n", - "Requirement already satisfied: kiwisolver>=1.3.1 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from matplotlib->ipysim==0.0.12) (1.4.8)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from matplotlib->ipysim==0.0.12) (3.2.1)\n", - "Requirement already satisfied: python-dateutil>=2.7 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from matplotlib->ipysim==0.0.12) (2.9.0.post0)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from requests->ipysim==0.0.12) (3.4.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from requests->ipysim==0.0.12) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from requests->ipysim==0.0.12) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from requests->ipysim==0.0.12) (2025.1.31)\n", - "Requirement already satisfied: parso<0.9.0,>=0.8.4 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from jedi>=0.16->ipython->ipysim==0.0.12) (0.8.4)\n", - "Requirement already satisfied: ptyprocess>=0.5 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from pexpect>4.3->ipython->ipysim==0.0.12) (0.7.0)\n", - "Requirement already satisfied: wcwidth in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->ipysim==0.0.12) (0.2.13)\n", - "Requirement already satisfied: six>=1.5 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from python-dateutil>=2.7->matplotlib->ipysim==0.0.12) (1.17.0)\n", - "Requirement already satisfied: executing>=1.2.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from stack_data->ipython->ipysim==0.0.12) (2.2.0)\n", - "Requirement already satisfied: asttokens>=2.1.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from stack_data->ipython->ipysim==0.0.12) (3.0.0)\n", - "Requirement already satisfied: pure-eval in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from stack_data->ipython->ipysim==0.0.12) (0.2.3)\n", - "Requirement already satisfied: MarkupSafe>=2.0 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from Jinja2>=2.9->bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (3.0.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from pandas>=1.2->bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (2025.1)\n", - "Requirement already satisfied: tzdata>=2022.7 in /Users/heap/programming/IT2901/ForceoftheCyber/CyberBook/.venv/lib/python3.13/site-packages (from pandas>=1.2->bokeh==3.*->jupyter-bokeh->ipysim==0.0.12) (2025.1)\n", - "Downloading ipysim-0.0.12-py3-none-any.whl (5.3 kB)\n", - "Installing collected packages: ipysim\n", - " Attempting uninstall: ipysim\n", - " Found existing installation: ipysim 0.0.11\n", - " Uninstalling ipysim-0.0.11:\n", - " Successfully uninstalled ipysim-0.0.11\n", - "Successfully installed ipysim-0.0.12\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.0.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "31e3c9c7d86c49babd7db0e80bc74f3f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(FloatSlider(value=200.0, description='Kp', max=1000.0, step=10.0), FloatSlider(value=40.…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6e78b0c6543d4bc3a5b8d641957892e0", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(Output(), Button(description='Evaluate', style=ButtonStyle()), Output()))" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "%pip install ipysim==0.0.12\n", - "from ipysim.widgets import interactive_simulation\n", - "\n", - "def evaluation_check(sol, t):\n", - " z = sol[:, 1] # Extract the z (height) position\n", - " return 0.02 < z[-1] < 0.03\n", - "\n", - "# Run the interactive simulation with evaluation\n", - "interactive_simulation(\n", - " T=1.0,\n", - " Kp_default=200.0,\n", - " Kd_default=40.0,\n", - " evaluation_function=evaluation_check\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.2" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/book/some_content/nb_parse_eskild.py b/book/some_content/nb_parse_eskild.py new file mode 100644 index 0000000..463335c --- /dev/null +++ b/book/some_content/nb_parse_eskild.py @@ -0,0 +1,25 @@ +from pathlib import Path +import nbformat +from glob import glob + + +nbpaths = glob("./chapters/**/*.ipynb", recursive=True) + +excluding_tags = ["remove-cell"] + +def extract_content(notebook_file: str) -> str: + + abs_path = Path(notebook_file).resolve() + + with abs_path.open("r", encoding="utf-8") as file: + nb = nbformat.read(file, nbformat.NO_CONVERT) + + return " ".join([ + cell.source + for cell in nb.cells + if not set(excluding_tags) & set(cell.get("metadata", {}).get("tags", [])) # Intersection + ]) + +def extract_all() -> list[str]: + return [extract_content(path) for path in nbpaths] + diff --git a/scripts/convert_to_local.py b/scripts/convert_to_local.py new file mode 100644 index 0000000..85c5402 --- /dev/null +++ b/scripts/convert_to_local.py @@ -0,0 +1,23 @@ +# Small script for converting download FaceIT-questions + +import requests +import json + +URL = "https://dev.faceittools.com/questions/fetch_questions_cu/it2901Adaptive" + +response = requests.get(URL) + +if response.status_code == 204: + print("error") +elif response.status_code == 200: + content = response.json() + + # Sanity check + if content["status"] != "success": + raise RuntimeError("Fetch returned with response code 200, but status in body was not 'success'") + + # Also limits questions + questions = json.loads(content["questions"]) + + with open("output.json", "w") as file: + file.write(content["questions"]) \ No newline at end of file