├── README.md ├── bldc_motor_control ├── bldc_foc.ipynb ├── half_bridge_control.ipynb └── motor_modeling.ipynb ├── control_theory └── predictive_filtering │ ├── FOPDT.ipynb │ └── predictive_filtering.ipynb └── light_guide_panel_generator ├── example.svg ├── good_laser_density_params.png └── light_guide_panel_generator.ipynb /README.md: -------------------------------------------------------------------------------- 1 | My engineering project notebook 2 | 3 | ## Installation Requirements: 4 | 5 | Most of these notebooks require: 6 | 7 | ``` 8 | sympy 9 | numpy 10 | ``` 11 | -------------------------------------------------------------------------------- /bldc_motor_control/bldc_foc.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Commutation\n", 8 | "\n", 9 | "A BLDC motors contains two main components of interest, a rotor (the rotating part) and a stator (the stationary part). Depending on the type of blc motor, the magnets will be either (1) attached permanently to the rotor with the coils on the stator (outrunner) or (2) attached permanently to the stator with the coils on the rotor (inrunner).\n", 10 | "\n", 11 | "The goal of controlling a BLDC motor is to control current to create a rotating magnetic field on the coils that is always orthogonal to the permanent magnetic field such that we generate the highest-efficiency torque to cause the motor to turn. (Any angle other than $90^\\circ$ is inefficient and will result in wasted energy disipated as heat.\n", 12 | "\n", 13 | "The process of controlling the motor current which creates the magnetic field of the motor in such a way that causes the motor to spin is called *commutation*. With a *brushed* DC motor, this process is done mechanically where the physical brushes on the motor shaft physically switch coils based on the angle of the motor. With a *brushless* DC motor, this process must be done with sensors and a microcontroller.\n", 14 | "\n", 15 | "To perform commutation, there are two things we need to measure at all times: (1) the angle of the motor shaft, which lets us compute the angle of the permanent magnetic field, and (2) the actual current going through each of the three phase windings. There is one (technically 3) thing we need to control at all times: the current going through each of the three phase windings.\n" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "## Background\n", 23 | "\n", 24 | "A BLDC motor is a 3 phase system, and thinking about things in terms of each phase can get confusing. That's where the Parke and Clark Transforms come into play. They simplify the way to conceptualize what exactly we are trying to control. The result is that we can think about both current and the the motor's magnetic field as 2D vectors with angle and magnitude.\n", 25 | "\n", 26 | "\n", 27 | "## The Parke and Clarke Transform\n", 28 | "\n", 29 | "Let's collect the 3-phase currents into a vector $\\begin{bmatrix}a \\\\ b \\\\ c \\\\ \\end{bmatrix}$ The vector exists in a 3D \"coil space\" spanned by a linear combination of $a$, $b$, and $c$ orthogonal components. (See [Wikipedia](https://en.wikipedia.org/wiki/Direct-quadrature-zero_transformation#/media/File:DQZ_1.svg))\n", 30 | "\n", 31 | "\n", 32 | "Let the Clarke Transform be denoted $K_c$. This transform rotates our coil space so that we're looking at it top-down from the tip of a $\\begin{bmatrix} 1\\\\ 1\\\\ 1\\\\ \\end{bmatrix}$ vector in that space. (Again, see [Wikipedia](https://en.wikipedia.org/wiki/Direct-quadrature-zero_transformation#/media/File:DQZ_6.svg)). After doing this rotation, we can basically ignore the Z component, making our system 2D.\n", 33 | "\n", 34 | "\n", 35 | "Let the Parke Transform be denoted $K_p$. This transform takes vectors from our 2D space and rotates them about the z axis such that the new x axis of this space is always aligned with the motor's magnetic field flux vector. This space will rotate in time, but since we know the angle of the motor shaft at all times, we can do calculations from the perspective of this rotating space as if they weren't rotating.\n", 36 | "\n", 37 | "\n", 38 | "In Linear Algebra terms, then the Parke and Clarke Transforms are just a change of basis.\n", 39 | "\n", 40 | "$$\n", 41 | "\\begin{bmatrix} d \\\\ q \\\\ z \\end{bmatrix} = \n", 42 | "K_{p} K_{c} \\begin{bmatrix} a \\\\ b\\\\ c\\\\ \\end{bmatrix} = \n", 43 | "K_{cp} \\begin{bmatrix} a\\\\ b\\\\ c\\\\ \\end{bmatrix}\n", 44 | "$$\n", 45 | "\n", 46 | "Note that $K_{cp}$ is invertible.\n" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Terms\n", 54 | "\n", 55 | "Recall that torque is directly proportional to current. ([Wikipedia](https://en.wikipedia.org/wiki/Motor_constants))\n", 56 | "$$\n", 57 | "T = K_T i\n", 58 | "$$\n", 59 | "\n", 60 | "Where $K_T = \\frac{1}{K_v}$, where $K_v$ might be a more familiar motor specification.\n", 61 | "\n", 62 | "Therefore, building a current controller is equivalent to building a torque controller.\n", 63 | "\n" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "## A Simplified Algorithm\n", 71 | "\n", 72 | "1. Determine (or set) magnetic field orientation. (D)\n", 73 | "1. Use D to determine Q in transformed frame.\n", 74 | "1. Set the Magnitude of Q according to desired torque\n", 75 | "1. Inverse Transform Q into 3 coils currents\n", 76 | "1. Apply currents to motor.\n", 77 | "1. Wait some small time delta.\n", 78 | "1. Measure actual currents. Measure D from the rotor angle.\n", 79 | "1. Forward-Transform currents into D in the Transformed frame.\n", 80 | "1. Use new D measurement to compute desired Q current vector.\n", 81 | "1. Use actual currents to compute actual Q current vector.\n", 82 | "1. Feed Error into PI controller.\n", 83 | "1. Repeat from step 5\n" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "## Pole Pairs\n", 91 | "\n", 92 | "In reality, BLDC motors have multiple pole pairs per revolution. And to smooth out motor cogging, the number of poles on the stator is not equal to the number of poles on the rotor. The crux is that the magnetic field angle that we've described above is not the same as the rotor angle. But the conversion is simple and dictated by the [winding combination](https://electronics.stackexchange.com/questions/483177/how-to-determine-brushless-dc-bldc-winding-pattern-based-on-poles-and-slots?rq=1)\n", 93 | "\n", 94 | "Assuming a 14P12N BLDC motor (fairly common) there are 7 electrical cycles per mechanical cycle.\n" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "## Resources\n", 102 | "1. [Field Oriented Control of Permanent Magnet Motors](https://www.youtube.com/watch?v=cdiZUszYLiA&t=347s&ab_channel=TexasInstruments)\n", 103 | "1. [Janzen Lee](https://www.youtube.com/watch?v=mbJOxqxLkLE&ab_channel=JantzenLee)\n", 104 | "1. [SUBMS: Motor Modeling](http://subms.com/tutorials/motor_modeling)\n", 105 | "1. [SUMBS: Motor Control](http://subms.com/tutorials/motor_control)\n", 106 | "1. [Park and Clark Transform Summary](https://www.cypress.com/file/222111/download)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [] 115 | } 116 | ], 117 | "metadata": { 118 | "kernelspec": { 119 | "display_name": "Python 3", 120 | "language": "python", 121 | "name": "python3" 122 | }, 123 | "language_info": { 124 | "codemirror_mode": { 125 | "name": "ipython", 126 | "version": 3 127 | }, 128 | "file_extension": ".py", 129 | "mimetype": "text/x-python", 130 | "name": "python", 131 | "nbconvert_exporter": "python", 132 | "pygments_lexer": "ipython3", 133 | "version": "3.6.12" 134 | } 135 | }, 136 | "nbformat": 4, 137 | "nbformat_minor": 4 138 | } 139 | -------------------------------------------------------------------------------- /bldc_motor_control/half_bridge_control.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Our FOC algorithm eventually generates three current values who's outputs sum to zero.\n", 8 | "\n", 9 | "We need to send these values to our half bridges to control the direction of current into the motor.\n", 10 | "\n", 11 | "All of our signals will be $120^{\\circ}$ out of phase with each other after the Parke/Clarke Transforms.\n", 12 | "\n", 13 | "A resulting current vector in ABC-space will look like this:\n", 14 | "$$\n", 15 | "i_{abc} =\n", 16 | "\\begin{bmatrix} 0 \\\\ 0.866 \\\\ -0.866 \\end{bmatrix}\n", 17 | "$$\n", 18 | "\n", 19 | "If the value is negative, we PWM the lower half bridge. If positive, we PWM the upper half bridge.\n", 20 | "\n", 21 | "Timingwise, we want to make sure that our on times are synchronized. In practice, the microcontroller might just do this for us automatically.\n" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [] 30 | } 31 | ], 32 | "metadata": { 33 | "kernelspec": { 34 | "display_name": "Python 3", 35 | "language": "python", 36 | "name": "python3" 37 | }, 38 | "language_info": { 39 | "codemirror_mode": { 40 | "name": "ipython", 41 | "version": 3 42 | }, 43 | "file_extension": ".py", 44 | "mimetype": "text/x-python", 45 | "name": "python", 46 | "nbconvert_exporter": "python", 47 | "pygments_lexer": "ipython3", 48 | "version": "3.6.12" 49 | } 50 | }, 51 | "nbformat": 4, 52 | "nbformat_minor": 4 53 | } 54 | -------------------------------------------------------------------------------- /bldc_motor_control/motor_modeling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# Environment Setup\n", 10 | "import sympy as sym\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "sym.init_printing(use_latex='mathjax')\n", 14 | "from IPython.display import display, Markdown, Math" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Motor Modeling\n", 22 | "\n", 23 | "Torque is controlled via current, but when we set the PWM values on the motor coils we are actually dictating the voltage. To control current with voltage, we need a motor model of how voltage (the parameter we can actually control) affects current (the parameter we want to control).\n", 24 | "\n", 25 | "\n", 26 | "## Constants:\n", 27 | "\n", 28 | "$J_m$: $\\text{kg} \\text{m}^2$ Rotational moment of inertia\n", 29 | "\n", 30 | "$B_m$: Friction coefficient. (Scalar, dimensionless)\n", 31 | "\n", 32 | "$L_m$: $\\text{Henrys}$ inductance of the motor coils\n", 33 | "\n", 34 | "$R_m$: $\\text{Ohms}$ resistance of the motor coils\n", 35 | "\n", 36 | "$K_v$: $\\frac{\\text{RPM}}{\\text{V}}$ motor constant that shows up more commonly.\n", 37 | "\n", 38 | "$K_m$: $\\frac{60}{2 \\pi K_v}$ motor torque constant\n", 39 | "\n", 40 | "$G_{iv} = \\frac{\\text{output}}{\\text{input}} = \\frac{I(s)}{V(s)}$" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 59, 46 | "metadata": {}, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "text/latex": [ 51 | "$\\displaystyle \\frac{B_{m} + J_{m} s}{B_{m} R_{m} + J_{m} L_{m} s^{2} + K_{m}^{2} + s \\left(B_{m} L_{m} + J_{m} R_{m}\\right)}$" 52 | ], 53 | "text/plain": [ 54 | " Bₘ + Jₘ⋅s \n", 55 | "──────────────────────────────────────────\n", 56 | " 2 2 \n", 57 | "Bₘ⋅Rₘ + Jₘ⋅Lₘ⋅s + Kₘ + s⋅(Bₘ⋅Lₘ + Jₘ⋅Rₘ)" 58 | ] 59 | }, 60 | "metadata": {}, 61 | "output_type": "display_data" 62 | } 63 | ], 64 | "source": [ 65 | "# Create the Voltage-to-Current Transfer Function in Sympy\n", 66 | "s = sym.symbols('s')\n", 67 | "t = sym.symbols('t', real=True)\n", 68 | "Jm, Bm, Lm, Rm, Km, Vm = sym.symbols('J_m, B_m, L_m, R_m, K_m, V_m', real=True)\n", 69 | "kv = 25 # rpm per volt\n", 70 | "\n", 71 | "givens = \\\n", 72 | "{\n", 73 | " Jm: 0.001, # rotational moment of inertia. Random guess, but just influences time until steady-state.\n", 74 | " Bm: 0.005, # Friction Coefficient. 3 decimal places is a reasonable value for ball bearings.\n", 75 | " Lm: 0.001,\n", 76 | " Rm: 15,\n", 77 | " Km: 60./(2 * sym.pi * kv),\n", 78 | "}\n", 79 | "\n", 80 | "# L(Output)/L(Input) = I(s)/V(s)\n", 81 | "Tf = (s * Jm + Bm)/(s**2 * Jm*Lm + s*(Jm*Rm + Bm*Lm) + (Bm*Rm + Km**2))\n", 82 | "display(Tf)\n", 83 | "\n", 84 | "num,den = Tf.subs(givens).as_numer_denom()\n", 85 | "num_coeffs = sym.Poly(num.subs(givens).evalf(), s).coeffs()\n", 86 | "den_coeffs = sym.Poly(den.subs(givens).evalf(), s).coeffs()\n", 87 | "\n", 88 | "# Convert out of Sympy Float to normal float.\n", 89 | "num_coeffs = [float(c) for c in num_coeffs]\n", 90 | "den_coeffs = [float(c) for c in den_coeffs]" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 60, 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "image/png": "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\n", 101 | "text/plain": [ 102 | "
" 103 | ] 104 | }, 105 | "metadata": { 106 | "needs_background": "light" 107 | }, 108 | "output_type": "display_data" 109 | } 110 | ], 111 | "source": [ 112 | "# Numerically Simulate the Transfer Function\n", 113 | "from scipy.signal import lsim\n", 114 | "step_voltage = 24\n", 115 | "t_short = np.linspace(0, 0.01,100, endpoint=False) # 0.0, 0.01, ...\n", 116 | "t_long = np.linspace(0, 10, 1000, endpoint=False)\n", 117 | "sim_times = [t_short, t_long]\n", 118 | "\n", 119 | "fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 3))\n", 120 | "titles = [rf\"$i(t)$ for ${step_voltage}$v step input, (Short Time)\",\n", 121 | " rf\"$i(t)$ for ${step_voltage}$v step input, (Long Time)\"]\n", 122 | "\n", 123 | "for ax, t_, title in zip(axes, sim_times, titles):\n", 124 | " u_ = np.ones_like(t_) * step_voltage # step input.\n", 125 | " t_, y_, x_ = lsim((num_coeffs, den_coeffs), u_, t_)\n", 126 | " ax.plot(t_, y_, label=rf\"$i(t)$\")\n", 127 | " ax.set_title(title)\n", 128 | " ax.set_xlabel(r\"time $(t)$\")\n", 129 | " ax.set_ylabel(r\"current $(A)$\")\n", 130 | " ax.legend()\n", 131 | "fig.tight_layout()" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "Do the above graphs make sense?\n", 139 | "\n", 140 | "Yes! Starting from an idle motor (rpm = 0), the transient behavior is for current to follow the voltage immediately. But, once the motor starts spinning, it starts generating a Back-EMF voltage that opposes the input voltage. This Back-EMF increases until we hit equilibrium. \n", 141 | "\n", 142 | "Let's make a few observations:\n", 143 | "\n", 144 | "1. Increasing the voltage (to 18v or 24v) produces current values that make more sense with [this gimbal motor](https://indonesian.alibaba.com/product-detail/gbm5208h-200t-dc-brushless-gimbal-motor-1600101101528.html) with similar specs to our model.\n", 145 | "1. A smaller moment of inertia means the motor will spin up faster.\n", 146 | "1. A smaller internal resistance means the input current will be higher\n", 147 | "1. A smaller amount of friction means that the steady-state current would asymptotically approach zero since the back-EMF and input voltage would more closely match each other.\n", 148 | "\n", 149 | "---" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "## State Space Representation\n", 157 | "\n", 158 | "\n", 159 | "In state space, our differential equation takes on the form:\n", 160 | "$$\n", 161 | "f(\\vec{x}, \\vec{u}) = \\vec{x}'\n", 162 | "$$\n", 163 | "\n", 164 | "Here let's let our state and inputs be:\n", 165 | "\\begin{align}\n", 166 | "\\vec{x} = \n", 167 | "\\begin{bmatrix}\n", 168 | "\\theta \\\\\n", 169 | "\\theta' \\\\\n", 170 | "i \\\\\n", 171 | "\\end{bmatrix}\n", 172 | "&&\n", 173 | "\\vec{u} = \\begin{bmatrix} V_m \\end{bmatrix}\n", 174 | "\\end{align}\n", 175 | "\n", 176 | "Using our equations from [subms](http://subms.com/tutorials/motor_modeling), we get:\n", 177 | "\n", 178 | "$$\n", 179 | "f(\\vec{x}, \\vec{u}) = \n", 180 | "\\begin{bmatrix}\n", 181 | "\\theta' \\\\\n", 182 | "\\frac{K_m}{J_m}i - \\frac{B_m}{J_m}\\theta'\\\\\n", 183 | "-\\frac{R_m}{L_m}i - \\frac{K_m}{L_m}\\theta' + \\frac{1}{L_m}V_m\n", 184 | "\\end{bmatrix}\n", 185 | "$$\n", 186 | "\n", 187 | "The above system is already linear, which is nice since we're not approximating when we put it into $A\\vec{x} + B\\vec{u}$ form. In that form, we get:\n", 188 | "\n", 189 | "$$\n", 190 | "\\begin{bmatrix}\n", 191 | "\\theta' \\\\\n", 192 | "\\theta'' \\\\\n", 193 | "i'\n", 194 | "\\end{bmatrix} =\n", 195 | "\\begin{bmatrix}\n", 196 | "0 & 1 & 0 \\\\\n", 197 | "0 & -\\frac{B_m}{J_m} & \\frac{K_m}{J_m}\\\\\n", 198 | "0 & -\\frac{K_m}{L_m} & -\\frac{R_m}{L_m}\n", 199 | "\\end{bmatrix}\n", 200 | "\\begin{bmatrix}\n", 201 | "\\theta \\\\\n", 202 | "\\theta' \\\\\n", 203 | "i\n", 204 | "\\end{bmatrix}\n", 205 | "+\n", 206 | "\\begin{bmatrix}\n", 207 | "0 \\\\\n", 208 | "0\\\\\n", 209 | "\\frac{1}{L_m}\n", 210 | "\\end{bmatrix}\n", 211 | "\\begin{bmatrix}\n", 212 | "V_m\n", 213 | "\\end{bmatrix}\n", 214 | "$$" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 4, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [ 223 | "# Prof Burden's Numerical Simulation fn\n", 224 | "# from: https://colab.research.google.com/github/sburden/547-21wi/blob/master/547_lec.ipynb#scrollTo=x-AAJZ-RNxS-\n", 225 | "def numerical_simulation(f,t,x,t0=0.,dt=1e-4,ut=None,ux=None,utx=None,return_u=False):\n", 226 | " \"\"\"\n", 227 | " simulate x' = f(x,u) \n", 228 | "\n", 229 | " input:\n", 230 | " f : R x X x U --> X - vector field\n", 231 | " X - state space (must be vector space)\n", 232 | " U - control input set\n", 233 | " t - scalar - final simulation time\n", 234 | " x - initial condition; element of X\n", 235 | "\n", 236 | " (optional:)\n", 237 | " t0 - scalar - initial simulation time\n", 238 | " dt - scalar - stepsize parameter\n", 239 | " return_u - bool - whether to return u_\n", 240 | "\n", 241 | " (only one of:)\n", 242 | " ut : R --> U\n", 243 | " ux : X --> U\n", 244 | " utx : R x X --> U\n", 245 | "\n", 246 | " output:\n", 247 | " t_ - N array - time trajectory\n", 248 | " x_ - N x X array - state trajectory\n", 249 | " (if return_u:)\n", 250 | " u_ - N x U array - state trajectory\n", 251 | " \"\"\"\n", 252 | " t_,x_,u_ = [t0],[x],[]\n", 253 | " \n", 254 | " inputs = sum([1 if u is not None else 0 for u in [ut,ux,utx]])\n", 255 | " assert inputs <= 1, \"more than one of ut,ux,utx defined\"\n", 256 | "\n", 257 | " if inputs == 0:\n", 258 | " assert not return_u, \"no input supplied\"\n", 259 | " else:\n", 260 | " if ut is not None:\n", 261 | " u = lambda t,x : ut(t)\n", 262 | " elif ux is not None:\n", 263 | " u = lambda t,x : ux(x)\n", 264 | " elif utx is not None:\n", 265 | " u = lambda t,x : utx(t,x)\n", 266 | "\n", 267 | " while t_[-1]+dt < t:\n", 268 | " if inputs == 0:\n", 269 | " _t,_x = t_[-1],x_[-1]\n", 270 | " dx = f(t_[-1],x_[-1]) * dt\n", 271 | " else:\n", 272 | " _t,_x,_u = t_[-1],x_[-1],u(t_[-1],x_[-1])\n", 273 | " dx = f(_t,_x,_u) * dt\n", 274 | " u_.append( _u )\n", 275 | "\n", 276 | " x_.append( _x + dx )\n", 277 | " t_.append( _t + dt )\n", 278 | "\n", 279 | " if return_u:\n", 280 | " return np.asarray(t_),np.asarray(x_),np.asarray(u_)\n", 281 | " else:\n", 282 | " return np.asarray(t_),np.asarray(x_)" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 5, 288 | "metadata": {}, 289 | "outputs": [ 290 | { 291 | "data": { 292 | "image/png": "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\n", 293 | "text/plain": [ 294 | "
" 295 | ] 296 | }, 297 | "metadata": { 298 | "needs_background": "light" 299 | }, 300 | "output_type": "display_data" 301 | } 302 | ], 303 | "source": [ 304 | "i, i_prime, theta, theta_prime = sym.symbols(\"i, i', \\theta, \\\\theta'\")\n", 305 | "\n", 306 | "kv = 25 # rpm per volt\n", 307 | "\n", 308 | "givens = \\\n", 309 | "{\n", 310 | " Jm: 0.01, # rotational moment of inertia\n", 311 | " Bm: 0.005, # Friction Coefficient\n", 312 | " Lm: 0.001,\n", 313 | " Rm: 15,\n", 314 | " Km: 60./(2 * sym.pi * kv),\n", 315 | "}\n", 316 | "\n", 317 | "A = sym.Matrix([[0, 1, 0], [0, -Bm/Jm, Km/Jm], [0, -Km/Lm, -Rm/Lm]])\n", 318 | "B = sym.Matrix([[0], [0], [1/Lm]])\n", 319 | "\n", 320 | "x = sym.Matrix([[theta], [theta_prime], [i]])\n", 321 | "u = sym.Matrix([Vm])\n", 322 | "\n", 323 | "f = A*x + B*u\n", 324 | "\n", 325 | "lambda_f = sym.lambdify([t, (theta, theta_prime, i), Vm], f.subs(givens))\n", 326 | "lambda_f_ = lambda t,x,u : lambda_f(t, x, u).flatten()\n", 327 | "lambda_u = lambda t: 24 # constant voltage of 24 for all time.\n", 328 | "\n", 329 | "sim_time =2.5\n", 330 | "x0 = np.array([0, 0, 0]) # initial condition for the lambdified function\n", 331 | "\n", 332 | "t_, x_ = numerical_simulation(lambda_f_, sim_time, x0, ut=lambda_u)\n", 333 | "\n", 334 | "plt.plot(t_, x_[:,0], label=r\"$\\theta(t)$\")\n", 335 | "plt.plot(t_, x_[:, 2], label=r\"$i (t)$\")\n", 336 | "plt.plot(t_, x_[:, 1], label=r\"$\\dot{\\theta}(t)$\")\n", 337 | "plt.legend()\n", 338 | "plt.show()" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "## Resources\n", 346 | "1. [SUBMS: Motor Modeling](http://subms.com/tutorials/motor_modeling)\n", 347 | "1. https://aleksandarhaber.com/modeling-a-dc-motor-and-matlab-simulation/\n", 348 | "1. [Motor Constants](https://en.wikipedia.org/wiki/Motor_constants)" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "## Scratchwork" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 6, 361 | "metadata": {}, 362 | "outputs": [ 363 | { 364 | "data": { 365 | "text/latex": [ 366 | "$\\displaystyle \\frac{B_{m} + J_{m} s}{B_{m} R_{m} + J_{m} L_{m} s^{2} + K_{m}^{2} + s \\left(B_{m} L_{m} + J_{m} R_{m}\\right)}$" 367 | ], 368 | "text/plain": [ 369 | " Bₘ + Jₘ⋅s \n", 370 | "──────────────────────────────────────────\n", 371 | " 2 2 \n", 372 | "Bₘ⋅Rₘ + Jₘ⋅Lₘ⋅s + Kₘ + s⋅(Bₘ⋅Lₘ + Jₘ⋅Rₘ)" 373 | ] 374 | }, 375 | "metadata": {}, 376 | "output_type": "display_data" 377 | }, 378 | { 379 | "data": { 380 | "text/latex": [ 381 | "$\\displaystyle \\frac{\\left(e^{t} + \\sin{\\left(t \\right)} - \\cos{\\left(t \\right)}\\right) e^{- t} \\theta\\left(t\\right)}{2}$" 382 | ], 383 | "text/plain": [ 384 | "⎛ t ⎞ -t \n", 385 | "⎝ℯ + sin(t) - cos(t)⎠⋅ℯ ⋅θ(t)\n", 386 | "───────────────────────────────\n", 387 | " 2 " 388 | ] 389 | }, 390 | "metadata": {}, 391 | "output_type": "display_data" 392 | }, 393 | { 394 | "data": { 395 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEJCAYAAACE39xMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAk2ElEQVR4nO3de3xU9Z3/8dcnk4QkGLkGRMJNuYaLqFwEb7WI1dYFb1vF4kNrXd22bvtra1e764Nu1V9rq6td96dVq1jXxXqrdalSrWW14o0ClhYBuQgRgyghhFvumXx+f8wkDCEhkzDJZM68n49HHsw5c+aczwzJO998zznfr7k7IiKS+jKSXYCIiCSGAl1EJCAU6CIiAaFAFxEJCAW6iEhAZCbrwP379/fhw4cn6/AiIilp1apVu9y9oKXnkhbow4cPZ+XKlck6vIhISjKzj1p7Tl0uIiIBoUAXEQkIBbqISEAkrQ9dpLupq6ujpKSE6urqZJciQk5ODoWFhWRlZcX9GgW6SFRJSQn5+fkMHz4cM0t2OZLG3J2ysjJKSkoYMWJE3K9Tl4tIVHV1Nf369VOYS9KZGf369Wv3X4txBbqZnW9mG8xss5nd0so2XzazdWa21syebFcVIt2Ewly6i458L7bZ5WJmIeB+YDZQAqwws8Xuvi5mm1HAD4DT3b3czAa0u5Juri7cwPItu1m/Yx+14QYG9cph2oi+FPbJS3ZpIiJAfH3o04DN7r4FwMyeAuYC62K2+QfgfncvB3D3nYkuNFncnedWlXDXKxvYub/msOdnnNCPf/r8SGaO7J+E6kREDoon0AcDH8cslwDTm20zGsDM3gJCwL+5+8sJqTCJ6sIN/Mvza3h2VQmnDO3NHRdNYOrwvuRmh/iorJI/rv+MRe9+xJWPLOe8ooH834snUpDfI9lli0iaStRJ0UxgFPA5YB7wSzPr3XwjM7vezFaa2crS0tIEHbpzuDs3PftXnl1VwrdmjeK5f5zJeeOPo0/PbHKyQow5Lp9vnjOS/73pc/zz+WP408ZSLviPZbyxsXu/L+n+3n77bRYsWEBVVRVnn3024XAYiFyF8/TTTwNQW1vLWWedRX19fYv7uO+++xg3bhxf+cpXuqzu9pg5cyZ79uzhgQceaNfrOvKajjiazz4e1157LQMGDGDChAkJqbdRPIG+HRgSs1wYXRerBFjs7nXuvhXYSCTgD+HuD7v7FHefUlDQ4tgy3cYDr3/I/6z+hJvOG813Z48mI6PlExQ5WSG+8bmRLL7xDPr2zOKax/7Mf71T3LXFSqDMnDmT2267jYULF3LJJZcQCoUAWLp0Ke+99x4A2dnZzJo1qylkmnvggQd49dVXWbRo0SHr3Z2GhobOfQNxePvtt7t1oB/NZx+Pa665hpdf7oRODHc/4heR1vcWYASQDfwVGN9sm/OBx6OP+xPpoul3pP2eeuqp3l29v32Pn/iDl/ybi1Z5Q0ND3K87UF3nX/vVn33YzS/67b9b267XSvKtW7cu2SW4u/tll13mb7zxhs+YMcO3bt3q7u7Lli3zvn37+gknnOAnnXSSf/jhh7569Wq/4IILDnv9DTfc4FlZWT5hwgS/5557fOvWrT569Gi/6qqrvKioyIuLi/3f//3fffz48T5+/Hi/99573d1969atPmbMGL/66qt91KhRfuWVV/qrr77qM2fO9JEjR/ry5csPO9bWrVt9/PjxTct33XWX//CHP/StW7f62LFj/brrrvOioiKfPXu2V1ZWNm3Xs2dPv/zyyz0nJ8dPOukkv+mmmw7Z74EDB/yLX/yiT5o0ycePH+9PPfWUu3uLr3niiSd86tSpftJJJ/n111/v9fX1Te/lyiuv9LFjx/qll17qFRUVhxxj5cqVfvbZZzctr1mzxmfMmOHu3uHPvj2af3Ytael7EljpreRqm33o7l5vZjcCrxDpH1/o7mvN7LbojhdHnzvPzNYBYeD77l6W0N88XaShwbnlN2vonZfN7XMntOvSoZ49Mnnoqinc9ru1PPLmVirrwtwxd0KrrXvpvn70u7Ws+2RfQvdZdPyx/PDvxre53fvvv8+kSZPYsmULjUNMn3HGGUydOpW777676c/0cDjMihUrDnv9gw8+yMsvv8xrr71G//79KS4uZtOmTTz++OOcdtpprFq1iscee4zly5fj7kyfPp2zzz6bPn36sHnzZp599lkWLlzI1KlTefLJJ3nzzTdZvHgxP/7xj3nhhRfifr+bNm3i17/+Nb/85S/58pe/zG9+8xvmz5/f9Pydd97J+++/z+rVqw977csvv8zxxx/PSy+9BMDevXtbfM369et5+umneeutt8jKyuIb3/gGixYt4qyzzmLDhg08+uijnH766Vx77bU88MAD3HTTTU3HGDduHBs3bmxaXrBgAbfddhu1tbUd/uzPPPNM9u/ff9j6u+++m3PPPTfuz66j4rpT1N2XAEuarVsQ89iB70a/UtqLa3awZvte7r38JPr0zG7360MZxr/NGU9ej0x+8fqH1NU3cOelkwgp1CUO1dXV1NbWUlFRQe/evQ95bsOGDYwdO7ZpORQKkZ2dzf79+8nPzz/ifocNG8Zpp50GwJtvvsnFF19Mz549AbjkkktYtmwZc+bMYcSIEUycOBGA8ePHM2vWLMyMiRMnUlxc3K73MmLECCZPngzAqaee2q7XT5w4ke9973vcfPPNXHjhhZx55pktbrd06VJWrVrF1KlTgUjf94ABAzjrrLMYMmQIp59+OgDz58/nvvvuOyTQ8/LyyM3NZc+ePWzZsoXy8nLOPfdcPvnkkw5/9suWLYv7PXYG3fofoz7cwD1/2MDY4/KZe9LgDu/HzPjnL4whK5TBfUs3AfDTSyeppZ5C4mlJd4a1a9dSVFREbm7uIXcJ7tq1i169epGZeeiPbE1NDTk5OW3utzG829Kjx8GrtDIyMpqWMzIyWjwJmJmZeUiffGzNsfsKhUJUVVXFVQPA6NGjee+991iyZAm33nors2bNYsGCBYdt5+5cffXV/OQnPzlkfXFx8WF/Xbf013ZRUREffPABt99+O3fccQfAUX32yW6h69b/GC+v/ZTiskq+c4SToPEyM747ezTf+vxInl1Vwu0vrWs83yDSqjVr1jBp0iT69OlDOBxuCpbi4mKOP/74Q7YtKyujf//+7Rq8CSKh88ILL1BZWUlFRQW//e1vW20Bt2XgwIHs3LmTsrIyampqePHFF+N+bX5+fovhB/DJJ5+Ql5fH/Pnz+f73v990QrL5a2bNmsVzzz3Hzp2RW192797NRx9F5n/Ytm0b77zzDgBPPvkkZ5xxxmHHGT9+PAsXLsTdm1rzR/PZL1u2jNWrVx/21RVhDgr0Qyx8cyvD+uUxe9zAhO3zO7NH89XTh/PYW8Xc+8dNCduvBFNjoAOcd955vPnmmwCMHTuWXbt2MWHCBN5++20AXnvtNb70pS+1+xinnHIK11xzDdOmTWP69Olcd911nHzyyR2qNysriwULFjBt2jRmz559SLdEW/r168fpp5/OhAkT+P73v3/Ic2vWrGHatGlMnjyZH/3oR9x6660tvqaoqIg77riD8847j0mTJjF79mx27NgBwJgxY7j//vsZN24c5eXlfP3rXz+shvHjx/PII480tc4bddZn32jevHnMmDGDDRs2UFhYyKOPPtrhfR2itbOlnf3V3a5yWb2t3Ifd/KI/9uaWhO87HG7wm55Z7cNuftF/+caHCd+/JEZ3ucql0apVq3z+/PmtPn/xxRf7hg0burCi1BHPFSRH0l0++4Rf5ZIunltVQo/MDC49tTDh+87IMO68dBKVtWHueGk9PXtkMm/a0IQfR4LllFNO4ZxzziEcDjddD92otraWiy66iNGjRyepumBL1c/ePEn9ulOmTPHuMkl0bX0D03/8R84YVcB/zuvYn57xHuf6J1byp42l/Pzyycyd3PETr5J469evZ9y4cckuQ6RJS9+TZrbK3ae0tL360IE/bSylvLKOS07u3IDNzszgwfmnMm14X777zF95dd1nnXo8EUkvCnTghdXb6dczmzNGdf6IiTlZIR65egoTjj+Wby56jzc37er0Y4pIekj7QK+pD/P6Bzv5woTjyAp1zceRn5PF49dO44SCnvzDf61kZfHuLjmutC1ZXZAizXXkezHtA335lt1U1IY5d1zXzsnROy+bJ742neN65fDVx1bw/va9XXp8OVxOTg5lZWUKdUk6j84pGs9NY7HS/iqXpes/Iycrg5kndv0EFQX5Pfjv66bz5Qff4apHl/PMDTMYNfDIt3BL5yksLKSkpITuPrSzpIecnBwKC9t31V1aB7q788f1OzljZH9yskJtv6ATDO6dy6LrpvP3D73DlY8sZ9F10xmtUE+KrKysds2wLtLdpHWXy6adB9i+p4pZCbwztCOG9+/Jk9dNx4DLH3pH3S8i0iFpHehvb45cYXJGN5gPdNTAfJ65YQZ52ZnM++W7vLetPNkliUiKSetAf2dLGYV9chnSNy/ZpQCRlvrTN5xG357ZXPXIcpZtUl+uiMQvbQO9ocFZvnU3M07ol+xSDlHYJ49nbpjBkL55fPWxFTy9YluySxKRFJG2gb7+033sqaxjxondK9ABBh6bw7P/OIMZJ/bj5t+s4a5XPqChQZfSiciRpW2gv/NhZIa87hjoELn5aOE1U5k3bQj3v/Yh1z+xir1VdckuS0S6sbQN9JXF5Qztm8egXrnJLqVVWaEMfnzxRH74d0W8vmEnF/7nMl0BIyKtSttA/8vH5Zw8tHeyy2iTmfHV00fw9A0zqA87l/zibR7604eE1QUjIs2kZaDv2FvFZ/tqOHlI72SXErdTh/XhpW+dyedGF/CT33/AZQ++zYelB5Jdloh0I2kZ6H/ZtgeAyUP7JLeQdurbM5uHrjqV/7hiMltKK7jg58v46csfcKDm8Ml7RST9pGmgl5OdmUHRoGOTXUq7mRlzJw/m1e+cxYWTBvGL1z/knLtf56k/b6O2vqHtHYhIYKVloK/+eA8Tjj+W7MzUffsDjs3hnssn89tvzKSwTy63PL+Gc+5+ncffLqa6Lpzs8kQkCeJKNDM738w2mNlmM7ulheevMbNSM1sd/bou8aUmRn24gb+V7GXykNTqbmnNyUP78PzXZ/LYV6cyqFcOP1y8ltN+spQf/W4tGz/bn+zyRKQLtTnaopmFgPuB2UAJsMLMFrv7umabPu3uN3ZCjQm1ZVcFNfUNTCxMve6W1pgZ54wZwOdGF/Dnrbt54t2P+O93P+Kxt4opGnQsXxh/HF+YMJAxA/Mxs2SXKyKdJJ7hc6cBm919C4CZPQXMBZoHekpY98k+AIoG9UpyJYlnZkw/oR/TT+hH2YEafvuX7fz+/U/5+dKN3PvHjQzI78HUEX2ZOqwPJw/tw6iBx5CXnRojKLs7dWGnqi5MTV2Y6roGqurCVNeFm/6tjq6vqQ8TboCwO+5OuCHy1eBOgxN53BB97I2PnXAHJ7Yw2vdL8ki/U4+0pyO/rvUnO3q81l7Y1TUG0TljBjCxMPEZFM9P82Dg45jlEmB6C9tdamZnARuB77j7x803MLPrgesBhg4d2v5qE2Ddjn1kZ2ZwQkHPpBy/q/Q7pgfXnXkC1515Ajv3V7N0/U7e3VLGiq27eelvO5q2G9I3l1ED8jm+dw4D83MY2CuHAfk9yM/JpGePTHpmZ3JMj0xCISPDIj+SZpBhRn2DU1vf0PRVUx+mpr6B2nADNXUNB0O2PkxVbUNT+NY0hXBDTCAf3L4qJpxj13XWpfcZBqEMw6y90QztLukIL/AjPHmk3zVHquFIsy8d+XVHeFKOWt+e2UkL9Hj8Dvi1u9eY2Q3A48Dnm2/k7g8DDwNMmTIlKd8y6z7Zx+iBx3TZ/KHdwYD8HOZNG8q8aZFfoiXllby/fR+bPtvPxp0H2LzzAH/ZVk55ZdcMLWAGOZkhcrND5GRmkJMdIiczRE5WBrnZIXrlZh26LitETlZk+x6ZGZHHTesyyMkM0aNpXQY9skKEzMjIIPKvGRkZRijDCJlh0QBvfKxuqMQ44i+Po/iFFMT/n856R/EE+nZgSMxyYXRdE3cvi1l8BPjZ0ZeWeO7Ouh37unz+0O6msE8ehX3yOH/CcYesr64Ls3NfDaUHqtlfXU9FTZiKmnoO1NRHuyscd2hwaHAnM8PokZlBdmYo+m/kq0dmBj1iAvpgeIfokRV5Pog/pOnuSP+nHf/v1vdJe8QT6CuAUWY2gkiQXwFcGbuBmQ1y98a/4+cA6xNaZYLs3F/D7oralLz+vCvkZIUY2i+Pof26x/jwItI+bQa6u9eb2Y3AK0AIWOjua83sNmCluy8GvmVmc4B6YDdwTSfW3GFNJ0SPD94JURGRuPrQ3X0JsKTZugUxj38A/CCxpSXeuh2RQB87SJMwi0jwpM+ZQWD9jn0U9snl2JysZJciIpJwaRXom3ceYNSAY5JdhohIp0ibQA83OFt2VTBSgS4iAZU2gf7x7kpq6xsU6CISWGkT6Jt3RiaDUKCLSFClT6BHZ/cZWaArXEQkmNIn0HceoP8xPeiVpytcRCSY0irQRw4I9oBcIpLe0iLQ3Z0Pdx5Q/7mIBFpaBPrO/TXsr6lnZIECXUSCKy0C/cOmK1x0QlREgistAr24rBKA4f01iqCIBFdaBPpHuyvIDmUwqFdusksREek06RHouyoZ0jeXUIYGyxeR4EqLQC8uq2B4P12yKCLBFvhAd3e27a7ULDwiEniBD/TSAzVU1obVQheRwAt8oH8UvcJlmFroIhJwgQ/04l0VAAxTC11EAi7wgb5tdyWhDGNwb12yKCLBFvhALy6rZHDvXLIzA/9WRSTNBT7lPiqrUP+5iKSFwAf6tt2VDO2rQBeR4At0oFfU1LOnso7BfdR/LiLBF1egm9n5ZrbBzDab2S1H2O5SM3Mzm5K4Ejtu+54qAJ0QFZG00Gagm1kIuB+4ACgC5plZUQvb5QPfBpYnusiO2l4eCfRCtdBFJA3E00KfBmx29y3uXgs8BcxtYbvbgZ8C1Qms76iUNLXQ1YcuIsEXT6APBj6OWS6JrmtiZqcAQ9z9pSPtyMyuN7OVZraytLS03cW21/byKrJCxoD8Hp1+LBGRZDvqk6JmlgHcA3yvrW3d/WF3n+LuUwoKCo720G3avqeKQb1yydCwuSKSBuIJ9O3AkJjlwui6RvnABOB1MysGTgMWd4cTo9vLK3VCVETSRjyBvgIYZWYjzCwbuAJY3Piku+919/7uPtzdhwPvAnPcfWWnVNwO2/dU6ZJFEUkbbQa6u9cDNwKvAOuBZ9x9rZndZmZzOrvAjqqtb2Dn/hq10EUkbWTGs5G7LwGWNFu3oJVtP3f0ZR29HXurcEctdBFJG4G9U7TpGnS10EUkTQQ20JuuQVcLXUTSRGADfXt5FWYwqJcCXUTSQ3ADfU8VA/J7aBx0EUkbgU27T/ZUcbz6z0UkjQQ20D/dV82gXjnJLkNEpMsENtA/21vNwGMV6CKSPgIZ6Pur66ioDXOcAl1E0kggA/2zfZERfI9Tl4uIpJFABvqne2sA1OUiImklmIHe2EJXoItIGglkoKvLRUTSUSAD/dO91fTKzSInK5TsUkREukwwA31ftbpbRCTtBDLQP9tXzUB1t4hImglkoH+6t5rjjtXE0CKSXgIX6HXhBkoP1KjLRUTSTuACvXR/De6oy0VE0k7gAr3xGnQNzCUi6SZwgf7Z3kig6y5REUk3gQt03SUqIukqcIH+2b4askJG357ZyS5FRKRLBS7QS/fXMCA/BzNLdikiIl0qeIF+oIb+x6h1LiLpJ65AN7PzzWyDmW02s1taeP4fzWyNma02szfNrCjxpcandH8NBfm6qUhE0k+bgW5mIeB+4AKgCJjXQmA/6e4T3X0y8DPgnkQXGi8Fuoikq3ha6NOAze6+xd1rgaeAubEbuPu+mMWegCeuxPiFG5zdFTUUHKNAF5H0kxnHNoOBj2OWS4DpzTcys28C3wWygc+3tCMzux64HmDo0KHtrbVNuytqaXDorxa6iKShhJ0Udff73f1E4Gbg1la2edjdp7j7lIKCgkQduknp/sjUc2qhi0g6iifQtwNDYpYLo+ta8xRw0VHU1GGlB6KBrha6iKSheAJ9BTDKzEaYWTZwBbA4dgMzGxWz+CVgU+JKjF9TC12BLiJpqM0+dHevN7MbgVeAELDQ3dea2W3ASndfDNxoZucCdUA5cHVnFt2axkDvry4XEUlD8ZwUxd2XAEuarVsQ8/jbCa6rQ0r315CXHaJnj7jelohIoATqTtFdB3QNuoikr0AFeul+XYMuIukrWIGuFrqIpLFgBbpu+xeRNBaYQK+pD7O3qk5XuIhI2gpMoJcdqAV0DbqIpK/ABLpu+xeRdBe8QFcLXUTSVGACfVd0HJd+mq1IRNJUYAK9rCLSh66ToiKSroIT6AdqycsOkZMVSnYpIiJJEZhA311RQ9+e6m4RkfQVmEAvq6ilnwJdRNJYYAJ9d0WtWugiktYCFug6ISoi6SsQge7ukS4XXbIoImksEIFeURumtr5BXS4iktYCEei7o+O4KNBFJJ0FItDLKqJ3iSrQRSSNBSLQd1eohS4iEohAb7ztv5+uchGRNBaIQG9qoesqFxFJY4EJ9B6ZGfTM1jguIpK+4gp0MzvfzDaY2WYzu6WF579rZuvM7G9mttTMhiW+1NaVHYjc9m9mXXlYEZFupc1AN7MQcD9wAVAEzDOzomab/QWY4u6TgOeAnyW60CPZXVGj7hYRSXvxtNCnAZvdfYu71wJPAXNjN3D319y9Mrr4LlCY2DKPTLf9i4jEF+iDgY9jlkui61rzNeD3LT1hZteb2UozW1laWhp/lW3QSIsiIgk+KWpm84EpwF0tPe/uD7v7FHefUlBQkLDjaqRFERHIjGOb7cCQmOXC6LpDmNm5wL8CZ7t7TWLKa1t1XZjK2rACXUTSXjwt9BXAKDMbYWbZwBXA4tgNzOxk4CFgjrvvTHyZrTt4U5ECXUTSW5uB7u71wI3AK8B64Bl3X2tmt5nZnOhmdwHHAM+a2WozW9zK7hJOA3OJiETE0+WCuy8BljRbtyDm8bkJrituTQNz6bJFEUlzKX+n6MGBuXTZooikt+AEep5a6CKS3lI+0PdU1pFhkJ8TV++RiEhgpX6gV9XSKzeLjAyN4yIi6S3lA728so4+6m4REUn9QN9TWUvvvKxklyEiknQBCPQ6equFLiISlEBXC11EJOUDvbyyVn3oIiKkeKDX1EcG5uqdqxa6iEhKB/reyjoAemscFxGR1A708mig91EfuohIagf6nsrIbf/qQxcRSfFAb2yh91IfuohIagd6UwtdfegiIike6FXqQxcRaZTSgV5eWUt2KIPcrFCySxERSbqUDvQ9FZG7RM000qKISGoHepXuEhURaZTSgV5eWUcv9Z+LiAApHuh7Kmt1QlREJCrFA12TW4iINErZQHd39qjLRUSkScoGemVtmNpwg1roIiJRcQW6mZ1vZhvMbLOZ3dLC82eZ2XtmVm9mlyW+zMPppiIRkUO1GehmFgLuBy4AioB5ZlbUbLNtwDXAk4kusDXlFZHb/nvlqoUuIgKQGcc204DN7r4FwMyeAuYC6xo3cPfi6HMNnVBji/aqhS4icoh4ulwGAx/HLJdE17WbmV1vZivNbGVpaWlHdtGkXANziYgcoktPirr7w+4+xd2nFBQUHNW+GofO1fRzIiIR8QT6dmBIzHJhdF1S7Yt2uRyrQBcRAeIL9BXAKDMbYWbZwBXA4s4tq217q+rokZlBjkZaFBEB4gh0d68HbgReAdYDz7j7WjO7zczmAJjZVDMrAf4eeMjM1nZm0RBpoWumIhGRg+K5ygV3XwIsabZuQczjFUS6YrrMXgW6iMghUvZO0b1Vdeo/FxGJkdKBrha6iMhBKRvo+6oV6CIisVI20PdWKtBFRGKlZKA3NDj7a+o5Nieuc7oiImkhJQN9f0097rqpSEQkVkoGeuNdoupyERE5KCUDfa9u+xcROUxKB7pa6CIiB6VkoKvLRUTkcCkZ6Gqhi4gcLqUDXX3oIiIHpWSg76uuI5Rh9MzW0LkiIo1SMtAbx3Exs2SXIiLSbaRooOsuURGR5lIy0DW5hYjI4VIy0DUWuojI4VIy0Pcp0EVEDpOSga7JLUREDpdyge7umtxCRKQFKRfoVXVh6sKuQBcRaSblAr3pLtEcBbqISKyUC/R9VfWAxnEREWku5QJdA3OJiLQsrkA3s/PNbIOZbTazW1p4voeZPR19frmZDU94pVEHB+bSnaIiIrHaDHQzCwH3AxcARcA8MytqttnXgHJ3HwncC/w00YU20ljoIiIti6eFPg3Y7O5b3L0WeAqY22ybucDj0cfPAbOsk0bOUpeLiEjL4gn0wcDHMcsl0XUtbuPu9cBeoF/zHZnZ9Wa20sxWlpaWdqjgwj65nFc0kHxd5SIicogu7Yh294eBhwGmTJniHdnHeeOP47zxxyW0LhGRIIinhb4dGBKzXBhd1+I2ZpYJ9ALKElGgiIjEJ55AXwGMMrMRZpYNXAEsbrbNYuDq6OPLgP919w61wEVEpGPa7HJx93ozuxF4BQgBC919rZndBqx098XAo8ATZrYZ2E0k9EVEpAvF1Yfu7kuAJc3WLYh5XA38fWJLExGR9ki5O0VFRKRlCnQRkYBQoIuIBIQCXUQkICxZVxeaWSnwUQdf3h/YlcByOoNqPHrdvT7o/jV29/pANbbXMHcvaOmJpAX60TCzle4+Jdl1HIlqPHrdvT7o/jV29/pANSaSulxERAJCgS4iEhCpGugPJ7uAOKjGo9fd64PuX2N3rw9UY8KkZB+6iIgcLlVb6CIi0owCXUQkIFIu0NuasDqZzGyImb1mZuvMbK2ZfTvZNbXGzEJm9hczezHZtbTEzHqb2XNm9oGZrTezGcmuKZaZfSf6f/y+mf3azHK6QU0LzWynmb0fs66vmb1qZpui//bphjXeFf1//puZ/dbMenen+mKe+56ZuZn1T0Zt8UipQI9zwupkqge+5+5FwGnAN7tZfbG+DaxPdhFH8B/Ay+4+FjiJblSrmQ0GvgVMcfcJRIaV7g5DRv8KOL/ZuluApe4+ClgaXU6mX3F4ja8CE9x9ErAR+EFXFxXjVxxeH2Y2BDgP2NbVBbVHSgU68U1YnTTuvsPd34s+3k8khJrPv5p0ZlYIfAl4JNm1tMTMegFnERlnH3evdfc9SS3qcJlAbnSGrjzgkyTXg7u/QWQ+glixE7g/DlzUlTU111KN7v6H6FzEAO8SmRUtKVr5DAHuBf4Z6NZXkaRaoMczYXW3YGbDgZOB5UkupSU/J/LN2ZDkOlozAigFHot2Cz1iZj2TXVQjd98O3E2ktbYD2Ovuf0huVa0a6O47oo8/BQYms5g4XAv8PtlFxDKzucB2d/9rsmtpS6oFekows2OA3wD/x933JbueWGZ2IbDT3Vclu5YjyAROAX7h7icDFSS/q6BJtB96LpFfPMcDPc1sfnKralt0Wshu28I0s38l0m25KNm1NDKzPOBfgAVtbdsdpFqgxzNhdVKZWRaRMF/k7s8nu54WnA7MMbNiIl1Wnzez/05uSYcpAUrcvfGvm+eIBHx3cS6w1d1L3b0OeB6YmeSaWvOZmQ0CiP67M8n1tMjMrgEuBL7SzeYjPpHIL+6/Rn9mCoH3zOy4pFbVilQL9HgmrE4aMzMi/b7r3f2eZNfTEnf/gbsXuvtwIp/f/7p7t2pduvunwMdmNia6ahawLoklNbcNOM3M8qL/57PoRidtm4mdwP1q4H+SWEuLzOx8Il2Ac9y9Mtn1xHL3Ne4+wN2HR39mSoBTot+j3U5KBXr0xEnjhNXrgWfcfW1yqzrE6cBVRFq9q6NfX0x2USnqn4BFZvY3YDLw4+SWc1D0L4fngPeANUR+jpJ+a7iZ/Rp4BxhjZiVm9jXgTmC2mW0i8pfFnd2wxv8H5AOvRn9mHuxm9aUM3fovIhIQKdVCFxGR1inQRUQCQoEuIhIQCnQRkYBQoIuIBIQCXUQkIBToIiIBoUCXwIiOof6NmOW3O+k4uWb2p+hwzphZoZldHn2cbWZvREdhFOlSCnQJkt5AU6C7e2eNr3It8Ly7h6PLs4iONRMd1nkpcHknHVukVQp0CZI7gROjt4/fZWYHIDKUcXRGnF+Z2UYzW2Rm55rZW9GZfKY17sDM5pvZn6P7eKixFd7MV4iOiWJmZwD3AJdFX3MC8EJ0G5EupVv/JTCiY9C/GJ1FCDM74O7HRNdvJjI+/Voig7z9FfgaMAf4qrtfZGbjgJ8Bl7h7nZk9ALzr7v8Vc4xsYJu7Hxez7mXgJnd/P7ocAj5194JOf9MiMdTPJ+liq7uvATCztUSmZXMzWwMMj24zCzgVWBEZRJFcDh9utj+wp9m6McAHjQvuHjazWjPLj85cJdIlFOiSLmpiHjfELDdw8OfAgMfd/UhzWlYBTRNCRycM3hszhVqjHkD1UVUs0k7qQ5cg2U9kGNaOWkqkL3wAgJn1NbNhsRu4ezkQMrPGUB9Os/lEzawfsCs6+YVIl1GgS2C4exnwlpm9b2Z3deD164BbgT9Ex2F/FRjUwqZ/AM6IPv4A6B89ZuNVNecAL7X7DYgcJZ0UFWknMzsF+I67X9XK888Dt7j7xq6tTNKdWugi7eTu7wGvtXRJY/QqmBcU5pIMaqGLiASEWugiIgGhQBcRCQgFuohIQCjQRUQCQoEuIhIQCnQRkYD4/1TZeFuU7xcjAAAAAElFTkSuQmCC\n", 396 | "text/plain": [ 397 | "
" 398 | ] 399 | }, 400 | "metadata": { 401 | "needs_background": "light" 402 | }, 403 | "output_type": "display_data" 404 | } 405 | ], 406 | "source": [ 407 | "s = sym.symbols('s')\n", 408 | "t = sym.symbols('t', real=True)\n", 409 | "Jm, Bm, Lm, Rm, Km, Vm = sym.symbols('J_m, B_m, L_m, R_m, K_m, V_m', real=True)\n", 410 | "\n", 411 | "givens = \\\n", 412 | "{\n", 413 | " Jm: 1,#1.,\n", 414 | " Bm: 1,#0.5,\n", 415 | " Lm: 1, # Inv L transform breaks if we use floats.\n", 416 | " Rm: 1,\n", 417 | " Km: 1\n", 418 | "}\n", 419 | "\n", 420 | "\n", 421 | "# L(Output)/L(Input) = I(s)/V(s)\n", 422 | "Tf = (s * Jm + Bm)/(s**2 * Jm*Lm + s*(Jm*Rm + Bm*Lm) + (Bm*Rm + Km**2))\n", 423 | "display(Tf)\n", 424 | "\n", 425 | "# L(unit step)\n", 426 | "U = 1/s\n", 427 | "\n", 428 | "\n", 429 | "# Create Callable Function for Plotting.\n", 430 | "# Sympy needs help finding the heaviside function.\n", 431 | "modules = [{'Heaviside': lambda x: np.heaviside(x, 1)}, 'numpy']\n", 432 | "# Create a callable function from given numerical values.\n", 433 | "unit_step_response = sym.inverse_laplace_transform((Tf*U).subs(givens), s, t)\n", 434 | "\n", 435 | "display(unit_step_response)\n", 436 | "lambda_f = sym.lambdify(t, unit_step_response, modules=modules)\n", 437 | "\n", 438 | "time_series = np.arange(0, 15, 0.01)\n", 439 | "f_series = np.array([lambda_f(t) for t in time_series])\n", 440 | "\n", 441 | "plt.plot(time_series, f_series, label=r\"$i(t)$ from unit step $v(t) = 1$\")\n", 442 | "plt.xlabel(\"time ($t$)\")\n", 443 | "plt.legend()\n", 444 | "plt.show()" 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "execution_count": 7, 450 | "metadata": {}, 451 | "outputs": [ 452 | { 453 | "data": { 454 | "text/latex": [ 455 | "$\\displaystyle \\frac{s + 1}{s^{2} + 2 s + 2}$" 456 | ], 457 | "text/plain": [ 458 | " s + 1 \n", 459 | "────────────\n", 460 | " 2 \n", 461 | "s + 2⋅s + 2" 462 | ] 463 | }, 464 | "metadata": {}, 465 | "output_type": "display_data" 466 | }, 467 | { 468 | "data": { 469 | "image/png": "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\n", 470 | "text/plain": [ 471 | "
" 472 | ] 473 | }, 474 | "metadata": { 475 | "needs_background": "light" 476 | }, 477 | "output_type": "display_data" 478 | } 479 | ], 480 | "source": [ 481 | "display(Tf.subs(givens))\n", 482 | "impulse_response = sym.inverse_laplace_transform(Tf.subs(givens), s, t).evalf()\n", 483 | "\n", 484 | "lambda_f = sym.lambdify(t, impulse_response, modules=modules)\n", 485 | "time_series = np.arange(0, 15, 0.05)\n", 486 | "f_series = np.array([lambda_f(t) for t in time_series])\n", 487 | "\n", 488 | "plt.plot(time_series, f_series, label=r\"$i(t)$\")\n", 489 | "plt.xlabel(\"time ($t$)\")\n", 490 | "plt.legend()\n", 491 | "plt.show()" 492 | ] 493 | } 494 | ], 495 | "metadata": { 496 | "kernelspec": { 497 | "display_name": "Python 3", 498 | "language": "python", 499 | "name": "python3" 500 | }, 501 | "language_info": { 502 | "codemirror_mode": { 503 | "name": "ipython", 504 | "version": 3 505 | }, 506 | "file_extension": ".py", 507 | "mimetype": "text/x-python", 508 | "name": "python", 509 | "nbconvert_exporter": "python", 510 | "pygments_lexer": "ipython3", 511 | "version": "3.6.12" 512 | } 513 | }, 514 | "nbformat": 4, 515 | "nbformat_minor": 4 516 | } 517 | -------------------------------------------------------------------------------- /control_theory/predictive_filtering/FOPDT.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# Environment Setup\n", 10 | "import sympy as sym\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "sym.init_printing(use_latex='mathjax')\n", 14 | "from IPython.display import display, Markdown, Math" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# First-Order Plus Dead Time System\n", 22 | "\n", 23 | "Some systems behave like a first order system after some initial delay. We can model those as a first-order-plus-dead-time system." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 4, 29 | "metadata": {}, 30 | "outputs": [ 31 | { 32 | "data": { 33 | "text/latex": [ 34 | "$\\displaystyle \\left(e^{t} - e\\right) e^{- t} \\theta\\left(t - 1\\right)$" 35 | ], 36 | "text/plain": [ 37 | "⎛ t ⎞ -t \n", 38 | "⎝ℯ - ℯ⎠⋅ℯ ⋅θ(t - 1)" 39 | ] 40 | }, 41 | "metadata": {}, 42 | "output_type": "display_data" 43 | }, 44 | { 45 | "data": { 46 | "image/png": "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\n", 47 | "text/plain": [ 48 | "
" 49 | ] 50 | }, 51 | "metadata": { 52 | "needs_background": "light" 53 | }, 54 | "output_type": "display_data" 55 | } 56 | ], 57 | "source": [ 58 | "K, T = sym.symbols('K, T', real=True)\n", 59 | "s = sym.symbols('s')\n", 60 | "td, t = sym.symbols('t_d, t', real=True, positive = True)\n", 61 | "\n", 62 | "# Laplace Transform of Unit Step\n", 63 | "H = 1/s \n", 64 | "\n", 65 | "# Laplace Transform of a FOPDT System.\n", 66 | "F = K/(T*s + 1) * sym.exp(-s*td) \n", 67 | "\n", 68 | "# Plot the Unit Step Response.\n", 69 | "# Sympy can't find Heavyside function without some help when we Lambdify a function.\n", 70 | "modules = [{'Heaviside': lambda x: np.heaviside(x, 1)}, 'numpy']\n", 71 | "f_unit_step_response = sym.inverse_laplace_transform(F*H, s, t).subs({T: 1, K: 1, td: 1})\n", 72 | "display(f_unit_step_response)\n", 73 | "lambda_f = sym.lambdify(t, f_unit_step_response, modules=modules)\n", 74 | "\n", 75 | "\n", 76 | "time_series = np.arange(0, 10, 0.1)\n", 77 | "f_series = np.array([lambda_f(t) for t in time_series])\n", 78 | "\n", 79 | "\n", 80 | "plt.plot(time_series, f_series)\n", 81 | "plt.show()" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [] 90 | } 91 | ], 92 | "metadata": { 93 | "kernelspec": { 94 | "display_name": "Python 3", 95 | "language": "python", 96 | "name": "python3" 97 | }, 98 | "language_info": { 99 | "codemirror_mode": { 100 | "name": "ipython", 101 | "version": 3 102 | }, 103 | "file_extension": ".py", 104 | "mimetype": "text/x-python", 105 | "name": "python", 106 | "nbconvert_exporter": "python", 107 | "pygments_lexer": "ipython3", 108 | "version": "3.6.12" 109 | } 110 | }, 111 | "nbformat": 4, 112 | "nbformat_minor": 4 113 | } 114 | -------------------------------------------------------------------------------- /control_theory/predictive_filtering/predictive_filtering.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# Environment Setup\n", 10 | "import sympy as sym\n", 11 | "import numpy as np\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "sym.init_printing(use_latex='mathjax')\n", 14 | "from IPython.display import display, Markdown, Math" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Predictive Filtering\n", 22 | "\n", 23 | "Lots of systems behave according to first order." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 50, 29 | "metadata": {}, 30 | "outputs": [ 31 | { 32 | "data": { 33 | "text/latex": [ 34 | "$\\displaystyle 1 - e^{- t}$" 35 | ], 36 | "text/plain": [ 37 | " -t\n", 38 | "1 - ℯ " 39 | ] 40 | }, 41 | "metadata": {}, 42 | "output_type": "display_data" 43 | }, 44 | { 45 | "data": { 46 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAej0lEQVR4nO3de3TcdZ3/8ec792uTpkmvaZu0tLSlN0psuS6swtKitiroWhRFEXZdcRU9uOjuYXfZXfG+/tbFXSreULkJqF0oF12KCEuh6Z3e09I2adMkbdPcL5OZ9++PDBhLS9J2km9m5vU4J2fm+51vZl6jzet8+Hxv5u6IiEj8Swk6gIiIxIYKXUQkQajQRUQShApdRCRBqNBFRBJEWlAfXFxc7GVlZUF9vIhIXFq3bt0Rdy852WuBFXpZWRmVlZVBfbyISFwys/2nek1TLiIiCUKFLiKSIFToIiIJQoUuIpIg+i10M/uRmdWb2WuneN3M7D/MrMrMNpvZgtjHFBGR/gxkhP4TYPHbvL4EmBb9uQX4r7OPJSIip6vfQnf3F4Bjb7PJMuB+77UGKDSzcbEKKCIiAxOL49AnANV9lmui62pP3NDMbqF3FM+kSZNi8NEiIkMjEnG6wxG6QhG6esJ09USiP2G6eyJ0R5e7eyJ0h//0MRTu/eld57xrxmjmTSyMecYhPbHI3VcAKwAqKip0IXYRiYnunggd3WHaunto7+6hvTtMW1eYjlDv8/buMJ2h3seO7jAdod7HzlDv885QmM5QpM/z3sLuDEXoij7vDkdilnd0fuawLfSDwMQ+y6XRdSIib6u7J0JLZ4jmzh6aO0I0d4Zo6eyh5c3HHlq7emjt7KGlK0RrV5jWzhBtXWFau3po6+6hrauHUPj0xoeZaSnkZKSSlZ5KdnrvY1Z6ClnpqRRmp5OVnkpmWgqZ0fWZab3Lf1zfuy4jLYWM1Ohyakrv8hs/qX/6mB59TEsxzGxQ/veMRaGvBG41s4eARUCTu79lukVEEld3T4Tj7d0ca++msS305vPj7SEa27pp6ghxvCNEU0eIpvZQdLmbzlD/o97cjFTys9LJy0ojNzONvMxUivMyycvsXc7NTCM3I5XczDRyMlLJiS7nZESX3yjuN56npZKSMjiFGrR+C93MHgSuAIrNrAb4RyAdwN3/G1gFXANUAe3AJwYrrIgMDXentauHhpYujrR2Rx+7aGjp4mhbF0dbuzna1s2xtm6OtHbR0tlzyvfKTk+lMCedguzen7LinDefF2SnMyI7nfysNEZk/fF5flbvY25GGqkJWr6Dod9Cd/fl/bzuwGdilkhEBlV3T4S65k4OHe/gcHMndc2d1DV3UdfcSX1zF3UtvetONnpOMSjKzaQ4L4Oi3AzOGz+CUbkZjMrLZGRuBkU5GYzMSacwp/f1wpze6QsZGoFdbVFEBkdzZ4iaYx3UNLZT09hBTWMHB4+3U9vUyaHjnRxp7XrL72SnpzK2IKt3Z11pIaPzMxk9IpOS/ExK8rIozs+gJC+TkTkZCTtdkQhU6CJxJhxxaps6OHC0nf3H2tl/tJ0Dx9rYf7Sd6mPtNJ8w/ZGdnsqEkdmMK8hi5tgRjCvMYnxBNmMLshhfmMWYEVnkZaYN2o46GToqdJFhqqk9xJ4jrextaGNvQ/TxSCv7jrbT3fPH6ZD0VGPiyBwmjcphwaSRTCzKpnRkDqUjs5lQmE1RbobKOkmo0EUC1twZYnddC7vqWtlV18Lu6GN9yx+nRlJTjMlFOZQX53L59BLKinMpG5XLpKIcxhdma8ehACp0kSHj7lQf62BbbTPbapvZXtvMtkPNHDze8eY22empnDM6j0unFTN9TD5TS/KYUtJb3OmpujiqvD0VusggcHcOHGtnc00TWw42san6ONsONdPS1Tu/nWIwpSSPBZNHcv2iSZw7Jp/pY/IpHZmtnY5yxlToIjHQ1B5ifXUj6/Y1sqnmOJtrmmjqCAGQkZbCrHEjeN/5E5g1fgSzxo1g+ph8sjN0OJ/Elgpd5DS5O68faaNyfyPr9zeybn8ju+tbgd657nPH5HPNnLHMmVDI3NICpo/JJyNN0yUy+FToIv14o8DX7D3Gmr1HWbP36Js7LAuy01kwqZBl88ezYPJI5pUWkpupPysJhv7liZxEXXMnL+xq4MWqI7y8548FPjo/k4umjmJR+SgWlo9kSnGe5rxl2FChiwCdoTCV+xp5YXcDL+xqYMfhFgCK8zK5eOooLpwyigunFFFenKtjumXYUqFL0mpo6eK5HXX8dls9L1Y10BmKkJGaQkXZSO5YMoM/m1bCzHH5KnCJGyp0SRruzp6GVp7dVsfvttWxofo47jChMJu/rJjI5eeWcOGUUeRk6M9C4pP+5UrC21XXwhOba3ly8yH2NLQBMLe0gNuunM5Vs8YwY6xG4ZIYVOiSkKrqW3lycy1PbjnErrpWUgwWlY/ixkvKuWrmGMYWZAUdUSTmVOiSMI60dvGbjYd4bF0N22qbMYN3lBVx17LzWDx7LKPzVeKS2FToEte6eyI8t6Oex9bXsHpHPT0RZ86EAu58zyyumTNOI3FJKip0iUtV9S384pUD/HrDQRrbQ5TkZ/LJS8u5dkEp547NDzqeSCBU6BI3QuEIz26t4+dr9vPy3qNkpKZw1awxXHdBKZdNKyZNVyOUJKdCl2GvtqmDB1+t5qFXD1Df0sWEwmy+tPhcPlQxkeK8zKDjiQwbKnQZtl472MSKF/by5JZaIu5cMb2Er100mcunj9YNHUROQoUuw4q788LuI6x4YQ8vVR0lLzONT1xcxscvLmNiUU7Q8USGNRW6DAuhcISVGw/xgz/sZcfhFsaMyOSOJTO4ftEkRmSlBx1PJC6o0CVQoXCEX60/yPdW76b6WAfnjsnnWx+cx9J543UNcZHTpEKXQPSEI/x64yG+99xu9h9tZ25pAf/03vN454zROg1f5Ayp0GVI9YQjrNx0iO89V8XrR9o4b/wI7vtYBe+aqSIXOVsqdBkS7s7zOxv46qrt7K5vZea4Eay44QKumjVGRS4SIyp0GXTbDjXz1VXbebHqCGWjcvj+Rxaw+LyxutOPSIyp0GXQ1DV38q1ndvLo+hoKstP5x/fO4iOLJmtnp8ggUaFLzHWGwvz37/dw7+/3Eo44N182hc9ccQ4FOTr8UGQwDajQzWwx8P+AVOA+d//aCa9PAn4KFEa3ucPdV8U2qsSDF3Y1cOdvXmPf0XbePWccf7d4BpNG6YQgkaHQb6GbWSpwD3AVUAOsNbOV7r6tz2b/ADzi7v9lZrOAVUDZIOSVYaq+uZN/eXI7/7PpEOXFufz8pkVcOq046FgiSWUgI/SFQJW77wUws4eAZUDfQndgRPR5AXAoliFl+ApHnJ+v2c+3ntlJVzjCbVdO568un0JWemrQ0USSzkAKfQJQ3We5Blh0wjb/BDxrZp8FcoErY5JOhrWdh1u4/dFNbK5p4rJpxdy1bDblxblBxxJJWrHaKboc+Im7f9vMLgJ+Zmaz3T3SdyMzuwW4BWDSpEkx+mgZauGI84M/7OU7z+4iPyuN/1h+Pu+dO07Hk4sEbCCFfhCY2Ge5NLqur5uAxQDu/rKZZQHFQH3fjdx9BbACoKKiws8wswRo35E2vvjLTazb38ji88byb++fzShdk1xkWBhIoa8FpplZOb1F/mHg+hO2OQC8C/iJmc0EsoCGWAaVYEUizs9f2c/dq3aQnmp89y/ns2z+eI3KRYaRfgvd3XvM7FbgGXoPSfyRu281s7uASndfCXwR+IGZ3UbvDtIb3V0j8ARR19zJFx/ZxItVR7h8eglfv3aubr4sMgwNaA49ekz5qhPW3dnn+TbgkthGk+HghV0N3PbwRtq7w3z1/XNYvnCiRuUiw5TOFJWTCkec7/5uF/+5uorpo/O55yMLOGd0XtCxRORtqNDlLeqbO/nbhzawZu8xPlRRyj8vnU12ho4rFxnuVOjyJ17cfYTPP7yBtq4w3/7gPK69oDToSCIyQCp0AXqvV/795/fwrWd3ck5JHg/evIBpY/KDjiUip0GFLnSGwvzdY5v5zcZDLJs/nrs/MIecDP3TEIk3+qtNcvXNndz8s3Vsqj7O7Vefy99cMVVHsYjEKRV6EnvtYBM3319JU0eIe2+4gKvPGxt0JBE5Cyr0JPXUllpue2QjRTkZPPrXFzNr/Ij+f0lEhjUVepJ5Y+fnN5/ZyYJJhdx7QwUl+boWi0giUKEnkUjEueuJbfzk//bxvvnj+fp1c8lM0/HlIolChZ4kQuEIt/9yE7/eeIhPXVrOV66ZSUqKdn6KJBIVehLo6A7z6V+s4/mdDXxp8bl8+nIdySKSiFToCe54ezc3/bSSDQcaufsDc1i+UDcWEUlUKvQEdripk4//6FVeP9LG9z+ygMWzxwUdSUQGkQo9QR083sGHV7zMsdZufvKJd3DxOcVBRxKRQaZCT0C1TR0sX7GG4+0hHrj5QuZNLAw6kogMgZSgA0hs1TV3snzFGhrbuvnZTYtU5iJJRIWeQOqjZd7Q0sVPPrmQ+SpzkaSiKZcE0dDSxfX3vcLh5k5++smFXDB5ZNCRRGSIaYSeAI60dvGR+9ZwsLGDH9/4Dt5RVhR0JBEJgAo9zjW1h/jofa9w4Fg7P7yxgkVTRgUdSUQCokKPY52hMJ+6fy17Glr5wccquHiqDk0USWaaQ49T4Yhz28MbWbuvkf9Yfj6XTSsJOpKIBEwj9Djk7tz1P1t56rXD/MO7Z7J03vigI4nIMKBCj0P3vrCXn768n09dWs6nLpsSdBwRGSZU6HHmVxtq+NpTO3jP3HF85ZqZQccRkWFEhR5H/rC7gdt/uZkLpxTx7Q/N0/XMReRPqNDjxPbaZj798/WcMzqPe2+o0J2GROQtVOhxoLGtm5vvryQ3M5Uff+IdFGSnBx1JRIYhHbY4zPWEI9z64Hrqm7t4+K8uZFxBdtCRRGSYUqEPc3c/tYOXqo7yjevmcv4kXZ9FRE5tQFMuZrbYzHaaWZWZ3XGKbT5kZtvMbKuZPRDbmMnp8fU1/PDF17nx4jI+VDEx6DgiMsz1O0I3s1TgHuAqoAZYa2Yr3X1bn22mAV8GLnH3RjMbPViBk8XmmuPc8fgWLpxSxN+/W4cnikj/BjJCXwhUufted+8GHgKWnbDNzcA97t4I4O71sY2ZXBpauvirn62jJC+Te65fQHqq9l2LSP8G0hQTgOo+yzXRdX1NB6ab2UtmtsbMFp/sjczsFjOrNLPKhoaGM0uc4Lp7IvzNL9bR2N7NvTdcwKi8zKAjiUiciNXQLw2YBlwBLAd+YGaFJ27k7ivcvcLdK0pKdDGpk7n7qe2s3dfI16+dy+wJBUHHEZE4MpBCPwj03SNXGl3XVw2w0t1D7v46sIvegpfT8Lttdfz4pX3ceHEZy+af+B9BIiJvbyCFvhaYZmblZpYBfBhYecI2v6Z3dI6ZFdM7BbM3djET3+GmTm5/dBOzxo3gy9fMCDqOiMShfgvd3XuAW4FngO3AI+6+1czuMrOl0c2eAY6a2TZgNXC7ux8drNCJJhxxPv/wBrp6Inzv+vN1Wr+InJEBnVjk7quAVSesu7PPcwe+EP2R0/T91VWs2XuMb143l6kleUHHEZE4pePhAla57xjf/d/dLJ03nusuKA06jojEMRV6gJraQ3zuoY1MKMzm394/GzNdDldEzpyu5RIQd+eOxzdT19zJo5++mPwsXUFRRM6ORugBeeDVAzz12mFuv/pc5k8sDDqOiCQAFXoADhxt51+f2M5l04q5WfcEFZEYUaEPsUjE+bvHNpOaYnz92rm6jZyIxIwKfYg98OoBXt57lK9cM5PxhbpZhYjEjgp9CNU0tnP3qu1ccs4oli/U9c1FJLZU6EPE3fny41tw4GsfmKtDFEUk5lToQ+SRymr+sPsIdyyZwcSinKDjiEgCUqEPgdqmDv71ie0sKi/io4smBx1HRBKUCn2QuTtfeXwLoUhER7WIyKBSoQ+yx9cfZPXOBm6/egZlxblBxxGRBKZCH0RHW7u464ltXDB5JDdeXBZ0HBFJcCr0QfSNp3fS1tXD3R+YQ6qmWkRkkKnQB8mGA408XFnNjReXMX1MftBxRCQJqNAHQTji3PmbrZTkZ/K5K3VrVREZGir0QfDw2mq2HGzi76+ZqcviisiQUaHHWGNbN994ZgcLy4tYNn980HFEJImo0GPsm8/upKWzh7uWnafT+0VkSKnQY2hzzXEefPUAH7toMjPGjgg6jogkGRV6jESiO0JH5WZy21XTg44jIklIhR4jj66rYWP1cb68ZAYjtCNURAKgQo+Bpo4QX3t6BxWTR/KBBROCjiMiSUqFHgP/9fweGtu7+ael2hEqIsFRoZ+l2qYOfvzS67xv/gRmTygIOo6IJDEV+ln699/uwh2+oB2hIhIwFfpZ2FXXwqPrarjhosm6C5GIBE6Ffha+8fROcjPS+MyfnxN0FBERFfqZWrvvGL/bXsdfXzGVotyMoOOIiKjQz4S7c/eq7YzOz+STl5QHHUdEBBhgoZvZYjPbaWZVZnbH22x3rZm5mVXELuLw8+y2OtYfOM5tV00nOyM16DgiIsAACt3MUoF7gCXALGC5mc06yXb5wOeAV2IdcjjpCUf4xtM7mFqSywcvKA06jojImwYyQl8IVLn7XnfvBh4Clp1ku38Bvg50xjDfsPPLdTXsaWjjS4tnkJaqGSsRGT4G0kgTgOo+yzXRdW8yswXARHd/8u3eyMxuMbNKM6tsaGg47bBB6+gO8++/3cWCSYX8xawxQccREfkTZz3ENLMU4DvAF/vb1t1XuHuFu1eUlJSc7UcPuftf3kd9Sxd3LJmpU/xFZNgZSKEfBCb2WS6NrntDPjAbeN7M9gEXAisTbcdoR3eYH/xhL5dNK2ZheVHQcURE3mIghb4WmGZm5WaWAXwYWPnGi+7e5O7F7l7m7mXAGmCpu1cOSuKAPPDqAY60dvO379JNn0VkeOq30N29B7gVeAbYDjzi7lvN7C4zWzrYAYeDzlCYe3+/hwunFPGOMo3ORWR4ShvIRu6+Clh1wro7T7HtFWcfa3h5pLKa+pYuvvuX84OOIiJySjrurh/dPRH++/k9XDB5JBdNHRV0HBGRU1Kh9+Ox9TUcaurks+88R0e2iMiwpkJ/G6FwhO8/X8W80gIunx5/h1mKSHJRob+N32w8RPWxDj77zmkanYvIsKdCP4VwxPn+6ipmjRvBu2aODjqOiEi/VOin8MTmQ+w90qa5cxGJGyr0k4hEnP98rorpY/K4+ryxQccRERkQFfpJPL31MLvrW7n1ndNISdHoXETigwr9BO7Ovb/fQ3lxLu+eMy7oOCIiA6ZCP8G6/Y1sqmnik5eWk6rRuYjEERX6Ce77w+sUZKdz7YIJ/W8sIjKMqND7qD7WzrPbDvORRZPIyRjQZW5ERIYNFXofP35pHylmfOyisqCjiIicNhV6VHNniEcqq3nP3HGMLcgKOo6IyGlToUc9sraa1q4ebrp0StBRRETOiAod6AlH+PFL+1hYXsSc0oKg44iInBEVOvDstjoOHu/gpkvLg44iInLGVOjAD198nUlFOVw5c0zQUUREzljSF/qGA42s29/IJy8p04lEIhLXkr7Qf/ji6+RnpfHBiolBRxEROStJXegHj3fw1GuHWb5wErmZOpFIROJbUhf6/f+3D4CPX1wWaA4RkVhI2kLvDIV5aG01i2ePZUJhdtBxRETOWtIW+qottTR1hPjooslBRxERiYmkLfQHXz1AeXEuF04pCjqKiEhMJGWh76prYe2+RpYvnKj7hYpIwkjKQn/w1QNkpKZw3QU6VFFEEkfSFXpnKMxj62q4evZYinIzgo4jIhIzSVfoq7bU0tzZw/ULJwUdRUQkppKu0B945QBTtDNURBJQUhX6rroWKvc3snzhJO0MFZGEM6BCN7PFZrbTzKrM7I6TvP4FM9tmZpvN7H/NbFge3P3AK707Q6+9oDToKCIiMddvoZtZKnAPsASYBSw3s1knbLYBqHD3ucCjwDdiHfRsdYbCPL5eO0NFJHENZIS+EKhy973u3g08BCzru4G7r3b39ujiGmDYDYGf3KydoSKS2AZS6BOA6j7LNdF1p3IT8NTJXjCzW8ys0swqGxoaBp4yBh58VTtDRSSxxXSnqJl9FKgAvnmy1919hbtXuHtFSUlJLD/6bWlnqIgkg4FcBPwg0PeUytLouj9hZlcCfw9c7u5dsYkXG9oZKiLJYCAj9LXANDMrN7MM4MPAyr4bmNn5wL3AUnevj33MM/fGztDF2hkqIgmu30J39x7gVuAZYDvwiLtvNbO7zGxpdLNvAnnAL81so5mtPMXbDbn/3V5Pc2cPH9It5kQkwQ3ovmvuvgpYdcK6O/s8vzLGuWLmVxtqGDMik4umjgo6iojIoEroM0WPtnbx/M4Gls2fQGqKdoaKSGJL6EJ/ckstPRHn/ee/3VGWIiKJIaEL/fH1B5kxNp+Z40YEHUVEZNAlbKHvbWhlY/VxPrBAo3MRSQ4JW+i/3ngIM1g6T4UuIskhIQvd3fn1hoNcMrWYsQVZQccRERkSCVno6/Y3cuBYu3aGikhSSchCf3zDQbLSU7h69tigo4iIDJmEK/SunjBPbq7l6vPGkpc5oPOmREQSQsIV+uodDTR1hDTdIiJJJ+EK/VcbaijOy+TSc4qDjiIiMqQSqtCPt3ezekcDS+eNJy01ob6aiEi/Eqr1ntxSS3c4opOJRCQpJVSh/2r9QaaNzuO88TrVX0SST8IUevWxdir3N/L+BRN0mzkRSUoJU+hPbqkF4L1zxwecREQkGAlT6E9tqWVeaQETi3KCjiIiEoiEKPSaxnY21TSxZM64oKOIiAQmIQr96dcOA7BEp/qLSBJLiEJftaWW88aPYPKo3KCjiIgEJu4Lvbapg/UHjmt0LiJJL+4L/c3pFs2fi0iSi/tCf+q1w5w7Jp+pJXlBRxERCVRcF3p9Sydr9x1jyRxNt4iIxHWhP7O1Dne4RtMtIiLxXehPballakku00ZrukVEJG4L/WhrF2v2HuWaOeN07RYREeK40J/dVkfEYclsTbeIiEAcF/qqLbWUjcph5rj8oKOIiAwLcVnojW3d/N+eoyzRdIuIyJvistB/u72OcMR1dqiISB8DKnQzW2xmO82syszuOMnrmWb2cPT1V8ysLOZJ+3hqSy0TCrOZM6FgMD9GRCSu9FvoZpYK3AMsAWYBy81s1gmb3QQ0uvs5wL8DX4910Dc0dYR4seoI18wZq+kWEZE+BjJCXwhUufted+8GHgKWnbDNMuCn0eePAu+yQWrb53bUEQq7rt0iInKCgRT6BKC6z3JNdN1Jt3H3HqAJGHXiG5nZLWZWaWaVDQ0NZxQ4PzOdq2aNYX5p4Rn9vohIokobyg9z9xXACoCKigo/k/e4ctYYrpw1Jqa5REQSwUBG6AeBiX2WS6PrTrqNmaUBBcDRWAQUEZGBGUihrwWmmVm5mWUAHwZWnrDNSuDj0efXAc+5+xmNwEVE5Mz0O+Xi7j1mdivwDJAK/Mjdt5rZXUClu68Efgj8zMyqgGP0lr6IiAyhAc2hu/sqYNUJ6+7s87wT+GBso4mIyOmIyzNFRUTkrVToIiIJQoUuIpIgVOgiIgnCgjq60MwagP1n+OvFwJEYxokXyfq9IXm/u753chnI957s7iUneyGwQj8bZlbp7hVB5xhqyfq9IXm/u753cjnb760pFxGRBKFCFxFJEPFa6CuCDhCQZP3ekLzfXd87uZzV947LOXQREXmreB2hi4jICVToIiIJIu4Kvb8bViciM/uRmdWb2WtBZxlKZjbRzFab2TYz22pmnws601Awsywze9XMNkW/9z8HnWkomVmqmW0wsyeCzjJUzGyfmW0xs41mVnnG7xNPc+jRG1bvAq6i91Z4a4Hl7r4t0GCDzMz+DGgF7nf32UHnGSpmNg4Y5+7rzSwfWAe8Lwn+/zYg191bzSwdeBH4nLuvCTjakDCzLwAVwAh3f0/QeYaCme0DKtz9rE6mircR+kBuWJ1w3P0Feq8zn1Tcvdbd10eftwDbeev9bBOO92qNLqZHf+Jn5HUWzKwUeDdwX9BZ4lG8FfpAblgtCcjMyoDzgVcCjjIkotMOG4F64LfunhTfG/gu8CUgEnCOoebAs2a2zsxuOdM3ibdClyRkZnnAY8Dn3b056DxDwd3D7j6f3nv4LjSzhJ9qM7P3APXuvi7oLAG41N0XAEuAz0SnWU9bvBX6QG5YLQkkOof8GPALd3886DxDzd2PA6uBxQFHGQqXAEuj88kPAe80s58HG2louPvB6GM98Ct6p5dPW7wV+kBuWC0JIrpz8IfAdnf/TtB5hoqZlZhZYfR5Nr0HAewINNQQcPcvu3upu5fR+7f9nLt/NOBYg87McqM7/TGzXOAvgDM6oi2uCt3de4A3bli9HXjE3bcGm2rwmdmDwMvAuWZWY2Y3BZ1piFwC3EDvSG1j9OeaoEMNgXHAajPbTO8g5rfunjSH8CWhMcCLZrYJeBV40t2fPpM3iqvDFkVE5NTiaoQuIiKnpkIXEUkQKnQRkQShQhcRSRAqdBGRBKFCFxFJECp0EZEE8f8B26wZ10XzNSEAAAAASUVORK5CYII=\n", 47 | "text/plain": [ 48 | "
" 49 | ] 50 | }, 51 | "metadata": { 52 | "needs_background": "light" 53 | }, 54 | "output_type": "display_data" 55 | } 56 | ], 57 | "source": [ 58 | "K, T = sym.symbols('K, T', real=True)\n", 59 | "s = sym.symbols('s')\n", 60 | "td, t = sym.symbols('t_d, t', real=True, positive = True)\n", 61 | "\n", 62 | "# Laplace Transform of Unit Step\n", 63 | "H = 1/s \n", 64 | "\n", 65 | "# Laplace Transform of a First-Order System\n", 66 | "F = K/(T*s + 1)\n", 67 | "\n", 68 | "\n", 69 | "# Plot the Unit Step Response.\n", 70 | "# Sympy can't find Heavyside function without some help when we Lambdify a function.\n", 71 | "modules = [{'Heaviside': lambda x: np.heaviside(x, 1)}, 'numpy']\n", 72 | "f_unit_step_response = sym.inverse_laplace_transform(F*H, s, t).subs({T: 1, K: 1, td: 1})\n", 73 | "display(f_unit_step_response)\n", 74 | "lambda_f = sym.lambdify(t, f_unit_step_response, modules=modules)\n", 75 | "\n", 76 | "\n", 77 | "time_series = np.arange(0, 5, 0.1)\n", 78 | "f_series = np.array([lambda_f(t) for t in time_series])\n", 79 | "\n", 80 | "\n", 81 | "plt.plot(time_series, f_series)\n", 82 | "plt.show()" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "If we know the unit step response of the system, we actually know quite a bit about the system.\n", 90 | "\n", 91 | "In fact, given any moment in this curve, we can use the time constant to predict where the curve will settle." 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 54, 97 | "metadata": {}, 98 | "outputs": [ 99 | { 100 | "data": { 101 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAnPElEQVR4nO3deXhV1b3/8ffKPJIQQiBAQgKEWUSNCIKKggqiYrX1J7W1tlrstd6qHW31WmsfO9y23t7B25a2tmqtXmtQUVGsVYsjCoqSEMAwzwQSyDycnO/vj32QiGACnJydnHxez5PnnD1kn+8R+bhce+21nJkhIiI9X4zfBYiISHgo0EVEooQCXUQkSijQRUSihAJdRCRKxPn1wdnZ2VZQUODXx4uI9EgrVqzYa2b9j3TMt0AvKChg+fLlfn28iEiP5JzbfLRj6nIREYkSCnQRkSihQBcRiRIKdBGRKKFAFxGJEgp0EZEooUAXEYkSCnQRkUjZvxVe/y/YuLRLLu/bg0UiIr1C7W5Y/SSUlsDWZd6+abdC4dlh/ygFuohIuNXvg/JFULYQNr0GFoQB42HGnTDuM5A1rEs+VoEuIhIOTQdgzbNeS3zDKxAMQL8RcPZ3Yfzl0H9Ul5egQBcROV4t9bD2OShdCBV/h7YWyMyHKTd5IT5wAjgXsXIU6CIix6K1yQvv0hJY+zwEGiE9F06/HsZfAYNPi2iIt6dAFxHpSKDF60YpLfG6VVpqIaUfTPy81xLPPxNi/B802GGgO+fuBy4G9pjZ+CMcvxr4HuCAWuBfzOz9cBcqIhJRwTbY9KoX4qsXQdN+SMqAcXO9lnjB2RDbvdrEnanmz8D/AA8e5fhG4Bwzq3bOzQYWAGeEpzwRkQgKBr2hhaUlsPopqN8DCWkw6iKvJT58BsQl+F3lUXUY6Ga21DlX8CnH32i3+RYwJAx1iYhEhhnseNe7sVn2BNRsh7gkGHmh1xIvugDik/2uslPC/f8L1wHPHe2gc24+MB8gPz8/zB8tItJJZrBntdcSLy2B6k0QEw8jZsDMu2DUbEhM97vKYxa2QHfOnYsX6NOOdo6ZLcDrkqG4uNjC9dkiIp2y90OvJV5aAnvXgov1ntg869sw5mJI7ut3hSckLIHunJsA/AGYbWb7wnFNEZGwqN7sPbFZWgK7VgEOhp4JZ8yHMXMh7YjrLfdIJxzozrl8YCHwRTNbd+IliYicoJodUPakF+LbQ4vRDy6GC38K4y6DPoP8rK7LdGbY4iPAdCDbObcN+CEQD2BmvwXuBPoB/+u8wfQBMyvuqoJFRI6orhLKn/K6VDa/ARgMOMnrEx/3Gehb4HOBXa8zo1zmdXD8euD6sFUkItJZjdVQ/ozXpbLhn2BtkD0Kpn/fG2aYXeR3hRHVvUbFi4h0pLnWe+S+tAQqXoRgq9f6nnaLN8wwZ6xvj977TYEuIt1fayN8+IIX4uuWQKAJ+gyGM27wQnzQKb02xNtToItI9xRohvUveX3iaxdDSx2k9odTr/FCfMikbjF/SneiQBeR7qMtAJuWei3x8qe9OcaT+3oBPv4KKJgGMbF+V9ltKdBFxF/BIGx589D8KQ17ISHde9Bn3OUwbHq3nj+lO1Ggi0jkmcH2FV6Ilz0BtTshLhlGzfJCvOgCiE/yu8oeR4EuIpFh5j2pWVriDTPcvwViE7zwHvcZGDkLEtP8rrJHU6CLSNeqXHtoEqx9Fd78KcPP9caKj57jzTEuYaFAF5Hwq9pwaDra3aWA825oTrkJxlwKqf38rjAqKdBFJDwObPcCvLTEm18cvKGFs37mdamkD/S3vl5AgS4ix69ujzcypbTEG6kCkDsRzr/bC/FMrXsQSQp0ETk2DVXeGPHSEm/NTQt6j9ufe4c3f0q/4X5X2Gsp0EWkY0013tOapQth/T8gGICsYXDWt7xhhgPG+l2hoEAXkaNpaYAPl4TmT3kB2pohIw8m3+g9tZl7suZP6WYU6CJySKAZKv7hhfja56C1HtIGQPGXvRAfXKz5U7oxBbpIb9fW6s0lXrbQm1u8+QAkZ8GEz8H4z3rLtWn+lB5BgS7SGwXbYPPrXp/46qegsQoS+8CYS0Lzp5wDsfF+VynHSIEu0lsEg7DtHa8lXvYE1O2G+BQYNdvrThk+Q/On9HAKdJFoZgY73z80CdaBrRCbCEXneyE+8kJISPW7SgkTBbpINNpTfmj+lKoNEBPntcDPuwNGXQRJffyuULqAAl0kWuxbH5o/ZSHsWQ0uBgrPhqm3eH3jKVl+VyhdTIEu0pPt33po/pSdK719+VPgol/C2LmQluNreRJZCnSRnqZ2N6x+0gvxrcu8fYNOhQvugXGXQcYQP6sTH3UY6M65+4GLgT1mNv4Ixx3wn8BFQANwrZm9G+5CRXqTA08/zZ7/+DWBnTuJy80l58brySho9LpUNr0GGAwYDzPu9CbByhrmd8nSDXSmhf5n4H+AB49yfDZQFPo5A/hN6FVEjsOBp59m57/diTU1ARDYsYOdP7wLTj9AxmmD4ZzvemPFc0b7W6h0Ox0Gupktdc4VfMopc4EHzcyAt5xzmc65XDPbGa4i2/v52z9nTdWarri0iP+Cbdxwz3tkNAU+ttvaYihfk8PvrpoAzR/Cuz/3qUAJh9FZo/nepO+F/brh6EMfDGxtt70ttO8Tge6cmw/MB8jP1zzJIoA3/WxjNdRXQkMVffY74JOTXvXZ3xr52qKEAWZGMAhBs9BPaF+714PHzLwh/EEzjIPn0O6YEQxd89B5HDpmYBy6zqH33u811VfDpPB/z4jeFDWzBcACgOLiYjuea3TFf9VEIi7QAhte8W5srnkWWmohJRvGzuXDnGUE9lR94lfiBw3iT7P+FPlau5iZ0RwIUt8coKGljfqWAPXNbTS0eNsHXxtb2rzXVu99U+uh7abQj/c++NF2U2uQ5kAbrW3HFTefkBAbQ3ysIz4uJvTe206OiyEuJia03xEXE0NcrCMh1nuNi40hPib0Gus4Z2TXjD4KR6BvB/LabQ8J7ROR9oJt3oIQpSXeAhGN1d4CyePmek9tFpwNsXHk2Mf70AFcUhI5t97iX+1HEWgLUtMUoKaxlZqmVmoaA9Q2tVLbFPC2m7ztuqYA9S0BapsC1DUHqDv4GgrxtmDnAzc+1pEcH0tyQizJ8bEkhX6S42PpnxZHckIsSXGxJMbHkhQf4x2PiyUxPobEOG87MS6GxDjvNSEu5qPXhHb742MP7TsY5K6bTxccjkBfBNzknHsU72boga7qPxfpcYJBb2hh2UIoexLq90BCmrfa/bjLYfh5EJfwsV/JuOQSgI+Pcrn1lo/2dwUzo6YxQFVDC1X1zVTVt1Jd38L+xhaqG1rZ39DC/oZWqkOvtU0BDjS2Utcc6PDa6YlxpCXFkZYYR2piHOlJcQzsk0Rq4sF9saQkeO9TEmK919D75PhYUg++D23Hx2r63qPpzLDFR4DpQLZzbhvwQyAewMx+CyzGG7JYgTds8ctdVaxIj2AGO947NH9KzXaIS/LmTRl/BRRdAPHJn3qJjEsuOeEAbwsa++qb2VPTTGVtM5V1zeyta2ZfXQt7273fV99CdX0LgaO0kuNiHJkpCfRNiSczJZ4hfVPISI4nIzmePslxh94nxdMnOZ70JC+0+yTHk5YQR0xM927VRpPOjHKZ18FxA74etopEeiIz73H70hJvrHj1RoiJhxEzYeaPYNQsSEwP28fVNrWyu6aJnQe8n12h1901TeypbWJPTTP76luO2JWRkhBLdloi2WkJ5GWlMDEvk6zUhE/89E1JIDMlnrTEuG7f1SAePSkqciL2VoRa4guhcg24WG/+lLO/7XWrJPc95kuaGfvqW9hS1cD26ka2729ke3UjO/Yfel97hK6OfqkJDOiTRE6fRMbm9iEnPYkBfRLpn55E//REctIT6ZeWQEqC/tpHK/3Jihyr6s2H5k/Z9QHgYOhUmPMrGDMX0vp3eIm2oLG9upGN++rZtLeeLVUNbKlqYGvotaGl7WPnZyTHMygzmSF9U5g8rB+5GUkMzEgiNyOZ3AwvxBPjtKpQb6dAF+mMmh3eTc2yhd4iEQCDT4MLf+rNn9Jn0BF/7UBDKxWVtXy4u471lXVs3NvAxr11bK1qpKUt+NF5yfGx5GelkJeVwpnDs8nPSiYvK4UhfVMYlJlEepJWD5KOKdBFjqauEsqf8vrEN78BGAw8CWbe5c2f0rfgo1Nrm1pZu6uW8l21fLjbC/CKyjoqa5s/OichLobCfqmMyEnj/LEDKcxOoTA7jYLsFPqnJaqfWk6YAl2kvcZqb6Hk0hLYuBSsDbJHwvTvw/jLsX4j2FrVyKqtByh/ey1rdtWwZlct26obP7pEWmIcI3LSOGdkf4py0hiRk0ZRTjqD+yYTqxEf0oUU6CLNtbD2Oa8lXvEiBFuhbwE29WZ2DJnNiqbBlO2oYdUT+yjdvoGa0DwrsTGOYdmpTMzLZN6kfEYPTGd0bh8GZSSptS2+UKBL79TaCOuWeH3i65ZAoIlg+iB2jLqG1xLPZklVLivfOEB1QyVQSUJsDKNz05kzYRAnDc5g/OA+jByQTlK8bkRK96FAl94j0ALrX/K6U9YuhpY6mhL78V7GHB5rOp2n9g4hWOk9hViU08T5YwcwMa8vJ+dlUJSTTkKcnlCU7k2BLtGtLQCblkJpCcHVTxPTfICGmHRedFN4pGUSy5rGkNKUwGlD+3LLqX05JT+TCUMyyUjWqBLpeRToEn2CQdjyJk0r/4Yrf4rE5irqSeb5ttN4pm0KZUmncmrBAM4vzOL2wizG5PbRzUqJCgp0iQ5mtG1dzt63/kpKxdOkt1RilsCLwVP5e8w0mgtmMHlkLj8Ykc2InDTdtJSopECXnsuM2s3vsev1h8na9Az9WneRaXEstYmU9f0KCWPncMboPH41JJM4zdAnvYACXXqcvRs/YPtrfyF787MMDmwj2WJ4y01gS+6XyTz1MqaOG875KeoDl95HgS49wq5N5Wx99S/03/wsBYGNZJnj/bjxrCq8moGTr2RK0XCmqR9cejkFunRbVTs3UvHyQ2RueJqRgXUMBMpix/DKsG+TP20epwwb4XeJIt2KAl26lcaqnXz4yl9IXPsko5pLmQRUxA7njWG3kHfW5xlXOMrvEkW6LQW6+M4aqtj46qO0fvA4I+reZYIz1rt8luZ9jbyzrmbEyAmoLS7SMQW6+KOphroPFlG17BEG7XuTYbSx2QbySs41ZE++ipNOmcJw9YmLHBMFukROSwO27nmq3n6UPltfIs1a2W/ZPJP6GdJO+39MnXYeQxP1r6TI8dLfHulagWaoeJG2Dx4nuPY54tsaabNMHnMzaRx5GWedO5vLcjP8rlIkKijQJfzaWmHDP735U9Y8Q0xzDTWkszhwJh9kzuD06RdzxclDNFOhSJgp0CU8gm2w+XVvJsPVi6CxisaYVBYHilkUmEzKqPP40llFfL4wS4/di3SRTgW6c24W8J9ALPAHM/vZYcfzgQeAzNA5t5nZ4vCWKt1OMOitr1m20Fs0uW43bXHJLE+czB9aTmF53CnMLR7O3VMLGNov1e9qRaJeh4HunIsF7gPOB7YB7zjnFpnZ6nan3QE8Zma/cc6NBRYDBV1Qr/jNDHa+77XEy56AA1shNpGqwdN5OKGY/90xnMRgOtfNKOSXZxZoGlqRCOpMC30SUGFmGwCcc48Cc4H2gW5An9D7DGBHOIuUbmBPuRfipSVQtQFi4mD4DNaNu5l7Kgr557pmstMSuGX2ML4weSipGq0iEnGd+Vs3GNjabnsbcMZh59wFvOCc+1cgFZh5pAs55+YD8wHy8/OPtVaJtH3rvXU2yxbCntXgYqDwbJh6C2UZ5/CTV3bx+kv7GNjH8cNLxjJvUr5udIr4KFzNqHnAn83sV865KcBDzrnxZhZsf5KZLQAWABQXF1uYPlvCaf9WryultAR2rvT25Z8JF/0Sxs5lU1Mqv3xhLc98UEbflHjuvHgsV0/OJzFOQS7it84E+nYgr932kNC+9q4DZgGY2ZvOuSQgG9gTjiKli9XuhtVPeiG+dZm3b/BpcME9MO4yyBhCZW0z//Xihzzy9hbiY2P4xnkj+OrZw0hPUh+5SHfRmUB/ByhyzhXiBflVwOcPO2cLMAP4s3NuDJAEVIazUAmz+n1QvsgL8U2vAQYDxsN5/wbjr4CsQgBaAkH++Mp6/vulD2kJBLlqUh7fmFFETnqSv/WLyCd0GOhmFnDO3QQswRuSeL+ZlTnn7gaWm9ki4FvA751zt+LdIL3WzNSl0t00HYA1z3ohvuEVCAag3wg453sw/nLo//GZDP+5rpIfLSpjw956zh87gB9cNIbCbA0/FOmuOtWHHhpTvviwfXe2e78amBre0iQsWuph7XPezc2Kv0NbC2Tmw5SbvJb4wJPgsAd9tlY18ONnVvPC6t0UZqfy5y+fzvRROT59ARHpLI0ti0atTV54l5bA2uch0AjpuXD69V6IDz7tEyEO0NTaxm//uZ7fvLKeGOf47qxRXDetUDc8RXoIBXq0CLR43SilJV63SkstpPSDifNg/GchfwrEHH2h5BWbq/jO4x+wobKeiyfkcvucMeRmJEeufhE5YQr0nizYBpte9UK8/GlorIakDBg312uJF5wNsZ/+R9zQEuCXS9bxpzc2MigjmQe/MomzR/aP0BcQkXBSoPc0waA3tLC0BFY/BfV7ICENRl3khfjw8yAuoVOXemP9Xm4rWcWWqgaumTKU784aTZqe8BTpsfS3tycwgx3vhp7afAJqtkNcEoy80AvxogsgvvPdI7VNrfzsuTU8vGwLBf1S+L/5kzljWL8u/AIiEgkK9O7KzHvc/uD8KdWbICYeRsyEmT+CUbMgMf2YL/velmpufnQl26ob+OpZhXzz/FEkJ+imp0g0UKB3N3s/PDR/SuUacLEw7Bw469sw5mJI7ntclw0Gjd8uXc+9L6xjQJ8kHrthCsUFWWEuXkT8pEDvDqo3ewFeWgK7VgEOhp4Jc34FY+ZC2ondpNxd08Q3H1vJ6xX7mHNSLj+5/CRNaysShRTofqnZAWVPeiG+fbm3b3AxXPhTb/6UPoPC8jH/KN/Ndx7/gMaWNn5+xUlcWZynFYNEopQCPZLqKqH8Ka9LZfMbgHlPas68C8Z9BvoWhO2jWtuC/Oy5NfzxtY2Mye3Df8+byIicY+9zF5GeQ4He1RqrofwZryW+cSlYG2SPgunf9+ZPyS4K+0fuq2vmxoffZdnGKr40ZSjfv2iM5ikX6QUU6F2hudZ75L60BCpehGAr9C2Eabd4wwxzxh7x0ftwKN1+gBseWsHeumbuvfJkLj91SJd8joh0Pwr0cGlthA9f8EJ83RIINEGfwXDGDV5LfNCpXRbiBz3x3jZuK1lFv9QEHv/amZw0JKNLP09EuhcF+okItMD6l0KTYC2GljpI7Q+nXuO1xIdM+tT5U8JWRluQn4b6y88ozOK+q08lOy2xyz9XRLoXBfqxagvApqWH5k9pOuCNDR9/uTcJVsE0iIlcf/WBxlZufHgFr1fs49ozC7h9zhjiY7v+PyIi0v0o0DsjGIQtb3pjxcuehIa9kJDuPegz7nIYNr3T86eE0479jVz7p7fZuLeeX3x2Ap8rzuv4l0QkainQj8YMtq84NH9K7Q6IS/YeuR9/BYw4H+L9W4Ztza4arr3/HeqbAzzw5UmcOSLbt1pEpHtQoLdn5j2pefCpzf1bIDbBC+/xP4aRsyAxze8qeWP9Xm54cAWpiXE89rUpjMnt43dJItINKNABKteGJsFaCPs+9OZPGX4unHMbjJ4DyZl+V/iRp1Zu59t/ez+0NNwkBmVqEQoR8fTeQK/acKg7ZXcp4LwbmlNu9OZPSe1e08maGb9/dQM/WbyGMwqzWHBNseZjEZGP6V2BfmC7F+ClJd784uANLZz1M+/R+/SB/tZ3FGbGL19Yy30vr2fOhFzuvfJkrfMpIp8Q/YFet8db2ae0xBupApA7Ec6/2wvxzHxfy+uImfGz59bwu6UbmDcpn3suG09MjCbXEpFP6lSgO+dmAf8JxAJ/MLOfHeGcK4G7AAPeN7PPh7HOY9NQ5Y0RLy3x1ty0IPQfA+fe4Y0X7zfct9KOhZnx42fKuf/1jVwzZSh3XTJOYS4iR9VhoDvnYoH7gPOBbcA7zrlFZra63TlFwPeBqWZW7ZzL6aqCj6qpxntas3QhrP8HBAOQNQzO+pY3VnzA2IiXdCKCQeOup8t48M3NfGVqIf928RhNeysin6ozLfRJQIWZbQBwzj0KzAVWtzvnq8B9ZlYNYGZ7wl3oEbU0wLrnvWGG616AtmbIyIPJN3pjxXNP7vL5U7pCMGjc/mQpj7y9hRvOHsZts0crzEWkQ50J9MHA1nbb24AzDjtnJIBz7nW8bpm7zOz5sFR4uECzN4Nh6UJY+xy01kPaACj+stcSz5vUI0P8oLagcVvJB/xtxTa+fu5wvn3BKIW5iHRKuG6KxgFFwHRgCLDUOXeSme1vf5Jzbj4wHyA//zhvRq76Gzz1dUjOgglXei3xoWdGdP6UrmJm3PHkKv62Yhu3zCzi5hlFCnMR6bTOBPp2oP0kIUNC+9rbBiwzs1Zgo3NuHV7Av9P+JDNbACwAKC4utuOqePTFkDbQWzg5NrrGYf/7krU88vZWbjp3BLfMHOl3OSLSw3RmWr53gCLnXKFzLgG4Clh02DlP4rXOcc5l43XBbAhfme0kZ0LRzKgL8wVL1/ObV9Zz9Rn5fOsChbmIHLsOA93MAsBNwBKgHHjMzMqcc3c75y4NnbYE2OecWw28DHzHzPZ1VdHR5rF3tvKTxWu4eEIud88dr24WETkuzuz4ej5OVHFxsS1fvtyXz+5Oni/dxY0Pr2DqiGz++KXTSYjTXOYicnTOuRVmVnykY0oPH71RsZdvPPIeJ+dl8rsvnqYwF5ETogTxyQfb9vPVB5dTmJ3Kn649nZSE6J+FQUS6lgLdBzv2N3LdA8vpm5rAg9dNIjMl8qsdiUj0UbMwwhpaAlz/wHKaWtr46/VnMKCPf6seiUh0UaBHUDBo3Pp/K1mzq4Y/Xns6RQPS/S5JRKKIulwi6Fd/X8uSst3cMWcs546K/PxlIhLdFOgR8sR727jv5fXMm5TPl6cW+F2OiEQhBXoErNhczfceX8XkYVncPXecHhwSkS6hQO9i26obuOGh5QzKTOI3V59GfKz+kYtI19BN0S7U1NrGVx9cQXMgyKPzT6dvqoYnikjXUaB3oR89XUb5zhr+dO3pjMhJ87scEYly+v//LrLw3W088vZWvn7ucM4drREtItL1FOhd4MPdtdz+RClnFGZxq+Y1F5EIUaCHWUNLgBsffpfUxFj+a94pxOkmqIhEiPrQw8jMuOOJUioq6/jLdXqsX0QiS83HMHps+VYWvredm2cUMXVEtt/liEgvo0APk9U7arjzqTKmjcjmX88r8rscEemFFOhhUN8c4Ot/fZeM5Hh+fdVEYmP0JKiIRJ760MPgJ4vL2bSvnr9eP5nstES/yxGRXkot9BP0z3WVPLxsC9dNLWTK8H5+lyMivZgC/QQcaGjlu4+/z4icNL594Si/yxGRXk6BfgJ+uKiUvXUt3HvlySTFx/pdjoj0cgr04/Tcqp08uXIH/3reCCYMyfS7HBGRzgW6c26Wc26tc67COXfbp5x3hXPOnHPF4Sux+9lT28QPnljFSYMz+Pq5I/wuR0QE6ESgO+digfuA2cBYYJ5zbuwRzksHbgaWhbvI7sTM+MHCVdS3tHHvlSdrfnMR6TY6k0aTgAoz22BmLcCjwNwjnPdj4OdAUxjr63b+tmIbL5bv4bsXjtIizyLSrXQm0AcDW9ttbwvt+4hz7lQgz8ye/bQLOefmO+eWO+eWV1ZWHnOxftu+v5G7n17NpMIsvjK10O9yREQ+5oT7C5xzMcC9wLc6OtfMFphZsZkV9+/f/0Q/OuJ++FQZbUHjV587mRg9DSoi3UxnAn07kNdue0ho30HpwHjgFefcJmAysCjaboy+ULaLF8t3c8vMIvKyUvwuR0TkEzoT6O8ARc65QudcAnAVsOjgQTM7YGbZZlZgZgXAW8ClZra8Syr2QX1zgLsWlTF6YDpfmaauFhHpnjoMdDMLADcBS4By4DEzK3PO3e2cu7SrC+wOfv3iOnYcaOKez4zXqBYR6bY6NTmXmS0GFh+2786jnDv9xMvqPlbvqOH+1zcxb1Iepw3N8rscEZGjUnPzU7QFjR88sYrM5Hi+N2u03+WIiHwqBfqneOTtLazcup87Lh5DZkqC3+WIiHwqBfpR7Klt4ufPr+HM4f24bOLgjn9BRMRnCvSjuOfZcppbg/z4svE4pzHnItL9KdCP4PWKvTy1cgdfmz6c4f3T/C5HRKRTFOiHCbQF+dHTZeRnpXDj9OF+lyMi0mkK9MM8tnwb63bX8f3Zo7VohYj0KAr0duqaA9z797WcXtCXWeMH+l2OiMgxUaC389tX1rO3roXb54zVjVAR6XEU6CE79jfy+1c3MHfiICbmZfpdjojIMVOgh/xiyVoM+M6Fo/wuRUTkuCjQgfe37ueJ97Zz/bRChvTV1Lgi0jP1+kA3M+55tpzstAT+RcMURaQH6/WBvqRsF29vquLW80eSnhTvdzkiIsetVwd6SyDIT59bQ1FOGv+vOK/jXxAR6cZ6daA/9NZmNu9r4PY5Y4jTwhUi0sP12hSrbw5w38sVTBuRzfRROX6XIyJywnptoD/w5iaq6lv45gUj/S5FRCQsemWg1za1smDpBs4d1Z9T8/v6XY6ISFj0ykD/8+ub2N/Qyq3nq3UuItGj1wX6gcZWfv/qBmaOGcCEIZl+lyMiEja9LtDvf20jNU0BbplZ5HcpIiJh1alAd87Ncs6tdc5VOOduO8LxbzrnVjvnPnDO/cM5NzT8pZ64Aw2t3P/aRi4cN4DxgzP8LkdEJKw6DHTnXCxwHzAbGAvMc86NPey094BiM5sAPA78e7gLDYc/vLaB2uYAt8xU37mIRJ/OtNAnARVmtsHMWoBHgbntTzCzl82sIbT5FjAkvGWeuOr6Fu5/bSNzTsplTG4fv8sREQm7zgT6YGBru+1toX1Hcx3w3JEOOOfmO+eWO+eWV1ZWdr7KMFjw6gYaWtu4WX3nIhKlwnpT1Dn3BaAY+MWRjpvZAjMrNrPi/v37h/OjP9XeumYeeGMTl0wYxMgB6RH7XBGRSIrrxDnbgfYzVw0J7fsY59xM4HbgHDNrDk954bFg6QaaWtv4xgy1zkUkenWmhf4OUOScK3TOJQBXAYvan+CcOwX4HXCpme0Jf5nHr7q+hYfe3MylJw9iRE6a3+WIiHSZDgPdzALATcASoBx4zMzKnHN3O+cuDZ32CyAN+JtzbqVzbtFRLhdxD721mcbWNv5l+gi/SxER6VKd6XLBzBYDiw/bd2e79zPDXFdYNLW28cAbmzh3VH9GDVTfuYhEt6h+UvTxFdvYV9/C/LO1tJyIRL+oDfS2oPGHVzdw8pAMJg/L8rscEZEuF7WB/kLZLjbta2D+2cNxzvldjohIl4vKQDczfrd0A/lZKcwaP9DvckREIiIqA/2dTdWs3Lqfr55VSGyMWuci0jtEZaD/7p/ryUpN4LOn5XV8sohIlIi6QP9wdy3/WLOHa6YMJTkh1u9yREQiJuoCfcHSDSTFx3DNlAK/SxERiaioCvTdNU08uXI7VxbnkZWa4Hc5IiIRFVWB/qfXN9EWNK6fNszvUkREIi5qAr2uOcDDb21m9km55PdL8bscEZGIi5pAf+LdbdQ2B7h+WqHfpYiI+CIqAt3MeOitzZw0OIOJeZl+lyMi4ouoCPS3N1axbncdX5w8VI/5i0ivFRWB/uBbm+mTFMclJw/yuxQREd/0+EDfU9PEktJdfK44Tw8SiUiv1uMD/dF3thIIGl+YPNTvUkREfNWjAz3QFuSvy7ZwVlE2hdmpfpcjIuKrHh3oL5bvZldNE19U61xEpGcH+kNvbWZQRhLnjc7xuxQREd/12ECv2FPH6xX7uHryUOJie+zXEBEJmx6bhA8v20x8rOPKYs15LiICPTTQG1oCPL5iG7PH59I/PdHvckREuoVOBbpzbpZzbq1zrsI5d9sRjic65/4vdHyZc64g7JW289TKHdQ2BfjiFN0MFRE5qMNAd87FAvcBs4GxwDzn3NjDTrsOqDazEcB/AD8Pd6EHmRkPvbmZ0QPTKR7at6s+RkSkx+lMC30SUGFmG8ysBXgUmHvYOXOBB0LvHwdmuC6aVOXdLftZvbOGL07RvC0iIu11JtAHA1vbbW8L7TviOWYWAA4A/Q6/kHNuvnNuuXNueWVl5fFVjHFWUTaXTTy8BBGR3i2iN0XNbIGZFZtZcf/+/Y/rGqcNzeKh684gNTEuzNWJiPRsnQn07UD7sYFDQvuOeI5zLg7IAPaFo0AREemczgT6O0CRc67QOZcAXAUsOuycRcCXQu8/C7xkZha+MkVEpCMd9luYWcA5dxOwBIgF7jezMufc3cByM1sE/BF4yDlXAVThhb6IiERQpzqizWwxsPiwfXe2e98EfC68pYmIyLHokU+KiojIJynQRUSihAJdRCRKKNBFRKKE82t0oXOuEth8nL+eDewNYzk9SW/97vrevYu+99ENNbMjPpnpW6CfCOfccjMr9rsOP/TW767v3bvoex8fdbmIiEQJBbqISJToqYG+wO8CfNRbv7u+d++i730cemQfuoiIfFJPbaGLiMhhFOgiIlGixwV6RwtWRyPn3P3OuT3OuVK/a4kk51yec+5l59xq51yZc+5mv2uKBOdcknPubefc+6Hv/SO/a4ok51ysc+4959wzftcSSc65Tc65Vc65lc655cd1jZ7Uhx5asHodcD7eUnjvAPPMbLWvhXUx59zZQB3woJmN97ueSHHO5QK5Zvaucy4dWAFc1gv+vB2QamZ1zrl44DXgZjN7y+fSIsI5902gGOhjZhf7XU+kOOc2AcVmdtwPVPW0FnpnFqyOOma2FG+e+V7FzHaa2buh97VAOZ9czzbqmKcutBkf+uk5La8T4JwbAswB/uB3LT1RTwv0zixYLVHIOVcAnAIs87mUiAh1O6wE9gB/N7Ne8b2BXwPfBYI+1+EHA15wzq1wzs0/ngv0tECXXsg5lwaUALeYWY3f9USCmbWZ2US8NXwnOeeivqvNOXcxsMfMVvhdi0+mmdmpwGzg66Gu1mPS0wK9MwtWSxQJ9SGXAA+b2UK/64k0M9sPvAzM8rmUSJgKXBrqS34UOM859xd/S4ocM9seet0DPIHXxXxMelqgd2bBaokSoZuDfwTKzexev+uJFOdcf+dcZuh9Mt4ggDW+FhUBZvZ9MxtiZgV4f7dfMrMv+FxWRDjnUkM3/nHOpQIXAMc8qq1HBbqZBYCDC1aXA4+ZWZm/VXU959wjwJvAKOfcNufcdX7XFCFTgS/itdRWhn4u8ruoCMgFXnbOfYDXiPm7mfWqIXy90ADgNefc+8DbwLNm9vyxXqRHDVsUEZGj61EtdBEROToFuohIlFCgi4hECQW6iEiUUKCLiEQJBbqISJRQoIuIRIn/D4W5H7Xmuzv6AAAAAElFTkSuQmCC\n", 102 | "text/plain": [ 103 | "
" 104 | ] 105 | }, 106 | "metadata": { 107 | "needs_background": "light" 108 | }, 109 | "output_type": "display_data" 110 | } 111 | ], 112 | "source": [ 113 | "givens = \\\n", 114 | "{t: 2}\n", 115 | "\n", 116 | "# Take the derivative with respect to t. Evaluate at t=2\n", 117 | "slope = sym.diff(f_unit_step_response, t).subs(givens)\n", 118 | "point_fn = f_unit_step_response.subs(givens)\n", 119 | "\n", 120 | "# Point-Slope Formula to get a line equation\n", 121 | "l = slope * (t - givens[t]) + point_fn\n", 122 | "\n", 123 | "# Get the limit of the original function to plot the DiffyQ steady state value.\n", 124 | "steady_state_val = sym.limit(f_unit_step_response, t, sym.oo)\n", 125 | "\n", 126 | "# Get the point at which the linearization intersects the steady state time.\n", 127 | "# Intersection time is one time constant away from the point we linearized around.\n", 128 | "tau = 1 # Unfortunately, we have to look at unit step response to get this value.\n", 129 | "intersection_time = givens[t] + tau\n", 130 | "\n", 131 | "# Plotting\n", 132 | "lambda_l = sym.lambdify(t, l, modules=modules)\n", 133 | "l_series = np.array([lambda_l(t) for t in time_series])\n", 134 | "ss_series = np.array([steady_state_val for t in time_series])\n", 135 | "\n", 136 | "plt.plot(time_series, f_series)\n", 137 | "plt.plot(time_series, l_series)\n", 138 | "plt.plot(time_series, ss_series)\n", 139 | "\n", 140 | "\n", 141 | "plt.plot([intersection_time], [lambda_l(intersection_time)], marker='o')\n", 142 | "plt.show()" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": {}, 148 | "source": [ 149 | "The result above is pretty powerful. Given *just* the system's time constant, we can use a small time window to approximate the slope and then get the tangent line to extrapolate what value the system will settle at." 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "# References\n", 157 | "\n", 158 | "1. https://www.youtube.com/watch?v=1mvZHN5ew5M&t=3s&ab_channel=nerdkits" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [] 167 | } 168 | ], 169 | "metadata": { 170 | "kernelspec": { 171 | "display_name": "Python 3", 172 | "language": "python", 173 | "name": "python3" 174 | }, 175 | "language_info": { 176 | "codemirror_mode": { 177 | "name": "ipython", 178 | "version": 3 179 | }, 180 | "file_extension": ".py", 181 | "mimetype": "text/x-python", 182 | "name": "python", 183 | "nbconvert_exporter": "python", 184 | "pygments_lexer": "ipython3", 185 | "version": "3.6.12" 186 | } 187 | }, 188 | "nbformat": 4, 189 | "nbformat_minor": 4 190 | } 191 | -------------------------------------------------------------------------------- /light_guide_panel_generator/good_laser_density_params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Poofjunior/jupyter_notebooks/729a300b20fe5d2c2577903a0137a75b75a46895/light_guide_panel_generator/good_laser_density_params.png --------------------------------------------------------------------------------