{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import sympy as smp\n", "from scipy.integrate import odeint\n", "import matplotlib.pyplot as plt\n", "from matplotlib import animation\n", "from mpl_toolkits.mplot3d import Axes3D\n", "from matplotlib.animation import PillowWriter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", " \"drawing\"\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define all appropriate symbols using sympy. " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "t, g = smp.symbols('t g')\n", "m1, m2 = smp.symbols('m1 m2')\n", "L1, L2 = smp.symbols('L1, L2')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\theta_1$ and $\\theta_2$ are functions of time (which we will eventually solve for). We need to define them carefully." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "the1, the2 = smp.symbols(r'\\theta_1, \\theta_2', cls=smp.Function)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Explicitly write them as functions of time $t$:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "the1 = the1(t)\n", "the2 = the2(t)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\theta_{1}{\\left(t \\right)}$" ], "text/plain": [ "\\theta_1(t)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "the1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define derivatives and second derivatives" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "the1_d = smp.diff(the1, t)\n", "the2_d = smp.diff(the2, t)\n", "the1_dd = smp.diff(the1_d, t)\n", "the2_dd = smp.diff(the2_d, t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define $x_1$, $y_1$, $x_2$, and $y_2$ written in terms of the parameters above." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "x1 = L1*smp.sin(the1)\n", "y1 = -L1*smp.cos(the1)\n", "x2 = L1*smp.sin(the1)+L2*smp.sin(the2)\n", "y2 = -L1*smp.cos(the1)-L2*smp.cos(the2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then use these to define kinetic and potential energy for each mass. Obtain the Lagrangian" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "# Kinetic\n", "T1 = 1/2 * m1 * (smp.diff(x1, t)**2 + smp.diff(y1, t)**2)\n", "T2 = 1/2 * m2 * (smp.diff(x2, t)**2 + smp.diff(y2, t)**2)\n", "T = T1+T2\n", "# Potential\n", "V1 = m1*g*y1\n", "V2 = m2*g*y2\n", "V = V1 + V2\n", "# Lagrangian\n", "L = T-V" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle L_{1} g m_{1} \\cos{\\left(\\theta_{1}{\\left(t \\right)} \\right)} - g m_{2} \\left(- L_{1} \\cos{\\left(\\theta_{1}{\\left(t \\right)} \\right)} - L_{2} \\cos{\\left(\\theta_{2}{\\left(t \\right)} \\right)}\\right) + 0.5 m_{1} \\left(L_{1}^{2} \\sin^{2}{\\left(\\theta_{1}{\\left(t \\right)} \\right)} \\left(\\frac{d}{d t} \\theta_{1}{\\left(t \\right)}\\right)^{2} + L_{1}^{2} \\cos^{2}{\\left(\\theta_{1}{\\left(t \\right)} \\right)} \\left(\\frac{d}{d t} \\theta_{1}{\\left(t \\right)}\\right)^{2}\\right) + 0.5 m_{2} \\left(\\left(L_{1} \\sin{\\left(\\theta_{1}{\\left(t \\right)} \\right)} \\frac{d}{d t} \\theta_{1}{\\left(t \\right)} + L_{2} \\sin{\\left(\\theta_{2}{\\left(t \\right)} \\right)} \\frac{d}{d t} \\theta_{2}{\\left(t \\right)}\\right)^{2} + \\left(L_{1} \\cos{\\left(\\theta_{1}{\\left(t \\right)} \\right)} \\frac{d}{d t} \\theta_{1}{\\left(t \\right)} + L_{2} \\cos{\\left(\\theta_{2}{\\left(t \\right)} \\right)} \\frac{d}{d t} \\theta_{2}{\\left(t \\right)}\\right)^{2}\\right)$" ], "text/plain": [ "L1*g*m1*cos(\\theta_1(t)) - g*m2*(-L1*cos(\\theta_1(t)) - L2*cos(\\theta_2(t))) + 0.5*m1*(L1**2*sin(\\theta_1(t))**2*Derivative(\\theta_1(t), t)**2 + L1**2*cos(\\theta_1(t))**2*Derivative(\\theta_1(t), t)**2) + 0.5*m2*((L1*sin(\\theta_1(t))*Derivative(\\theta_1(t), t) + L2*sin(\\theta_2(t))*Derivative(\\theta_2(t), t))**2 + (L1*cos(\\theta_1(t))*Derivative(\\theta_1(t), t) + L2*cos(\\theta_2(t))*Derivative(\\theta_2(t), t))**2)" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get Lagrange's equations\n", "\n", "$$\\frac{\\partial L}{\\partial \\theta_1} - \\frac{d}{dt}\\frac{\\partial L}{\\partial \\dot{\\theta_1}} = 0$$\n", "$$\\frac{\\partial L}{\\partial \\theta_2} - \\frac{d}{dt}\\frac{\\partial L}{\\partial \\dot{\\theta_2}} = 0$$" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "LE1 = smp.diff(L, the1) - smp.diff(smp.diff(L, the1_d), t).simplify()\n", "LE2 = smp.diff(L, the2) - smp.diff(smp.diff(L, the2_d), t).simplify()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solve Lagranges equations (this assumes that `LE1` and `LE2` are both equal to zero)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "sols = smp.solve([LE1, LE2], (the1_dd, the2_dd),\n", " simplify=False, rational=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we have \n", "\n", "* $\\frac{d^2 \\theta_1}{dt^2} = ...$\n", "* $\\frac{d^2 \\theta_2}{dt^2} = ...$\n", "\n", "These are two second order ODEs! In python we can only solve systems of first order ODEs. Any system of second order ODEs can be converted as follows:\n", "\n", "1. Define $z_1 = d\\theta_1/dt$ and $z_2=d\\theta_2/dt$\n", "2. Then $dz_1/dt = d^2\\theta_1/dt^2$ and $dz_2/dt = d^2\\theta_2/dt^2$\n", "\n", "Now we get a system of 4 first order ODEs (as opposed to 2 second order ones)\n", "\n", "* $d z_1/dt = ...$\n", "* $d\\theta_1/dt = z_1$\n", "* $d z_2/dt = ...$\n", "* $d\\theta_2/dt = z_1$\n", "\n", "We need to convert the **symbolic** expressions above to numerical functions so we can use them in a numerical python solver. For this we use `smp.lambdify`" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "dz1dt_f = smp.lambdify((t,g,m1,m2,L1,L2,the1,the2,the1_d,the2_d), sols[the1_dd])\n", "dz2dt_f = smp.lambdify((t,g,m1,m2,L1,L2,the1,the2,the1_d,the2_d), sols[the2_dd])\n", "dthe1dt_f = smp.lambdify(the1_d, the1_d)\n", "dthe2dt_f = smp.lambdify(the2_d, the2_d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now define $\\vec{S} = (\\theta_1, z_1, \\theta_2, z_2)$. IF we're going to use an ODE solver in python, we need to write a function that takes in $\\vec{S}$ and $t$ and returns $d\\vec{S}/dt$. In other words, we need to define $d\\vec{S}/dt (\\vec{S}, t)$\n", "\n", "* Our system of ODEs can be fully specified using $d\\vec{S}/dt$ and depends only on $\\vec{S}$ and $t$" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "def dSdt(S, t, g, m1, m2, L1, L2):\n", " the1, z1, the2, z2 = S\n", " return [\n", " dthe1dt_f(z1),\n", " dz1dt_f(t, g, m1, m2, L1, L2, the1, the2, z1, z2),\n", " dthe2dt_f(z2),\n", " dz2dt_f(t, g, m1, m2, L1, L2, the1, the2, z1, z2),\n", " ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solve the system of ODEs using scipys `odeint` method" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "t = np.linspace(0, 40, 1001)\n", "g = 9.81\n", "m1=2\n", "m2=1\n", "L1 = 2\n", "L2 = 1\n", "ans = odeint(dSdt, y0=[1, -3, -1, 5], t=t, args=(g,m1,m2,L1,L2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "25 times per second (number of data points). This will be important for animating later on." ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 1. , 0.87413906, 0.73333306, ..., -0.75268561,\n", " -0.60481044, -0.45270209],\n", " [-3. , -3.31025173, -3.75998052, ..., 3.64397936,\n", " 3.7514106 , 3.84881428],\n", " [-1. , -0.78277685, -0.52139856, ..., 79.49932146,\n", " 79.50044235, 79.55942868],\n", " [ 5. , 5.91440903, 7.24155048, ..., -0.66192636,\n", " 0.73534285, 2.22745168]])" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ans.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Can obtain $\\theta_1(t)$ and $\\theta_2(t)$ from the answer" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "the1 = ans.T[0]\n", "the2 = ans.T[2]" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(t, the2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's a function that takes in $\\theta_1$ and $\\theta_2$ and returns the location (x,y) of the two masses." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "def get_x1y1x2y2(t, the1, the2, L1, L2):\n", " return (L1*np.sin(the1),\n", " -L1*np.cos(the1),\n", " L1*np.sin(the1) + L2*np.sin(the2),\n", " -L1*np.cos(the1) - L2*np.cos(the2))\n", "\n", "x1, y1, x2, y2 = get_x1y1x2y2(t, ans.T[0], ans.T[2], L1, L2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we can make an animation" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def animate(i):\n", " ln1.set_data([0, x1[i], x2[i]], [0, y1[i], y2[i]])\n", " \n", "fig, ax = plt.subplots(1,1, figsize=(8,8))\n", "ax.set_facecolor('k')\n", "ax.get_xaxis().set_ticks([]) # enable this to hide x axis ticks\n", "ax.get_yaxis().set_ticks([]) # enable this to hide y axis ticks\n", "ln1, = plt.plot([], [], 'ro--', lw=3, markersize=8)\n", "ax.set_ylim(-4,4)\n", "ax.set_xlim(-4,4)\n", "ani = animation.FuncAnimation(fig, animate, frames=1000, interval=50)\n", "ani.save('pen.gif',writer='pillow',fps=25)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }