{ "cells": [ { "cell_type": "markdown", "id": "viral-score", "metadata": {}, "source": [ "

Deep Reinforcement Learning for Robotic Systems

" ] }, { "cell_type": "markdown", "id": "stretch-announcement", "metadata": {}, "source": [ "## Synopsis\n", "\n", "This notebook outlines the end-to-end mathematical and computational modelling of an **inverted double pendulum** with the integration of the **[Proximal Policy Optimisation](http://arxiv.org/abs/1707.06347)** algorithm as the control system. This project serves as a baseline study into advanced autonomous control systems facilitating the control of multibody, variable mass dynamical systems, such as docking and berthing of spacecraft, and rocket trajectory stabilisation.\n", "\n", "#### The accompanying written evaluation can be found [here](https://drive.google.com/file/d/1cvxC5QPPS9X9DEcnlZfgxMtREl2IGdMo/view?usp=sharing).\n", "\n", "--------\n", "Produced by *[Mughees Asif](https://github.com/mughees-asif)*, under the supervision of [Dr. Angadh Nanjangud](https://www.sems.qmul.ac.uk/staff/a.nanjangud) (Lecturer in Aerospace/Spacecraft Engineering @ [Queen Mary, University of London](https://www.sems.qmul.ac.uk/)). This project was awarded with the **[Institution of Mechanical Engineers (IMechE) Project Prize](https://www.imeche.org/careers-education/scholarships-and-awards/university-awards/project-award)**, in recognition, for the best third-year project for a finalist on an IMechE accredited programme.\n", "\n", "--------\n", "\n", "#### To cite, please use the following information:\n", "\n", "##### BibTeX:\n", "```@misc{asif_nanjangud_2021,```
\n", "    ```title = {Deep Reinforcement Learning for Robotic Systems},```
\n", "    ```url = {https://github.com/mughees-asif/dip},```
\n", "    ```journal = {GitHub},```
\n", "    ```publisher = {Mughees Asif},```
\n", "    ```author = {Asif, Mughees and Nanjangud, Angadh},```
\n", "    ```year = {2021},```
\n", "    ```month = {Apr}```
\n", "   ```}```\n", "\n", "##### Harvard:\n", "```Asif, M., and Nanjangud, A.. (2021). Deep Reinforcement Learning for Robotic Systems.```\n", "\n", "##### APA:\n", "```Asif, M., & Nanjangud, A.. (2021). Deep Reinforcement Learning for Robotic Systems.```" ] }, { "cell_type": "markdown", "id": "massive-childhood", "metadata": {}, "source": [ "## Contents\n", "\n", "**1. [Overview](#overview)
**\n", "\n", "**2. [Model](#model)
**\n", " 2.1. [Description](#model-description)
\n", "\n", "**3. [Governing Equations of Motion](#governing-eqs-motion)
**\n", " 3.1. [Library Imports](#library-imports)
\n", " 3.2. [Variable Declaration](#var-dec)
\n", " 3.3. [Kinetic and Potential Energy](#kinetic-potential)
\n", " 3.4. [The Lagrangian](#lagrangian)
\n", " 3.5. [The Euler-Lagrange Equations](#euler-lagrange)
\n", " 3.6. [Linearisation and Acceleration](#linearisation)
\n", "\n", "**4. [Proximal Policy Optimisation](#ppo)**
\n", " 4.1. [Overview](#ppo-overview)
\n", " 4.2. [Mathematical Model](#ppo-math)
\n", " 4.3. [Neural Network](#ppo-nn)
\n", "   *4.3.1. [Actor](#ppo-nn-actor)
*\n", "   *4.3.2. [Critic](#ppo-nn-critic)
*\n", "   *4.3.3. [Agent](#ppo-nn-agent)
*\n", " 4.4. [Environment](#ppo-env)
\n", " 4.5. [Test](#ppo-test)
\n", "\n", "**5. [Conclusion](#conclusion)**
\n", " 5.1. [Variations in initial angle conditions](#conclusion-init-angles)
\n", "\n", "---\n", "\n", "## Important information\n", "* Press [☝](#contents) to return to the contents.\n", "* Prior to running the notebook, please [install](https://github.com/mughees-asif/dip#environment-setup) the following dependencies:\n", " * `SymPy`\n", " * `NumPy`\n", " * `Matplotlib`\n", " * `PyTorch`\n", "* Make sure to have the `seeding.py` [file](https://github.com/mughees-asif/dip) locally in the same folder as the notebook.\n", "* To simulate the system according to your parameters:\n", " * Change the system parameters in the [Environment](#ppo-env) section.\n", " * Change the number of games to be executed in the [Test](#ppo-test) section and run the same cell to get results.\n", "* Any problems, [email](mailto:mughees460@gmail.com) me or ping me on [LinkedIn](https://www.linkedin.com/in/mugheesasif/). " ] }, { "cell_type": "markdown", "id": "minor-latex", "metadata": {}, "source": [ "## 1. Overview [☝](#contents)\n", "\n", "Proximal Policy Optimisation is a deep reinforcement learning algorithm developed by [OpenAI](https://spinningup.openai.com/en/latest/algorithms/ppo.html). It has proven to be successful in a variety of tasks ranging from enabling robotic systems in complex environments, to developing proficiency in computer gaming by using stochastic mathematical modelling to simulate real-life decision making. For the purposes of this research, the algorithm will be implemented to vertically stablise an inverted double pendulum, which is widely used in industry as a benchmark to validate the veracity of next-generation intelligent algorithms." ] }, { "cell_type": "markdown", "id": "primary-olympus", "metadata": {}, "source": [ "## 2. Model [☝](#contents)\n", "\n", "\n", "\n", "| Name | Symbol |\n", "| :-: | :-: | \n", "| Mass of the cart | $$m$$ | \n", "| Mass of the pendulums | $$M_1 = M_2 = M$$ |\n", "| Length of the pendulums | $$l_1 = l_2 = l$$ |\n", "| Angle of the first pendulum
w.r.t the vertical (CCW+) | $$\\theta$$ |\n", "| Angle of the second pendulum
w.r.t the first pendulum (CCW+) | $$\\phi$$ |\n", "| Moment of inertia for the pendulums | $$I_1 = I_2 = I$$ |\n", "| Horizontal cart position | $$x$$ |\n", "| Horizontal force applied to the cart | $$u$$ |\n", "| Gravitational constant | $$g$$ |" ] }, { "cell_type": "markdown", "id": "super-piece", "metadata": {}, "source": [ "### 2.1. Description [☝](#contents)\n", "\n", "An inverted double pendulum is a characteristic example of a holonomic, non-linear and chaotic mechanical system that relies on the *Butterfly Effect*: highly dependent on the initial conditions.\n", "\n", "#### Assumptions:\n", "* The mass, length & moment of inertia of the pendulums are equal.\n", "* No frictional forces exist between the surface and the cart wheels. " ] }, { "cell_type": "markdown", "id": "ordinary-orleans", "metadata": {}, "source": [ "## 3. Governing Equations of Motion [☝](#contents)" ] }, { "cell_type": "markdown", "id": "brave-portable", "metadata": {}, "source": [ "### 3.1. Library Imports [☝](#contents)" ] }, { "cell_type": "code", "execution_count": 18, "id": "preceding-baseball", "metadata": {}, "outputs": [], "source": [ "# mathematical\n", "from sympy import symbols, Function, cos, sin, Eq, linsolve\n", "from sympy.physics.mechanics import init_vprinting\n", "\n", "# computational\n", "import matplotlib.pyplot as plt\n", "import math\n", "import time\n", "import gym\n", "import seeding \n", "import numpy as np\n", "import torch as T \n", "import torch.nn as nn \n", "import torch.optim as optim\n", "from torch.distributions.categorical import Categorical " ] }, { "cell_type": "markdown", "id": "formed-brand", "metadata": {}, "source": [ "### 3.2. Variable Declaration [☝](#contents)" ] }, { "cell_type": "code", "execution_count": 2, "id": "aerial-anxiety", "metadata": {}, "outputs": [], "source": [ "# format mathematical output\n", "init_vprinting()\n", "\n", "# initiliase variables\n", "t = symbols('t') # time\n", "m = symbols('m') # mass of the cart\n", "l = symbols('l') # length of the pendulums, l_1 = l_2 = l\n", "M = symbols('M') # mass of the pendulums, M_1 = M_2 = M\n", "I = symbols('I') # moment of inertia\n", "g = symbols('g') # gravitational constant\n", "u = symbols('u') # force applied to the cart (horizontal component)\n", "\n", "x = Function('x')(t) # |\n", "Θ = Function('Θ')(t) # | --- functions of time `t`\n", "Φ = Function('Φ')(t) # |\n", "\n", "# cart\n", "x_dot = x.diff(t) # velocity\n", "\n", "# pendulum(s) \n", "Θ_dot = Θ.diff(t) # | \n", "Θ_ddot = Θ_dot.diff(t) # |\n", "Φ_dot = Φ.diff(t) # |\n", "Φ_ddot = Φ_dot.diff(t) # |\n", "cos_theta = cos(Θ) # | --- experimental parameters\n", "sin_theta = sin(Θ) # |\n", "cos_thetaphi = cos(Θ - Φ) # |\n", "cos_phi = cos(Φ) # |\n", "sin_phi = sin(Φ) # |" ] }, { "cell_type": "markdown", "id": "billion-clearance", "metadata": {}, "source": [ "### 3.3. Kinetic (K.E.) and Potential (P.E.) Energy [☝](#contents)" ] }, { "cell_type": "markdown", "id": "humanitarian-american", "metadata": {}, "source": [ "\n", "\n", "\n", "\\begin{equation*} \n", "\\because K.E._{T}= K.E._{C} + K.E._{1} + K.E._{2}\n", "\\label{eq:ke_4} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "\\because P.E._{T}= P.E._{C} + P.E._{1} + P.E._{2}\n", "\\end{equation*}\n", "\n", "---\n", "\n", "\\begin{equation*} \n", "K.E._{C}=\\frac{1}{2}m{\\dot{x}^2} \n", "\\label{eq:ke_1} \\tag{1} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "K.E._{1}=\\frac{1}{2}M\\left[\\dot{x}\\left(\\dot{x}+2l\\dot{\\theta{}}\\cos{\\theta{}}\\right)+{\\dot{\\theta{}}}^2\\left(Ml^2+I\\right)\\right] \n", "\\label{eq:ke_2} \\tag{2} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "K.E._{2}=\\frac{1}{2}\\left[{\\dot{x}}^2+l^2{\\dot{\\theta{}}}^2+{\\dot{\\phi{}}}^2\\left(Ml^2+I\\right)+Ml\\dot{\\theta{}}\\dot{\\phi{}}\\cos{\\left(\\theta{}-\\phi{}\\right)}+2Ml\\dot{x}\\left(\\dot{\\theta{}}\\cos{\\theta{}}+\\dot{\\phi{}}\\cos{\\phi{}}\\right)\\right] \n", "\\label{eq:ke_3} \\tag{3} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "\\therefore \\boldsymbol{K.E._{T}=\\frac{1}{2}\\left[m{\\dot{x}}^2+M\\dot{x}\\left(\\dot{x}+2l\\dot{\\theta{}}\\cos{\\theta{}}\\right)+{\\dot{\\theta{}}}^2\\left(Ml^2+I\\right)+{\\dot{x}}^2+l^2{\\dot{\\theta{}}}^2+\\\\{\\dot{\\phi{}}}^2\\left(Ml^2+I\\right)+Ml\\dot{\\theta{}}\\dot{\\phi{}}\\cos{\\left(\\theta{}-\\phi{}\\right)}+2Ml\\dot{x}\\left(\\dot{\\theta{}}\\cos{\\theta{}}+\\dot{\\phi{}}\\cos{\\phi{}}\\right)\\right]}\n", "\\label{eq:ke_5} \\tag{4} \n", "\\end{equation*}\n", "\n", "---\n", "\n", "\\begin{equation*} \n", "P.E._{C}=0\n", "\\tag{5} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "P.E._{1}=Mgl\\cos{\\theta}\n", "\\tag{6} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "P.E._{2}=Mgl\\cos{\\theta} + Mgl\\cos{\\phi}\n", "\\tag{7} \n", "\\end{equation*}\n", "\n", "\\begin{equation*} \n", "\\therefore \\boldsymbol{P.E._{T}=Mgl(2\\cos{\\theta} + \\cos{\\phi})}\n", "\\tag{8} \n", "\\end{equation*}" ] }, { "cell_type": "code", "execution_count": 3, "id": "figured-working", "metadata": {}, "outputs": [], "source": [ "# kinetic energy components\n", "# cart - linear\n", "k_1 = m*x_dot**2 \n", "\n", "# pendulum(s) - angular\n", "k_2 = (M*x_dot*(x_dot + 2*l*Θ_dot*cos_theta) + Θ_dot**2*(M*(l**2)+I))\n", "k_3 = (x_dot**2) + (l**2*Θ_dot**2) + (Φ_dot**2*(M*(l**2)+I) \\\n", " + (M*l*Θ_dot*Φ_dot*cos_thetaphi) + \\\n", " (2*M*l*x_dot*((Θ_dot*cos_theta) + (Φ_dot*cos_phi))))" ] }, { "cell_type": "code", "execution_count": 4, "id": "possible-apparel", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "The kinetic energy, K, of the system:\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle 1.0 M l \\left(\\cos{\\left(Θ \\right)} \\dot{Θ} + \\cos{\\left(Φ \\right)} \\dot{Φ}\\right) \\dot{x} + 0.5 M l \\cos{\\left(Θ - Φ \\right)} \\dot{Θ} \\dot{Φ} + 0.5 M \\left(2 l \\cos{\\left(Θ \\right)} \\dot{Θ} + \\dot{x}\\right) \\dot{x} + 0.5 l^{2} \\dot{Θ}^{2} + 0.5 m \\dot{x}^{2} + 0.5 \\left(I + M l^{2}\\right) \\dot{Θ}^{2} + 0.5 \\left(I + M l^{2}\\right) \\dot{Φ}^{2} + 0.5 \\dot{x}^{2}$" ], "text/plain": [ " \n", "1.0⋅M⋅l⋅(cos(Θ)⋅Θ̇ + cos(Φ)⋅Φ̇)⋅ẋ + 0.5⋅M⋅l⋅cos(Θ - Φ)⋅Θ̇⋅Φ̇ + 0.5⋅M⋅(2⋅l⋅cos\n", "\n", " 2 2 2 ⎛ 2⎞ 2 ⎛ 2⎞ 2 \n", "(Θ)⋅Θ̇ + ẋ)⋅ẋ + 0.5⋅l ⋅Θ̇ + 0.5⋅m⋅ẋ + 0.5⋅⎝I + M⋅l ⎠⋅Θ̇ + 0.5⋅⎝I + M⋅l ⎠\n", "\n", "2\n", "⋅Φ̇ + 0.5⋅ẋ " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# total kinetic energy\n", "K = 0.5*(k_1 + k_2 + k_3)\n", "\n", "print('----\\nThe kinetic energy, K, of the system:\\n----')\n", "K" ] }, { "cell_type": "code", "execution_count": 5, "id": "becoming-bangkok", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "The potential energy, P, of the system:\n", "----\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAANsAAAAXCAYAAACCqTqPAAAJkklEQVR4nO3ceZAdVRUG8N8kgMFIBSFaIIuhVMImiWEJ+2ZEsRQEhaJUIEQWJYK4AEYBU7IqokiJgECIUCouFCKC7ARNUAMJE4XIImvEgEJMDCRGAvGPc7teT7/u1zNkXmYi81VN3Z4+t2/fe/qec75zumc6Jk+ebAADGED7MaivJ5DwBazAx0tkV+EfGLpKZ9R+tGNd2wk9fqoXx1zd0dt6rtNxpbzM2G5LnVfghBY3vSLX74oeTLYMY1I7u3B+e3wS5+Kl3Pn1cRSuw1+xFIswXSyyvziRKlStq9jnSjwu1vdv/BnnYaOKa2bhlzgTb+q96a626I6eM4wQe/nJmn51Oq6Ul23KMViejretuOFYHIlX0u/31UywDmPwIh4pnD9bbLKLC+cPxmVpHn/EBbgW2+By/AwdKzmndqJqXcS8v4F7xUZ5CBcKh7YEXxJ6+ljF2OdgA60d5esFrfScYU28VzhvWBcTNQJAGep0XCovGts7sB5m4jnlxjYIF+GfGka2MsY2FCPRiVdz5zfHOGE4SwvXPIL9sTE+gUmYgC0wDx/FQSsxp3ai1brgNJyMp/EefBCn4PPCuRwkDPIa7F1y/UxhoMdi8GuY33jh4fd6Ddf2J9TpmTCwp3E7vprODcP3RISagz1KrqvTcam8aGzbp3YW7sfWJX2OFbz0ZGGcL+NPhT5D8GXMxX/wFL6Sbry40H90useswhgTxKb6acli7sQNuhonPItL0vFeJdfBjmnMZ7AM83ErDinpewh+KyjqUkHjJuENJX33xx1pvGX4O+7GcT1Y1whhbMvTeA+U9LkOnxO6vFg5O7kGm4rN1hfoax3TWs8EHb8M6+B07JfOz8Nugkm8O93vwJLr63TcJG9lbLPxRmFQGYbjLPxeLHK4UM6yXJ+huEuE0iX4bvr9dEwVPPb+XP/tUlvM18YJmvqHisVU4eXULi+RHY178JHUno8b8VbND+xs8aC2xI+Ft+tI528R9CPDMbgeWwkncD5uwtqCbnd3XUdiDWFQc1qscYrYaCOxZ4l8Rmrf12KMdqE/6JjWet5H0PEXsQvOEJGIcOAzRNQbL57HFFEnyKNOx03yNQodMmO7TyOh3BaPpuNzRZidqGEkRQp5KXYSxnWmoCRwtQjXdDWssuLIUBHx/qI+sc1jDRyejm8uyLbC9wWH3x0PFuQb5453Ft51nvDSz6bzk4QhfAgniU1BRPv/YpSofOUxPHdct67dUnub2KyjS/oQTmuaqN7uKpxZHvemtowCtRP9QcfU6/mY1F6kmZXlcZVwEGNFjnxpTlan4yZ53tg6RI6wRFh5xnO3FcWHsSI0XyIi08FJnje2nUQOdb3wFnncIfjxppqNbalQTIaNBE2aX7GQKpwriiQ3Cc+Yx2fEes/QvAngb7njCak9U2MTENHyiyKPOkpjI2SylzXj+dxx3bo2TO08HIojKvpNS33gbSXyRYK+b1pxfbvQH3RMvZ63Se30Cnke08Xe37pwvk7HTfI8jdxcRK1OEX4fx0JhbFlR5AWcmvrno2CGiak9q2ICL4hI15l+HyIoxByNyiaNkP2vinHKcIJ4SA/hsBL5Tqn9TTfGyqLtnSWyR8Sm2UxUruBHgnI/iO+IqPSWkmvr1pVVUFcICtNR8TOt0LcMCzR7/CKe1Hh9k/1cmWR3lcim1ozXH3RM9/dPle7K+pRVt+t03EWej2xlxtMpksRjBG08Og1AKGuZrkn8vsKgqqqTGwpKujj9PirNoVgcyaLqkBYLyWOiyA3nijLugpI+66b2mW6MNyy1VZ5xvvBYw4RD+rbwrscJoz9RPKS7BRXK9FG3rvmiotqdiJRRsqo5rq26CpfhAg29ZBiNA/BDze+cOmvGy8bqSx1Tr+e5IlLtKvLJVtg1d00RdTruIi8ztvzGv18k4GcLDpq9vN5MeI+ZGmF9iEiCO5V7jC3Eu4dpuXNVxZGMkxeT0jKcKDzdA8LQinw+w8LUbqSRDFdhUWo3wGMl8g0L/Qh+f5XYcLuICtYEQWe3TPOqW9d0Uc4fJyplVRisURiZUSIflObxRIsxCGMrYrwwtqm6PqvuYGFq+1LH1Ov5cpEGfVZEzDLKS+TEO4sc9BcFWZ2Om+R5GllmbLNF+Fw3TSwzorLiyPL08+aKm5+cGzND1Zcj88V7vJEVY2U4RRhap9ikVYZGoyq1X4s+GbJq6V4lsneKqPKExubKY6HIGY8WG3Y9USygfl1XCh0eqDlHyGO82NCPCs9exEjx3DpbjNEO9AcdU6/nWwUTWifNeVK6J2ETO4raxNUivTkqjZdHnY6b5INy7WhRuckXKm4SD34fEcUylFHO5YJrv11EmDwmapRni8a2TLNnWSHevQzXUEIRp4mCyKx0v2KSXMTFaY6niapZEflK2ZTUnqprXjAY3xL6yn+i9gHNlV0i0hNFJ+rX9YQoGKyJX1XMc3/xRcmrglIV3zXSyJ2KVcp2oz/omO7tnxOF/pYI5nZbOr+J+CrpWBGd98XPS66v03GTPJv8luL91wxdH94C8Z1XEVVl/3OEN7hRvD95VpSz35UmPlLD2NYSVaE5yitM14ovQd4vvn/M4wh8XXid3yn/bOZJXRP6uUK5WTX1ehEZ1hfOY7HGFxn34JsiGj8gKMRLwmNvI+jeebmxrxGVp+npvh3C0+4gnMHtub6t1iWta6jIQ+YIivSgeFa7iIe4VFR9by+5ntggr6Q1rkr0Fx1Tr2fCOUwRlHxP8eHFIkwW75Jnqi6i1Om4Sd6R/sTmcJEQXyi+TqjDCyL5W0fXKiIcL7zGJsLYbhBKnS2+JMmo43bCWH8gvEgRa4lXBU+J0msek/G1mjnerZyi7CxeaO4u6PHz4l3L5Zp5+aGCPo8S0eYx8fL1fPHgM3xaPNRRIgfJvpr5iXigi3N9W60rjx0EI9gzjfmK2GQ3Cwo0r+K6YULvt4iKXU8xXtDZvfU8Z8vQ1zqm+3rOMEIwi6fScSvU6bhU3rGK/p7tMJHYniQoQncxSYT4Mbp+dbK6o53rOl44zT1E1H89o116rtNxqbw3jW2woAvFIsU4QUUXCB7/Yg/GHIKHhVf88MpPsd+gXetaW0SGe1T/VcDrCe3Qc52OK+VlCedrxVbi9cAt6WZriqLLboJGHKBnhkZQhcMEpRmqZ59u9We0a10jBC2f2kvjre5oh55HaK3jSnlvRraRokAyVkS4VwUH/rV4Iflcb91oAANYHdGbke1h/fdvyAYwgD5Hf//3AQMYwP8NBoxtAANYRfgfc4fyOqZDI7QAAAAASUVORK5CYII=\n", "text/latex": [ "$\\displaystyle M g l \\left(2 \\cos{\\left(Θ \\right)} + \\cos{\\left(Φ \\right)}\\right)$" ], "text/plain": [ "M⋅g⋅l⋅(2⋅cos(Θ) + cos(Φ))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# total potential energy\n", "P = M*g*l*((2*cos_theta) + cos_phi)\n", "\n", "print('----\\nThe potential energy, P, of the system:\\n----')\n", "P" ] }, { "cell_type": "markdown", "id": "polar-soundtrack", "metadata": {}, "source": [ "### 3.4. The Lagrangian [☝](#contents)\n", "\n", "The action $S$ of the cart (movement; left, right) is mathematically defined as:\n", "\n", "$$\\because S = \\int_{t_{0}}^{t_{1}} K - P \\,dt$$\n", "\n", "and since, $\\mathcal{L} = K - P,$\n", "\n", "$$\\therefore S = \\int_{t_{0}}^{t_{1}} \\mathcal{L} \\;dt$$\n", "\n", "where,\n", "\n", "\\begin{equation*} \n", "\\boldsymbol{\\mathcal{L}=\\frac{1}{2}\\left[m{\\dot{x}}^2+M\\dot{x}\\left(\\dot{x}+2l\\dot{\\theta{}}\\cos{\\theta{}}\\right)+{\\dot{\\theta{}}}^2\\left(Ml^2+I\\right)+{\\dot{x}}^2+l^2{\\dot{\\theta{}}}^2+\\\\{\\dot{\\phi{}}}^2\\left(Ml^2+I\\right)+Ml\\dot{\\theta{}}\\dot{\\phi{}}\\cos{\\left(\\theta{}-\\phi{}\\right)}+2Ml\\dot{x}\\left(\\dot{\\theta{}}\\cos{\\theta{}}+\\dot{\\phi{}}\\cos{\\phi{}}\\right)\\right] - Mgl(2\\cos{\\theta} + \\cos{\\phi})}\n", "\\tag{9} \n", "\\end{equation*}" ] }, { "cell_type": "code", "execution_count": 6, "id": "metallic-conjunction", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "The Lagrangian of the system is:\n", "----\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABisAAAAdCAYAAADby18zAAAZ/UlEQVR4nO2de/xuU53H3+c4oo46R5pGQ3k4uYRyOhq6CskUXWiqmWqqXzdNlEwjpZE5KLxGmifdGIVxaZpJpUk1SIjoMnQIiXR+oY4onYNCnZz++Oz9evZvP/u+19qX5/m+X6/faz+/fVl7Xb6Xtfa6zVu+fDmGYRiGUZAlwfHWVmNhZGFlZBjNUlfnTGeNScNk2qiLyZBhGGYHjLYxGWyJBW1HwDAMo2UWAWvajkSPuDg4DtqMhJFJXhmZzBuGW+raRbOrfjBb1x59k2mTle7RNxkyDMM9ZgeMtjEZbIn5bUfAMAyjRTYADm47EobRMNsBL2k7EoZhGB4x/26UwfyiYRiGYRhGR7DOCsMwppmTgLPbjkTPGGAjC7rOgOwy+h6wG/DUCmEvYTQd1jAMMaCeXaz7vDGO+fd2GdBNmU7zYeYX3XI48APgXuBu4KvAjiXDGJAtQy7eYeSTJt+W/0YTMjDA7ICRThdksKl49JXKPsQ6KwzDmFb2AlYDK1uOh2G0wXHAiRWeu5jRdFjDMIwuYv7dSCPLh5lfdMfuwKeAZwN7AmuBbwKP7dk7jHT53h3L/2lnd9qXgS7EwWiP3elG+XclHl2ksg+ZZxtsG4YxpXwfeANwU9sRMYyW+C808vhrJZ6ZDY4D15ExDMNwhPl3I43Z4DhIuW5+0Q8boT1B9kOjJ/v6jmlkNjgOcu6z/De6IANdiIPRHl0p/67EowvMBsdBzn1jeTZJMyveA6wDXptw7UzgLmBhozHyj+t07Yzy8C2OwpsEfMhOXj5bObgjzS7sC8yjHx8y2pBBoxx9LaMzgaNKPjPAPsjUJau+0hUmtd6UhtnEycGHf59GnZ1UnRiQ7cPML5aniH48Gn13uMdjPJp4xzQyoJh8W/5Pdt2pqp437UtMDidXDuv4GpPD9hhQ0Yf46Ky4CAnCOrI3tvts5L7POnjvsuB4Tez8M4B/AI4Hfhc5vwnwVuDLwE+BB1BPzhVIiLvekZOWrvg9pwM/Q+m7F/gRcAKwWcL9VwPnAR9CPVvTTpE8DhkgWZ4tEG5ePnehHF4JfBy4HMnNOuqt/bw5cBrwS+AhlE9DYOOMZ1zYkjS78AbgO/nRbh0feg7FZaxK2NNGW3aibvgAVyId2aHg/V2gii1JYpaR3Yj/3ZnxnE+71BXyZLpPdmFAMZ0oo2+u0l80bk0yCfqV5d+r1v37rrPhPb7aBH2yCXmYXyyvt0X0YwisAL6bct2FDOW9wzdtl0PbDJmM/IdqZZBnh0P/tkeF+NSlqbrrkHEZaNqXJMWhSdq2A12VwzZlEJppVxeJR1O0LYdVGBLLswWOXwASorVB2E9LuWdX4E3An4D1gP939N77gZtj549Fhu7TsfOvCs6tAi4BbgP+EngF8BngxcE96xzEzQdp6QKNKDseOAyVxUXAF4BHoDXBDgUOBN4InBt79ji0ydzBwTummaw8DlkfbcgXGvzFwEHAVWQb0rx8brscjgB2Qjp1B7BdjbCWoMbf44GvoNGOuwDvBl4EPAf4TcJzLmxJkl2YD+wNHFI6Jc3jS88hW8bqhj1NtGkn6oa/Bq3p/mLghoz7ukJVW5LGGlQxinN/xjO+7FKXSJPpPtmFKjqRp2+u0l9VX30zCfqV59+r1v37qrPgt03QJ5tQFPOL1fQ2Sz9OQDbveUhvo7iSoax3NEEXyqFNJi3/oXwZ5LUHliHf0oafb6LumiUDTfmSSZPDKnagq3LYtgyC/3Z10Xj4pgtyWJbEPHO9Z8USNFLpyuD3bShjosxHa8k+EVUGdw3u+UGN9y5ESnklSmDINqhwPgMcEHtmz+C5rwEPR85vGonfK4Ev1oiXL7LSBXAkmsJ8G5oOf33s+v7AOcgBvBA12KL8GHgUsBXVFGwG9YrvAVxa4fkukJfHoNF5xyCZSeI64F3At1Ou5+Vzm+WwB+qk+CnwfCQj56Ce+rJcgD4eHIxma4R8FPgn4BTgH2PPuLAlaXZhB6QTz0C97F3Ft55Duoy5CDuPGcxOQH07UTf885APfEXKddfMUL3cq9iSNGaD46DE+33apa6QJdNN2AUX1NGJLH1zkf66+prHDNOtX3n+vUrdv886C37bBJNaVziP5vziDPXS17be5unHiajtsAdwY8J1FzKU946izNBf+9kmk5b/UL4M8uxw6N9uBrYtEQ+obyOaqLsWkQHfvsSFHM7Qb3vsSw5nmAwZBP/tapPD8qTmmeuljp4RHK8GfogaDfF3vB2tGXYYEtY/okKPsyHwfhThB4GfAx9AvWz3xZ5ZGrwn3jB5M+qp/e+E8L+FNu54OHb+TuDk4PfuCc/tEoT3CzSlZhVwIfDqhHtfjQR5DZrK9iPgcGCDhHsBXoZ2Sl8VhP1L4DLUk1w0XQPgg6jn8mWMG3vQ9Pd3o7z8NONl9HngScBeKfFsAl/57CKPQb1/p6K11Y5EI7AAbgeei6atPTV41/4pYeTlc5vlcAlwC/VnFm2FjOUs8MnYtX9F0xNfz/iaii5syVKS7cI2wTGrR3ka9BySZcxV2E0w7XbCRfj3AFunXLsQ2YD4B5t5wBnBteNTnnVNVVviEp92CdqXZ0iX6QH9sAt1dSJN3wbUT78LffXFpOhXnn+vUvdfSj91Fvy2CVyE7ZuqPsz8YnGWkq4fJ5H90WZAfRnKe0cTtF0OeyC5+wgaeXwekuE1KP/Cj27bA59Da9mvAc5Huh2lrHxb/ou89kDo31ysJlIW33XXojLg05eYHIquymFXZBD8tqtNDh37EJ+dFdegXqslkeuPAz6MptBcFvz/I1QRj7IQfSw9Dvg98LHg/yNRIjdCgh6yc3CMT8vZC/WYlV0r7I/BcW3s/NtQb95+wfFENDrr8Yw3II5FhuIpqGLwCVRIx6LervVj9x+ApulsjxpSJwJfBx6JpkMVTdeb0PSqLwPXZqQxXMNsWzRyPkq41u8LM573ia98dpXHe6LpiPejqYnHMNrI8WGUf29FvaILUF5vkhBOXj63XQ4u2DM4Xsj4x4H7UBofBTwzds2FLUmzC2Gl/d6UOE+LnkOyjLkK2zfTbidchb8GeELCeYD3BmF9CDUQQj6CpmKfigYVNEFVW5LFBqiC9AHUCNqDuemM49MudUGeIV2m+2AXXOhEmr7VTb8rffXFpOhXnn/PIq3u31edBb9tgj7YhKo+zPxicb1N049PIXv2GvThfNPgL7pWeF0ZKvKOJmi7HJYFx23Q/jt/Qh/VbkP26TTgpWjU8kbAf6KR1fuijXijlJHvSc5/KFcGed+cutJZ4bruWkYGfPmSSZbDsva4q3LYFRkEf+1qk0Ph1IcsKBHJIkQVINzQ5WlohDaoF2URWvNr58i9cU5BGXgkSmg4uvss4JvB76igLks4txD1wP2Y/E1PoyxAm/MB/F/k/PYoQ+9FU4/i65huHvn9LDRa6nY06ircfORwZIhfggry2Mgzbwf+gPYJuCsW9uMiv/PS9dzgeBGqoCxNuAfU6XMp8Fq0bll0Ol043Wq3lGd94jOfXeXxAcHxkyTPCgo5EzVYd0XLCpwSu56Xz22WgyvCKYZpawvegnp/t0G91CEubEmSXYBRT3LSx4xp0nNIljFXYfvE7IS78O8lfXTFtcjvvhGNwjgDVVTeA/wP5abU16WqLcliU5S+KCtRw+myhPt92aUuyDNky3Qf7IILnUjTt7rpd6WvvpgU/cry71mk1f2hvzoLftsEfbAJVX2Y+cW5ZOltWl37HcEx/t6jgOXB77oyVOQdTdB2OYRlsAv6fhL6mKNRh8XewNPRx7mrgmuPQMuy7IZWs3gwOF9Gvic5/6F4GRT55tSFzgofbeoyMuDLl0yyHJaxA12Ww67IIPhrV5scCqc+xGVnxTzkCH+PeqEeCM4/Da39uiuamnQymhXxquB6XBCfCbwOjSo6JnbtYuR0n8R4Z8UDSDlDNkO9OatKpuN4YEc0iumCyPl3oPw6huQN1+6I/H5zcPwQc3dJXwv8M7AP6pmLfsQMr/+RcX4d+Z2XrnAk0O3A3yNBSeLS4B6Av4pdW4MqLfGpoU3gO59d5PGOwfGKlOtRrkCyv0PCtbx8brMcXLEoOK5JuR6eXxw558qWJNkFGI2aXJ/xEZTTpOeQLGOuwvaJ2Ql34SfpQZQjgL9DlYaN0MiXC1AFJD5iwydVbEkWpwOXI/m5D02bfSeqrH4DfWCMjvDyaZe6IM+QLdN9sAsudCJN3+qm35W++mJS9CvLv2eRVveH/uos+G0T9MEmQDUfZn6xmN5Cel17XoH31ZWhIu9ogrbLIfyIN8Pcj2z3oaVAlqIO0asi1/4A/AStD7+QUWcFFJfvSc1/KFcGeXY49G8PM3dlkCbw3aYuIwO+fMmkymFZO9BVOeySDIK/drXJ4QhnPiS+DNQsmsVQ9O/syLPboMxZgaYf/QxYjQRxPuql+k0QeUjv2TsoOH44Jc6/Cd69Ivh/QzSt+lrmbpISTsv5bUo4SRyMGg43ocyMEk6V+UaBcMJKw7cSrt2MGjFbMldIzkFTcm4A/h31LP9FwvN56QoLfR2qtMxL+bs0dm+cexgfwZXELONycXpw7ZKEa2fkhOczn13lcUhSvqXdk6aMefncVjk0RZIMurAlaXYBRiMuH5MQn2nTcxiXMZdhh8xidqLIPVXsRN3wF5E9CvkOYAhsgTbpuhKtQ/mHAu+dpTm7VFQWQ45CMvErVIG+Ho32+ChabmV57H6fdqkL8gzZMt2UXSha58yirk4k6Zur9LuwByGzmH7F2xBZ/j2NrLp/n3UW/LYJ+lBXgGo+zJdfnKXZurpvvc2qa5eN3wxuZKgos0yG/VyI7OdKxmeFgWT0HpLXsN8CfXyK7/FTp95XlFm6m/9Qrgzy7HDo325CS8xkMYvbfPHdpi5LU76kCLNMlj12JYezTLYMgt92dVlmmSw5BIc+JD6z4lbm9qzn8cvI7yTBWoE2ITkATel5GxIOUOX9IcY30dkbCWza9KQnoOkr9wX/74TSEd9sJey12zAnDSEHob0xbgReEIlnyOLg+IsCYS0Kjmk9m6tQb94ipKygAv81mlZ0MHAIEqLL0GiIMD/y0rUK2I5io/HDaepJ8Xxk5F1ZDBnvmVsKvBytiTkbu7YiJ7wwLB/57CqPb0Q9qc9B6xNn8ZzIM0nk5XNb5eCKsPd2Ucr1x8TuAze2JM0ugGZnhXH6Veza4uA4LXoO4zLmMuyQIWYnsqhiJ1yF/xjG8z/O3ZHfb0GVlSIMcVfuVWxJFU5GHy7j04N92qXFwbFNeYZsmfZhF+rUOZNwpRNJ+lY3/S7tQcgQ0694GyLLvyeRV/fvs86GYftqE/ShrhBS1of58otD3Kavbb3NqmsXwYcMFWXIZNjPndAHv4sS7h8AGwNfYnym1kZozfjvkEzVel9RhvQv/yG5DPLscJmld4a4tRG+29RlacqXFGHIZNljV3I4ZLJlEPy2q8syZLLkMMSJD4l3VrygSiABoSBGheiHaAOcY9H6YJ8Nzm+Jev++z1znuSHamG4Fyb0926E1sy6NnAvXNYuvXxau87oJ+RyCRi9dj/IgvkYsjD42bsZos5U0wsLfFDXG4zwhdl/ImcHfYrSxy/5oWtQFqDfxLvLTdQXa9GQvtIFJGusx2pwoXlGZH8RhZcbzIcOEczNIwc5gblkVYXVw9JXPLvL4M2iK2jvRCLikJQBAayo+C43OOjfhel4+t1kOrvhJcNwm5frWwTG6rp4LW5JmF2Dk/DZjfD2/1ZFrk67nkCxjrsKOMkw4N4PZCahuJ1yFvznjH/yivAZtinUnysN3M1pjMo9hwrkZqpV7FVtShbBc4+uV+7RLq4Njm/IM2TLtwy7UqXMm4UIn0vStbvpd6WuUYcK5GaZXvyDbv8c5hPy6f591Fvy2CfpQV4BqPsyXXxwmnJuhevra1tusunYRfMhQUYYJ52bon/0MZ24lfYDcOePa05FuJ5VdnXpfUYYJ52bodv5Dchnk2eGynRVxZqhuI3y3qcvQpC8pwjDh3Az9tceu5HCYcG6GyZBB8N+uLssw4dwM/ZVDcOhD4stA1SFJEK9BU00Wo4IPOyDSnOfa4G/jlHccFgk3JG2zlVWoR2dbsnkfaqysQIYyqbEC8N3g+OKc8GC0DtzuCdeejCrBKxk1duKsRuvmvg0J6WPRBn6Qn67TUR7uT/Z6xzOokXUL4xujbIvKbUXG875oKp9XUz2PL0Qj8R4dxPfw4H0gndoF9TaehaaqvZW5vYshefncZjm44pLguDfj9ubRqGf6AUblDm5sSZpdABnOW1BFPc406Tkky5irsH1idsJd+EtJL7990KiOG9B03ZuCcLZLud8nVWxJFZ4VHH8WO+/TLnVBniFbpvtgF1zoRJq+1U2/K331xSToF2T79yhF6/591lnw2ybog02o6sOWYn4xSpreZtW1i9AHGSpCm+UQlkHSiOOdM66FNjJedl2S76I0lf+QXAZ5drhMZ4VrfLepy9BnX1KEtu1xV+WwSzII/tvVbdO2HDr1Ia46K+ajit3vmLvpydeR4dkT9ZCFpCnLWtTLswXjI+4OQjuOw3hnxUOM936tA76N1iN7Msl8EG2qd3XwvvjGdVE+HcTvg8D2Cdc3j/w+LTgewdx1ZtdDvUzzGfUghryI5A3PHx8cw6kzeelaiTbxWx/435S4vgw4CW1wciDjm8GFa/FeQvP4zGdXeQwakXdg8MyxjKbfPhH4HvB2pJx7A19ICSMvn9sshyosQYZo/ci5W5HxHzDajybkKNQbeyayHeDOlqTZhZAvkfwxY5r0HJJlzFXYPjE74Sb8LdFU2KTprs9FI0buCJ6/G+X3AuQ3m6asLQlJsks7oI9+cbYAPhH8Pjty3rdd6oI8Q7ZM98EuQH2dSNM3F+mvGzefTIJ+haT595Aydf8+6yz4bRN03SZU9WHmF+eSpreQX9fOo+syVJQ2y2EZWgc8aSZQ1mjkpI9/XZPvorjMfyhfBll2OPRva2l+8GFTbeqi9NWXFKVte9xFOeyaDILfdnUXqCKHrmyhcx+SVBmuwlPQ2offYa7xuAc4L+H+rFFRx6Eeq6+hzaDuRAnfGgnHtowc6yPQzu3XMj4VHLTD/N8CfwP8NHbtjcDRqGfscrQubJxZRpuY3IiE92Q0SuorqGd3E6RY96HRWaBNRP4NzQS5HhXa79AIrB3RdLcTYu/6PFq7+YrgvfPQ6Km/Rg2qbxZMF0G6FqK1ba9F08ZvQOX9bKSkDwCvi4UbsjfKl68kXPONz3x2mcegxuppaBrb84EPoGn8y4GrkPFNWs4sJC+f2yyH/YI/0PQtUA/qGcHvXwOHxp65GBmvLZm7vt6BqKxOQh8GfgzsisrxZuBfIve6sCV5dgE0zfRSpBNrI+enSc8hXcZchO0TsxNuwt8H+BzjS5XtBJwfnH8ho7Vhz0W69nKUJ5dnxNsHZWxJSJJdehXwflRRXYnkZQmwL1qO8uvoI2KIb7vUFXmGbJnuul0IqaMTWfrmIv117YFP+qxfUdL8O5Sr+0+CzoLfNkFXbUIdH2Z+sZjeFqlrF6GrMlSWNsphA/Rh9zqSNy5dBvyc5A7ZZShfww+IXZXvorjKfyivC5Buh0P/dh3F9qB0SVNt6qL00ZeUpS17HNI1OeyaDILfdnVXKCuHLmyhFx/iqrMia5phEqGDvDHh2tloGahD0HpXdwJfReuDXYN6A38b3PtU1AOUNiXoi2iDvTegneajbBkc1wvelcRlzN1x/VTU0DgUTefeD1UArkPrnEV5H2rAvDN4//qop+sI4ETGKxXvR4ZlGaooP4gqGO9DShNVzqx0gRToMNTjdxBStBcgxZwN3v8x4PaEZxcF6To/5XoT+Mpnl3kc8hDqvbwZGbPVJK89Fycvn9suh6WoUR9lq+APlG/xzoo0bkWN96PRiMF9kAE7CfXwRje0dGFL8uxCGKfz0ceCr8auTYOeQ7aM1Q27CcxO1A//tcjPRnkyaiSsQ/lwa+z64WikyQmMRqc0RRlbksUlaODD01En7EKUZ1egwRJnMbci2oRd6oI8Q7ZM98EuhFTRiTx9c5X+qvrqmz7rV5Qs/16m7j8JOgt+2wRdtAl1fZj5xWJ6W6SuXYQuylAV2iiHHVEZJNnOLdAI628nXNsAfUS8GuVzl+W7KK7yH8rrAqTb4bzOdZ801aYuQh99SRXasschXZPDLskg+G9Xd4Wm5dCbD5m3fPnyMve3yevRlJX3ktyTmMbhaBrPMkbrxk4CvtL1LiTIu9Hd0RNN4VN28vLZysE/m6IpbK9sOyIZtCmDRjH6WkbPBF4NvMdxuEb/mdR6Ux5mEyeHPvh3l1ibwA3mFw3DqMq01p2KMG2+pE1MDtMxOewZXeusWA9Nob4rdn4vNFXoHjTd8f4SYW6IdkW/Dnhp/Sh2Bh/peiTqCbuS6WngZeFLdvLy2cqhOfZHdufctiOSQlsyaBSnj2W0APgUWgLlQcdhG/1nUutNWZhNnDy67t9dYm2C+phfNAyjDtNYdyrCtPmStjE5TMbksIfMbzsCMbYHbkNriH0U+Djq9boITQl6OeU6KkAVztejaU8LncW0fXykawD8B8WX95l0fMnOgOx8zrtuuOPLuFsOzwdtyaBRnD6W0fPQhlf2QcZIYlLrTVkMMJs4aXTdv7vE2gT1Mb9oGEYdprHuVIQB0+VL2sbkMJkBJoe9o2szK7ZFG2zvimZYPIw28zgfdV78qr2oGYZhGIZhGIZhGIZhGIZhGIbhg66NOPoJ8Iq2I2EYhmEYhmEYhmEYhmEYhmEYRnN0bRkowzAMwzAMwzAMwzAMwzAMwzCmDOusMAzDMAzDMAzDMAzDMAzDMAyjVayzwjAMwzAMwzAMwzAMwzAMwzCMVvkzpxfH7jJlf2MAAAAASUVORK5CYII=\n", "text/latex": [ "$\\displaystyle - M g l \\left(2 \\cos{\\left(Θ \\right)} + \\cos{\\left(Φ \\right)}\\right) + 1.0 M l \\left(\\cos{\\left(Θ \\right)} \\dot{Θ} + \\cos{\\left(Φ \\right)} \\dot{Φ}\\right) \\dot{x} + 0.5 M l \\cos{\\left(Θ - Φ \\right)} \\dot{Θ} \\dot{Φ} + 0.5 M \\left(2 l \\cos{\\left(Θ \\right)} \\dot{Θ} + \\dot{x}\\right) \\dot{x} + 0.5 l^{2} \\dot{Θ}^{2} + 0.5 m \\dot{x}^{2} + 0.5 \\left(I + M l^{2}\\right) \\dot{Θ}^{2} + 0.5 \\left(I + M l^{2}\\right) \\dot{Φ}^{2} + 0.5 \\dot{x}^{2}$" ], "text/plain": [ " \n", "-M⋅g⋅l⋅(2⋅cos(Θ) + cos(Φ)) + 1.0⋅M⋅l⋅(cos(Θ)⋅Θ̇ + cos(Φ)⋅Φ̇)⋅ẋ + 0.5⋅M⋅l⋅cos(\n", "\n", " 2 2 2 ⎛ 2⎞ \n", "Θ - Φ)⋅Θ̇⋅Φ̇ + 0.5⋅M⋅(2⋅l⋅cos(Θ)⋅Θ̇ + ẋ)⋅ẋ + 0.5⋅l ⋅Θ̇ + 0.5⋅m⋅ẋ + 0.5⋅⎝I\n", "\n", "2 ⎛ 2⎞ 2 2\n", " + M⋅l ⎠⋅Θ̇ + 0.5⋅⎝I + M⋅l ⎠⋅Φ̇ + 0.5⋅ẋ " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# the lagrangian\n", "L = K - P\n", "\n", "print('----\\nThe Lagrangian of the system is:\\n----')\n", "L" ] }, { "cell_type": "markdown", "id": "touched-percentage", "metadata": {}, "source": [ "### 3.5. The Euler-Lagrange Equations [☝](#contents)\n", "\n", "The standard [Euler-Lagrange equation](https://www.ucl.ac.uk/~ucahmto/latex_html/chapter2_latex2html/node5.html) is:\n", "\n", "$$\\frac{d}{dt}\\frac{\\partial \\mathcal{L}}{\\partial \\dot{x}} - \\frac{\\partial \\mathcal{L}}{\\partial x} = 0$$\n", "\n", "To introduce the generalised force $Q^{P}$ acting on the cart, the [Lagrange-D'Alembert Principle](https://en.wikipedia.org/wiki/D%27Alembert%27s_principle) is used:\n", "\n", "\\begin{equation}\n", "\\frac{d}{dt}\\frac{\\partial \\mathcal{L}}{\\partial \\dot{x}} - \\frac{\\partial \\mathcal{L}}{\\partial x} = Q^{P}\n", "\\tag{10}\n", "\\end{equation}\n", "\n", "Therefore, for a three-dimensional _working_ system, the equations of motion can be derived as:\n", "\n", "\\begin{equation}\n", "\\frac{d}{dt}\\frac{\\partial \\mathcal{L}}{\\partial \\dot{x}} - \\frac{\\partial \\mathcal{L}}{\\partial x} = u\n", "\\tag{11}\n", "\\end{equation}\n", "\n", "\\begin{equation}\n", "\\frac{d}{dt}\\frac{\\partial \\mathcal{L}}{\\partial \\dot{\\theta}} - \\frac{\\partial \\mathcal{L}}{\\partial \\theta} = 0\n", "\\tag{12}\n", "\\end{equation}\n", "\n", "\\begin{equation}\n", "\\frac{d}{dt}\\frac{\\partial \\mathcal{L}}{\\partial \\dot{\\phi}} - \\frac{\\partial \\mathcal{L}}{\\partial \\phi} = 0\n", "\\tag{13}\n", "\\end{equation}" ] }, { "cell_type": "code", "execution_count": 9, "id": "broadband-arbitration", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# euler-lagrange formulation\n", "\"\"\"\n", "`expand()`: allows cancellation of like terms\n", "`collect()`: collects common powers of a term in an expression\n", "\"\"\"\n", "\n", "euler_1 = Eq((L.diff(x_dot).diff(t) - L.diff(x)).simplify().expand().collect(x.diff(t, t)), u)\n", "euler_2 = Eq((L.diff(Θ_dot).diff(t) - L.diff(Θ)).simplify().expand().collect(Θ.diff(t, t)), 0)\n", "euler_3 = Eq((L.diff(Φ_dot).diff(t) - L.diff(Φ)).simplify().expand().collect(Φ.diff(t, t)), 0)" ] }, { "cell_type": "code", "execution_count": 10, "id": "processed-membrane", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "The Euler-Lagrange equations:\n", "----\n", "1.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle - 2.0 M l \\sin{\\left(Θ \\right)} \\dot{Θ}^{2} - 1.0 M l \\sin{\\left(Φ \\right)} \\dot{Φ}^{2} + 2.0 M l \\cos{\\left(Θ \\right)} \\ddot{Θ} + 1.0 M l \\cos{\\left(Φ \\right)} \\ddot{Φ} + \\left(1.0 M + 1.0 m + 1.0\\right) \\ddot{x} = u$" ], "text/plain": [ " 2 2 \n", "- 2.0⋅M⋅l⋅sin(Θ)⋅Θ̇ - M⋅l⋅sin(Φ)⋅Φ̇ + 2.0⋅M⋅l⋅cos(Θ)⋅Θ̈ + 1.0⋅M⋅l⋅cos(Φ)⋅Φ̈ \n", "\n", " \n", "+ (1.0⋅M + 1.0⋅m + 1.0)⋅ẍ = u" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\nThe Euler-Lagrange equations:\\n----\\n1.\\n----')\n", "euler_1" ] }, { "cell_type": "code", "execution_count": 11, "id": "circular-helicopter", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "2.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle - 2.0 M g l \\sin{\\left(Θ \\right)} + 0.5 M l \\sin{\\left(Θ - Φ \\right)} \\dot{Φ}^{2} + 0.5 M l \\cos{\\left(Θ - Φ \\right)} \\ddot{Φ} + 2.0 M l \\cos{\\left(Θ \\right)} \\ddot{x} + \\left(1.0 I + 1.0 M l^{2} + 1.0 l^{2}\\right) \\ddot{Θ} = 0$" ], "text/plain": [ " 2 \n", "-2.0⋅M⋅g⋅l⋅sin(Θ) + 0.5⋅M⋅l⋅sin(Θ - Φ)⋅Φ̇ + 0.5⋅M⋅l⋅cos(Θ - Φ)⋅Φ̈ + 2.0⋅M⋅l⋅c\n", "\n", " ⎛ 2 2⎞ \n", "os(Θ)⋅ẍ + ⎝1.0⋅I + 1.0⋅M⋅l + 1.0⋅l ⎠⋅Θ̈ = 0" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\n2.\\n----')\n", "euler_2" ] }, { "cell_type": "code", "execution_count": 12, "id": "guided-attitude", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "3.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle - 1.0 M g l \\sin{\\left(Φ \\right)} - 0.5 M l \\sin{\\left(Θ - Φ \\right)} \\dot{Θ}^{2} + 0.5 M l \\cos{\\left(Θ - Φ \\right)} \\ddot{Θ} + 1.0 M l \\cos{\\left(Φ \\right)} \\ddot{x} + \\left(1.0 I + 1.0 M l^{2}\\right) \\ddot{Φ} = 0$" ], "text/plain": [ " 2 \n", "-M⋅g⋅l⋅sin(Φ) - 0.5⋅M⋅l⋅sin(Θ - Φ)⋅Θ̇ + 0.5⋅M⋅l⋅cos(Θ - Φ)⋅Θ̈ + 1.0⋅M⋅l⋅cos(Φ\n", "\n", " ⎛ 2⎞ \n", ")⋅ẍ + ⎝1.0⋅I + 1.0⋅M⋅l ⎠⋅Φ̈ = 0" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\n3.\\n----')\n", "euler_3" ] }, { "cell_type": "markdown", "id": "incorrect-congress", "metadata": {}, "source": [ "### 3.6. Linearisation and Acceleration [☝](#contents)\n", "\n", "| | | |\n", "| :-: | :-: | :-: |\n", "| $$\\sin(\\theta)$$ | $$\\approx$$ | $$\\theta$$ | \n", "| $$\\cos(\\theta)$$ | $$=$$ | $$1$$ |\n", "| $$\\dot\\theta^{2}$$ | $$=$$ | $$0$$ |\n", "| $$\\sin(\\phi)$$ | $$\\approx$$ | $$\\phi$$ |\n", "| $$\\cos(\\phi)$$ | $$=$$ | $$1$$ |\n", "| $$\\dot\\phi^{2}$$ | $$=$$ | $$0$$ |\n", "| $$\\sin(\\theta - \\phi)$$ | $$\\approx$$ | $$\\theta - \\phi$$ |\n", "| $$\\cos(\\theta - \\phi)$$ | $$=$$ | $$1$$ |\n", "\n", "The pendulum will achieve equilibrium when vertical, i.e. $\\theta=0$ & $\\phi=0$. Using the above [small-angle approximations](https://brilliant.org/wiki/small-angle-approximation/) to simiplify the derived differential equations of motion, and solving for all three accelerations." ] }, { "cell_type": "code", "execution_count": 13, "id": "solid-title", "metadata": {}, "outputs": [], "source": [ "# linearise the system\n", "matrix = [\n", " (sin_theta, Θ), \n", " (cos_theta, 1), \n", " (Θ_dot**2, 0), \n", " (sin_phi, Φ), \n", " (cos_phi, 1), \n", " (Φ_dot**2, 0),\n", " (sin(Θ - Φ), Θ - Φ), \n", " (cos(Θ - Φ), 1)\n", "]\n", "\n", "linear_1 = euler_1.subs(matrix)\n", "linear_2 = euler_2.subs(matrix)\n", "linear_3 = euler_3.subs(matrix)" ] }, { "cell_type": "code", "execution_count": 14, "id": "final-bahrain", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "The linearised equations are:\n", "----\n", "1.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle 2.0 M l \\ddot{Θ} + 1.0 M l \\ddot{Φ} + \\left(1.0 M + 1.0 m + 1.0\\right) \\ddot{x} = u$" ], "text/plain": [ "2.0⋅M⋅l⋅Θ̈ + 1.0⋅M⋅l⋅Φ̈ + (1.0⋅M + 1.0⋅m + 1.0)⋅ẍ = u" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\nThe linearised equations are:\\n----\\n1.\\n----')\n", "linear_1" ] }, { "cell_type": "code", "execution_count": 15, "id": "painted-smoke", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "2.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle - 2.0 M g l Θ + 2.0 M l \\ddot{x} + 0.5 M l \\ddot{Φ} + \\left(1.0 I + 1.0 M l^{2} + 1.0 l^{2}\\right) \\ddot{Θ} = 0$" ], "text/plain": [ " ⎛ 2 2⎞ \n", "-2.0⋅M⋅g⋅l⋅Θ + 2.0⋅M⋅l⋅ẍ + 0.5⋅M⋅l⋅Φ̈ + ⎝1.0⋅I + 1.0⋅M⋅l + 1.0⋅l ⎠⋅Θ̈ = 0" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\n2.\\n----')\n", "linear_2" ] }, { "cell_type": "code", "execution_count": 16, "id": "intellectual-poison", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "3.\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle - 1.0 M g l Φ + 1.0 M l \\ddot{x} + 0.5 M l \\ddot{Θ} + \\left(1.0 I + 1.0 M l^{2}\\right) \\ddot{Φ} = 0$" ], "text/plain": [ " ⎛ 2⎞ \n", "-M⋅g⋅l⋅Φ + 1.0⋅M⋅l⋅ẍ + 0.5⋅M⋅l⋅Θ̈ + ⎝1.0⋅I + 1.0⋅M⋅l ⎠⋅Φ̈ = 0" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\n3.\\n----')\n", "linear_3" ] }, { "cell_type": "code", "execution_count": 19, "id": "statewide-thomas", "metadata": {}, "outputs": [], "source": [ "# simplify for linear and angular acceleration\n", "final_equations = linsolve([linear_1, linear_2, linear_3], [x.diff(t, t), Θ.diff(t, t), Φ.diff(t, t)])\n", "\n", "x_ddot = final_equations.args[0][0].expand().collect((Θ, Θ_dot, x, x_dot, Φ, Φ_dot, u, M, m, l, I)).simplify()\n", "Θ_ddot = final_equations.args[0][1].expand().collect((Θ, Θ_dot, x, x_dot, Φ, Φ_dot, u, M, m, l, I)).simplify()\n", "Φ_ddot = final_equations.args[0][2].expand().collect((Θ, Θ_dot, x, x_dot, Φ, Φ_dot, u, M, m, l, I)).simplify()" ] }, { "cell_type": "code", "execution_count": 20, "id": "appropriate-tumor", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "Acceleration of the cart:\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\frac{- M^{2} g l^{2} \\left(4.0 I + 4.0 M l^{2} - 1.0 M l\\right) Θ - 1.0 M^{2} g l^{2} \\left(I + M l^{2} - M l + l^{2}\\right) Φ + u \\left(1.0 I^{2} + 2.0 I M l^{2} + 1.0 I l^{2} + 1.0 M^{2} l^{4} - 0.25 M^{2} l^{2} + 1.0 M l^{4}\\right)}{1.0 I^{2} + 1.0 I l^{2} + 1.0 I m \\left(I + l^{2}\\right) - M^{3} l^{2} \\left(4.0 l^{2} - 2.0 l + 0.25\\right) - M^{2} l^{2} \\left(3.0 I - 1.0 l^{2} m - 1.0 l^{2} + 0.25 m + 0.25\\right) + M \\left(1.0 I^{2} + 2.0 I l^{2} m + 3.0 I l^{2} + 1.0 l^{4} m + 1.0 l^{4}\\right)}$" ], "text/plain": [ " 2 2 ⎛ 2 ⎞ 2 2 ⎛ 2 \n", " - M ⋅g⋅l ⋅⎝4.0⋅I + 4.0⋅M⋅l - M⋅l⎠⋅Θ - M ⋅g⋅l ⋅⎝I + M⋅l - M⋅l + \n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎛ 2⎞ 3 2 ⎛ 2 ⎞ 2 2 ⎛\n", "1.0⋅I + 1.0⋅I⋅l + 1.0⋅I⋅m⋅⎝I + l ⎠ - M ⋅l ⋅⎝4.0⋅l - 2.0⋅l + 0.25⎠ - M ⋅l ⋅⎝\n", "\n", " 2⎞ ⎛ 2 2 2 2 4 2 2 4⎞\n", "l ⎠⋅Φ + u⋅⎝1.0⋅I + 2.0⋅I⋅M⋅l + 1.0⋅I⋅l + 1.0⋅M ⋅l - 0.25⋅M ⋅l + 1.0⋅M⋅l ⎠\n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎞ ⎛ 2 2 2 \n", "3.0⋅I - l ⋅m - l + 0.25⋅m + 0.25⎠ + M⋅⎝1.0⋅I + 2.0⋅I⋅l ⋅m + 3.0⋅I⋅l + 1.0⋅l\n", "\n", " \n", " \n", "─────────────\n", "4 4⎞\n", " ⋅m + 1.0⋅l ⎠" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\nAcceleration of the cart:\\n----')\n", "x_ddot" ] }, { "cell_type": "code", "execution_count": 21, "id": "sustainable-nitrogen", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "Acceleration of the first pendulum:\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\frac{M l \\left(- M g l \\left(- 2.0 M l + 0.5 M + 0.5 m + 0.5\\right) Φ + 2.0 g \\left(I M + I m + I + M l^{2} m + M l^{2}\\right) Θ - u \\left(2.0 I + 2.0 M l^{2} - 0.5 M l\\right)\\right)}{1.0 I^{2} + 1.0 I l^{2} + 1.0 I m \\left(I + l^{2}\\right) - M^{3} l^{2} \\left(4.0 l^{2} - 2.0 l + 0.25\\right) - M^{2} l^{2} \\left(3.0 I - 1.0 l^{2} m - 1.0 l^{2} + 0.25 m + 0.25\\right) + M \\left(1.0 I^{2} + 2.0 I l^{2} m + 3.0 I l^{2} + 1.0 l^{4} m + 1.0 l^{4}\\right)}$" ], "text/plain": [ " ⎛ \n", " M⋅l⋅⎝-M⋅g⋅l⋅(-2.0⋅M⋅l + 0.5⋅M + 0.5⋅m + 0.5)⋅Φ + 2.0⋅g\n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎛ 2⎞ 3 2 ⎛ 2 ⎞ 2 2 ⎛\n", "1.0⋅I + 1.0⋅I⋅l + 1.0⋅I⋅m⋅⎝I + l ⎠ - M ⋅l ⋅⎝4.0⋅l - 2.0⋅l + 0.25⎠ - M ⋅l ⋅⎝\n", "\n", " ⎛ 2 2⎞ ⎛ 2 ⎞⎞ \n", "⋅⎝I⋅M + I⋅m + I + M⋅l ⋅m + M⋅l ⎠⋅Θ - u⋅⎝2.0⋅I + 2.0⋅M⋅l - 0.5⋅M⋅l⎠⎠ \n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎞ ⎛ 2 2 2 \n", "3.0⋅I - l ⋅m - l + 0.25⋅m + 0.25⎠ + M⋅⎝1.0⋅I + 2.0⋅I⋅l ⋅m + 3.0⋅I⋅l + 1.0⋅l\n", "\n", " \n", " \n", "─────────────\n", "4 4⎞\n", " ⋅m + 1.0⋅l ⎠" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\nAcceleration of the first pendulum:\\n----')\n", "Θ_ddot" ] }, { "cell_type": "code", "execution_count": 22, "id": "sudden-fault", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "----\n", "Acceleration of the second pendulum:\n", "----\n" ] }, { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\frac{M l \\left(- M g l \\left(- 4.0 M l + 1.0 M + 1.0 m + 1.0\\right) Θ + g \\left(1.0 I M + 1.0 I m + 1.0 I - 3.0 M^{2} l^{2} + 1.0 M l^{2} m + 2.0 M l^{2} + 1.0 l^{2} m + 1.0 l^{2}\\right) Φ - 1.0 u \\left(I + M l^{2} - M l + l^{2}\\right)\\right)}{1.0 I^{2} + 1.0 I l^{2} + 1.0 I m \\left(I + l^{2}\\right) - M^{3} l^{2} \\left(4.0 l^{2} - 2.0 l + 0.25\\right) - M^{2} l^{2} \\left(3.0 I - 1.0 l^{2} m - 1.0 l^{2} + 0.25 m + 0.25\\right) + M \\left(1.0 I^{2} + 2.0 I l^{2} m + 3.0 I l^{2} + 1.0 l^{4} m + 1.0 l^{4}\\right)}$" ], "text/plain": [ " ⎛ ⎛ \n", " M⋅l⋅⎝-M⋅g⋅l⋅(-4.0⋅M⋅l + 1.0⋅M + 1.0⋅m + 1.0)⋅Θ + g⋅⎝1.0⋅I⋅M + 1.0⋅I⋅m + 1.0\n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎛ 2⎞ 3 2 ⎛ 2 ⎞ 2 2 ⎛\n", "1.0⋅I + 1.0⋅I⋅l + 1.0⋅I⋅m⋅⎝I + l ⎠ - M ⋅l ⋅⎝4.0⋅l - 2.0⋅l + 0.25⎠ - M ⋅l ⋅⎝\n", "\n", " 2 2 2 2 2 2⎞ ⎛ 2 \n", "⋅I - 3.0⋅M ⋅l + 1.0⋅M⋅l ⋅m + 2.0⋅M⋅l + 1.0⋅l ⋅m + 1.0⋅l ⎠⋅Φ - u⋅⎝I + M⋅l - \n", "──────────────────────────────────────────────────────────────────────────────\n", " 2 2 ⎞ ⎛ 2 2 2 \n", "3.0⋅I - l ⋅m - l + 0.25⋅m + 0.25⎠ + M⋅⎝1.0⋅I + 2.0⋅I⋅l ⋅m + 3.0⋅I⋅l + 1.0⋅l\n", "\n", " 2⎞⎞ \n", "M⋅l + l ⎠⎠ \n", "─────────────\n", "4 4⎞\n", " ⋅m + 1.0⋅l ⎠" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print('----\\nAcceleration of the second pendulum:\\n----')\n", "Φ_ddot " ] }, { "cell_type": "markdown", "id": "blank-turtle", "metadata": {}, "source": [ "## 4. Proximal Policy Optimisation [☝](#contents)" ] }, { "cell_type": "markdown", "id": "cognitive-chess", "metadata": {}, "source": [ "### 4.1. Overview1 [☝](#contents)\n", " \n", " * State-of-the-art Policy Gradient method.\n", " * An on-policy algorithm.\n", " * Can be used for environments with either discrete or continuous action spaces.\n", " * **PPO-Clip** doesn’t have a KL-divergence term in the objective and doesn’t have a constraint at all. Instead relies on specialized clipping in the objective function to remove incentives for the new policy to get far from the old policy.\n", "\n", "---\n", "1Referenced from [OpenAI](https://spinningup.openai.com/en/latest/algorithms/ppo.html) " ] }, { "cell_type": "markdown", "id": "waiting-elizabeth", "metadata": {}, "source": [ "### 4.2. Mathematical Model1 [☝](#contents)\n", "\n", "$$ \\begin{equation}\\mathbf{\n", " L^{PPO} (\\theta)=\\mathbb{\\hat{E}}_t\\:[L^{CLIP}(\\theta)-c_1L^{VF}(\\theta)+c_2S[\\pi_\\theta](s_t)]}\n", " \\end{equation}$$ \n", " \n", "1. $ L^{CLIP} (\\theta)=\\mathbb{\\hat{E}}_t[\\min(r_t(\\theta)\\:\\hat{A}^t,\\:\\:clip(r_t(\\theta),\\:\\:1-\\epsilon,\\:\\:1+\\epsilon)\\hat{A}^t)]$
\n", "\n", "     - $r_t(\\theta)\\:\\hat{A}^t$: Surrogate objective is the probability ratio between a new policy network and an older policy network.
\n", "     - $\\epsilon$: Hyper-parameter; usually with a value of 0.2.
\n", "     - clip$(r_t(\\theta),\\:\\:1-\\epsilon,\\:\\:1+\\epsilon)\\:\\hat{A}^t$: Clipped version of the surrogate objective, where the probability ratio is truncated.
\n", "\n", "2. $c_1L^{VF}(\\theta)$: Determines desirability of the current state.\n", "\n", "3. $c_2S[\\pi_\\theta](s_t)$: The entropy term using Gaussian Distribution.\n", "\n", "---\n", "1Referenced from [Rich Sutton et al.](http://arxiv.org/abs/1707.06347)" ] }, { "cell_type": "markdown", "id": "shaped-newfoundland", "metadata": {}, "source": [ "### 4.3. Neural Network (NN) — A2C1 [☝](#contents)\n", "\n", "\n", "
Figure: Advantage Actor Critic (A2C) Architecture2
\n", "\n", "The input is a representation of the current state. One output is a probability distribution over moves — **the actor**. The other output represents the expected return from the current position — **the critic**.3\n", "\n", "* Each output serves as a sort of regularizer on the other[regularization is any technique to prevent your model from overfitting to the exact data set it was trained on] \n", "* Taking the game of Go as an example, imagine that a group of stones on the board is in danger of getting captured. This fact is relevant for the value output, because the player with the weak stones is probably behind. It’s also relevant to the action output, because you probably want to either attack or defend the weak stones. If your network learns a “weak stone” detector in the early layers, that’s relevant to both outputs. Training on both outputs forces the network to learn a representation that’s useful for both goals. This can often improve generalization and sometimes even speed up training.\n", "\n", "\n", "Actor-critic methods exhibit two significant advantages2:\n", "\n", "- They require minimal computation in order to select actions. Consider a case where there are an infinite number of possible actions — for example, a continuous-valued action. Any method learning just action values must search through this infinite set in order to pick an action. If the policy is explicitly stored, then this extensive computation may not be needed for each action selection.\n", "- They can learn an explicitly stochastic policy; that is, they can learn the optimal probabilities of selecting various actions. This ability turns out to be useful in competitive and non-Markov cases (e.g., see Singh, Jaakkola, and Jordan, 1994).\n", "\n", "-----\n", "1Code referenced from [Machine Learning With Phil](https://github.com/philtabor/Youtube-Code-Repository)
\n", "2Referenced from [Deep Learning and the Game of Go](https://livebook.manning.com/book/deep-learning-and-the-game-of-go/chapter-12/)
\n", "3Referenced from [Actor-Critic Methods](http://incompleteideas.net/book/first/ebook/node66.html)
" ] }, { "cell_type": "markdown", "id": "scientific-malta", "metadata": {}, "source": [ "#### 4.3.1. Actor [☝](#contents)\n", "\n", "The “Actor” updates the policy distribution in the direction suggested by the Critic (such as with policy gradients).1\n", " \n", "---\n", "1Referenced from [Understanding Actor Critic Methods and A2C](https://towardsdatascience.com/understanding-actor-critic-methods-931b97b6df3f)\n" ] }, { "cell_type": "code", "execution_count": 19, "id": "julian-iraqi", "metadata": {}, "outputs": [], "source": [ "class ActorNetwork(nn.Module):\n", " # constructor\n", " def __init__(self, num_actions, input_dimensions, learning_rate_alpha,\n", " fully_connected_layer_1_dimensions=256, fully_connected_layer_2_dimensions=256):\n", " # call super-constructor \n", " super(ActorNetwork, self).__init__()\n", " \n", " # neural network setup\n", " self.actor = nn.Sequential(\n", " # linear layers unpack input_dimensions\n", " nn.Linear(*input_dimensions, fully_connected_layer_1_dimensions),\n", " # ReLU: applies the rectified linear unit function element-wise\n", " nn.ReLU(),\n", " nn.Linear(fully_connected_layer_1_dimensions, fully_connected_layer_2_dimensions),\n", " nn.ReLU(),\n", " nn.Linear(fully_connected_layer_2_dimensions, num_actions),\n", " \n", " # softmax activation function: a mathematical function that converts a vector of numbers \n", " # into a vector of probabilities, where the probabilities of each value are proportional to the \n", " # relative scale of each value in the vector.\n", " nn.Softmax(dim=-1)\n", " )\n", " \n", " # optimizer: an optimization algorithm that can be used instead of the classical stochastic \n", " # gradient descent procedure to update network weights iterative based in training data\n", " self.optimizer = optim.Adam(self.parameters(), lr=learning_rate_alpha)\n", " \n", " # handle type of device\n", " self.device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')\n", " self.to(self.device)\n", "\n", " # pass state forward through the NN: calculate series of probabilities to draw from a distribution\n", " # to get actual action. Use action to get log probabilities for the calculation of the two probablities\n", " # for the learning function\n", " def forward(self, state):\n", " dist = self.actor(state)\n", " dist = Categorical(dist)\n", " return dist" ] }, { "cell_type": "markdown", "id": "frozen-christopher", "metadata": {}, "source": [ "#### 4.3.2. Critic [☝](#contents)\n", "\n", "The “Critic” estimates the value function. This could be the action-value (the Q value) or state-value (the V value).1\n", "\n", "---\n", "1Referenced from [Understanding Actor Critic Methods and A2C](https://towardsdatascience.com/understanding-actor-critic-methods-931b97b6df3f)" ] }, { "cell_type": "code", "execution_count": 20, "id": "armed-orchestra", "metadata": {}, "outputs": [], "source": [ "# [NOTE: See the above comments in the `ActorNetwork` for individual function explanation] \n", "class CriticNetwork(nn.Module):\n", " def __init__(self, input_dimensions, learning_rate_alpha, fully_connected_layer_1_dimensions=256, \n", " fully_connected_layer_2_dimensions=256):\n", " super(CriticNetwork, self).__init__()\n", "\n", " self.critic = nn.Sequential(\n", " nn.Linear(*input_dimensions, fully_connected_layer_1_dimensions),\n", " nn.ReLU(),\n", " nn.Linear(fully_connected_layer_1_dimensions, fully_connected_layer_2_dimensions),\n", " nn.ReLU(),\n", " nn.Linear(fully_connected_layer_2_dimensions, 1)\n", " )\n", " \n", " # same learning rate for both actor & critic -> actor is much more sensitive to the changes in the underlying\n", " # parameters\n", " self.optimizer = optim.Adam(self.parameters(), lr=learning_rate_alpha)\n", " self.device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')\n", " self.to(self.device)\n", "\n", " def forward(self, state):\n", " value = self.critic(state)\n", " return value" ] }, { "cell_type": "markdown", "id": "guilty-salon", "metadata": {}, "source": [ "#### 4.3.3. Agent 1 [☝](#contents)\n", " \n", "The agent is the component that makes the *decision* of what action to take.\n", "\n", "* The agent is allowed to use any observation from the environment, and any internal rules that it has. Those internal rules can be anything, but typically, it expects the current state to be provided by the environment, for that state to utilise the [Markov chain](https://en.wikipedia.org/wiki/Markov_chain), and then it processes that state using a policy function that decides what action to take.\n", "\n", "* In addition, to handle a reward signal (received from the environment) and optimise the agent towards maximising the expected reward in future, the agent will maintain some data which is influenced by the rewards it received in the past, and use that to construct a better policy.\n", "\n", "---\n", "1Referenced from [Neil Slater](https://ai.stackexchange.com/questions/8476/what-does-the-agent-in-reinforcement-learning-exactly-do)" ] }, { "cell_type": "code", "execution_count": 21, "id": "dying-apache", "metadata": {}, "outputs": [], "source": [ "# storage class\n", "class ExperienceCollector:\n", " # constructor - init values to empty lists\n", " def __init__(self, batch_size):\n", " self.states_encountered = []\n", " self.probability = []\n", " self.values = []\n", " self.actions = []\n", " self.rewards = []\n", " self.terminal_flag = []\n", "\n", " self.batch_size = batch_size\n", "\n", " # generate batches - defines the number of samples that will be propagated through the network\n", " def generate_batches(self):\n", " num_states = len(self.states_encountered)\n", " batch_start = np.arange(0, num_states, self.batch_size)\n", " idx = np.arange(num_states, dtype=np.int64)\n", " np.random.shuffle(idx) # shuffle to handle stochastic gradient descent\n", " batches = [idx[i:i+self.batch_size] for i in batch_start]\n", " \n", " # NOTE: maintain return order\n", " return np.array(self.states_encountered),\\\n", " np.array(self.actions),\\\n", " np.array(self.probability),\\\n", " np.array(self.values),\\\n", " np.array(self.rewards),\\\n", " np.array(self.terminal_flag),\\\n", " batches\n", " \n", " # store results from previous state\n", " def memory_storage(self, states_encountered, action, probability, values, reward, terminal_flag):\n", " self.states_encountered.append(states_encountered)\n", " self.actions.append(action)\n", " self.probability.append(probability)\n", " self.values.append(values)\n", " self.rewards.append(reward)\n", " self.terminal_flag.append(terminal_flag)\n", "\n", " # clear memory after retrieving state\n", " def memory_clear(self):\n", " self.states_encountered = []\n", " self.probability = []\n", " self.actions = []\n", " self.rewards = []\n", " self.terminal_flag = []\n", " self.values = []\n", "\n", "# defines the agent \n", "class Agent:\n", " def __init__(self, num_actions, input_dimensions, gamma=0.99, learning_rate_alpha=3e-4, gae_lambda=0.95,\n", " policy_clip=0.2, batch_size=64, num_epochs=10):\n", " # save parameters\n", " self.gamma = gamma\n", " self.policy_clip = policy_clip\n", " self.num_epochs = num_epochs\n", " self.gae_lambda = gae_lambda\n", "\n", " self.actor = ActorNetwork(num_actions, input_dimensions, learning_rate_alpha)\n", " self.critic = CriticNetwork(input_dimensions, learning_rate_alpha)\n", " self.memory = ExperienceCollector(batch_size)\n", " \n", " # store memory; interface function\n", " def interface_agent_memory(self, state, action, probability, values, reward, terminal_flag):\n", " self.memory.memory_storage(state, action, probability, values, reward, terminal_flag)\n", " \n", " # choosing an action\n", " def action_choice(self, observation):\n", " # convert numpy array to a tensor\n", " state = T.tensor([observation], dtype=T.float).to(self.actor.device)\n", " \n", " # distribution for choosing an action\n", " dist = self.actor(state)\n", " # value of the state\n", " value = self.critic(state)\n", " # sample distribution to get action\n", " action = dist.sample()\n", "\n", " # squeeze to eliminate batch dimensions\n", " probability = T.squeeze(dist.log_prob(action)).item()\n", " action = T.squeeze(action).item()\n", " value = T.squeeze(value).item()\n", "\n", " return action, probability, value\n", "\n", " # learning from actions\n", " def learn(self):\n", " # iterate over the number of epochs\n", " for _ in range(self.num_epochs):\n", " state_array, action_array, old_probability_array, values_array,\\\n", " reward_array, terminal_flag_array, batches = \\\n", " self.memory.generate_batches()\n", "\n", " values = values_array\n", " # advantage\n", " advantage = np.zeros(len(reward_array), dtype=np.float32)\n", " \n", " # calculate advantage\n", " for time_step in range(len(reward_array)-1):\n", " discount = 1\n", " advantage_time_step = 0\n", " # from Schulman paper -> the advantage function\n", " for k in range(time_step, len(reward_array)-1):\n", " advantage_time_step += discount*(reward_array[k] + self.gamma*values[k+1]*\\\n", " (1-int(terminal_flag_array[k])) - values[k])\n", " # multiplicative factor\n", " discount *= self.gamma*self.gae_lambda\n", " advantage[time_step] = advantage_time_step\n", " # turn advantage into tensor\n", " advantage = T.tensor(advantage).to(self.actor.device)\n", "\n", " # convert values to a tensor\n", " values = T.tensor(values).to(self.actor.device)\n", " for batch in batches:\n", " states = T.tensor(state_array[batch], dtype=T.float).to(self.actor.device)\n", " old_probability = T.tensor(old_probability_array[batch]).to(self.actor.device)\n", " actions = T.tensor(action_array[batch]).to(self.actor.device)\n", " \n", " # pi(theta)_new: take states and pass to Actor to get the distribution for new probability\n", " dist = self.actor(states)\n", " \n", " critic_value = self.critic(states)\n", " # new values of the state according to the Critic network\n", " critic_value = T.squeeze(critic_value)\n", " \n", " # calculate new probability\n", " new_probability = dist.log_prob(actions)\n", " # probability ratio; probabilities taken as exponential to get ratio\n", " probability_ratio = new_probability.exp() / old_probability.exp()\n", " # prob_ratio = (new_probs - old_probs).exp()\n", " \n", " weighted_probability = advantage[batch] * probability_ratio\n", " \n", " weighted_clipped_probability = T.clamp(probability_ratio, 1-self.policy_clip,\n", " 1+self.policy_clip)*advantage[batch]\n", " \n", " # negative due to gradient ascent\n", " actor_loss = -T.min(weighted_probability, weighted_clipped_probability).mean()\n", "\n", " returns = advantage[batch] + values[batch]\n", " critic_loss = (returns-critic_value)**2\n", " critic_loss = critic_loss.mean()\n", " \n", " total_loss = actor_loss + 0.5*critic_loss\n", " \n", " # zero the gradients\n", " self.actor.optimizer.zero_grad()\n", " self.critic.optimizer.zero_grad()\n", " \n", " # backpropagate total loss\n", " total_loss.backward()\n", " self.actor.optimizer.step()\n", " self.critic.optimizer.step()\n", " \n", " # at end of epochs clear memory\n", " self.memory.memory_clear() " ] }, { "cell_type": "markdown", "id": "athletic-variety", "metadata": {}, "source": [ "### 4.4. Environment [☝](#contents)\n", "\n", "The environment is a modelled as a stochastic finite state machine with inputs (actions sent from the agent) and outputs (observations and rewards sent to the agent).1\n", "\n", "The agent-environment boundary can be located at different places for different purposes. In practice, the agent-environment boundary is determined once one has selected particular states, actions, and rewards, and thus has identified a specific decision-making task of interest.2\n", "\n", "---\n", "1Referenced from [A Brief Introduction to Reinforcement Learning](https://www.cs.ubc.ca/~murphyk/Bayes/pomdp.html)
\n", "2Referenced from [Reinforcement Learning:\n", "An Introduction](https://web.stanford.edu/class/psych209/Readings/SuttonBartoIPRLBook2ndEd.pdf)\n", "\n", "---\n", "The simplified acceleration of each component from [Section 3.6: Linerisation and Acceleration](#linearisation):\n", "\n", "\\begin{equation}\n", "\\ddot{x}=\\frac{\\begin{array}{l}-M^2{gl}^2\\left[\\theta{}\\left(4I+Ml\\left(4l-1\\right)\\right)+\\phi{}\\left(I+Ml\\left(l-1\\right)+l^2\\right)\\right]\\\\+u\\left(I^2+Il^2\\left(2M+1\\right)+Ml^2\\left(Ml^2-\\frac{1}{4}M+l^2\\right)\\right)\\end{array}}{X}\n", "\\tag{2}\n", "\\end{equation}\n", "\n", "\\begin{equation}\n", "\\ddot{\\theta{}}=\\frac{Ml\\left[\\begin{array}{l}-2Mgl\\left(\\frac{1}{4}\\left(M+m+1\\right)-Ml\\right)\\phi{}\\\\+2g\\left(I\\left(M+m+1\\right)+Ml^2(m+1\\right)\\theta{}\\\\-2u\\left(I+Ml\\left(l-\\frac{1}{4}\\right)\\right)\\end{array}\\right]}{X}\n", "\\tag{3}\n", "\\end{equation}\n", "\n", "\\begin{equation}\n", "\\ddot{\\phi{}}=\\frac{Ml\\left[\\begin{array}{l}-Mgl\\left(-M\\left(4l-1\\right)+m+1\\right)\\theta{}\\\\+g\\left(I\\left(M+m+1\\right)+Ml^2\\left(m-3M+\\left(\\frac{m+1}{M}\\right)+2\\right)\\right)\\phi{}\\\\-u\\left(I(I+1)+Ml\\left(l-1\\right)\\right)\\end{array}\\right]}{X}\n", "\\tag{4}\n", "\\end{equation}\n", "\n", "where,\n", "\\begin{equation}\n", "X=I\\left[I+l^2+m\\left(I+l^2\\right)\\right]-M^2l^2\\left[M\\left(2l\\left(2l-1\\right)+\\frac{1}{4}\\right)\\\\+\\left(3I-l^2\\left(m-1\\right)+\\frac{1}{4}\\left(m+1\\right)\\right)\\right]+M\\left(I^2+l^2\\left[I\\left(2m+3\\right)+l^2(m+1)\\right]\\right)\n", "\\end{equation}" ] }, { "cell_type": "code", "execution_count": 22, "id": "surgical-herald", "metadata": {}, "outputs": [], "source": [ "\"\"\"\n", "Adapted from the classic cart-pole system implemented by Rich Sutton et al.\n", "Original `CartPole-v0` environment available here: http://incompleteideas.net/sutton/book/code/pole.c\n", "Permalink: https://perma.cc/C9ZM-652R\n", "\"\"\"\n", "class DoubleInvertedPendulum(gym.Env): \n", " def __init__(self): \n", " self.gravity = 9.81 # m/s^2\n", " self.mass_cart = 1.0 # kg\n", " self.masspole_1 = 0.1 # kg\n", " self.masspole_2 = 0.1 # kg\n", " self.mass_pole = (self.masspole_1 + self.masspole_2) # kg\n", " self.lengthpole_1 = 0.25 # m\n", " self.lengthpole_2 = 0.25 # m\n", " self.length = (self.lengthpole_1 + self.lengthpole_2) # m\n", " self.force = 10.0 # N\n", " self.moment_inertia = (self.mass_pole*self.length**2) / 12 # kgm^2\n", " self.tau = 0.02 # s\n", " self.kinematics_integrator = 'euler'\n", " self.theta = 0.05\n", " self.phi = 0.05\n", "\n", " # angle at which to fail the episode - ~ 0.2 rad, ~12 deg \n", " self.theta_threshold_radians = 12 * 2 * math.pi / 360\n", " self.phi_threshold_radians = 12 * 2 * math.pi / 360\n", " \n", " # distance of cart to fail episode\n", " self.x_threshold = 2.4\n", "\n", " # angle limit set to 2 * theta_threshold_radians so failing observation\n", " # is still within bounds.\n", " high = np.array([self.x_threshold * 2,\n", " np.finfo(np.float32).max,\n", " self.theta_threshold_radians * 2,\n", " np.finfo(np.float32).max,\n", " self.phi_threshold_radians * 2,\n", " np.finfo(np.float32).max],\n", " dtype=np.float32)\n", "\n", " self.action_space = gym.spaces.Discrete(2)\n", " self.observation_space = gym.spaces.Box(-high, high, dtype=np.float32)\n", "\n", " self.seed()\n", " self.viewer = None\n", " self.state = None\n", "\n", " self.steps_beyond_done = None\n", "\n", " def seed(self, seed=None):\n", " self.np_random, seed = seeding.np_random(seed)\n", " return [seed]\n", "\n", " def step(self, action):\n", " err_msg = \"%r (%s) invalid\" % (action, type(action))\n", " assert self.action_space.contains(action), err_msg\n", "\n", " x, x_dot, theta, theta_dot, phi, phi_dot = self.state\n", " force = self.force if action == 1 else -self.force\n", " \n", " #################################\n", " \n", " # denominator\n", " denominator_X = (self.moment_inertia**2) + (self.moment_inertia*self.length**2) + \\\n", " (self.moment_inertia*self.mass_cart*(self.moment_inertia+self.length**2)) - \\\n", " (self.mass_pole**3*self.length**2*(4*self.length**2-2*self.length+0.25)) - \\\n", " (self.mass_pole**2*self.length**2*(3*self.moment_inertia-self.length**2*self.mass_cart-self.length**2\\\n", " +0.25*self.mass_cart+0.25)) + \\\n", " (self.mass_pole*(self.moment_inertia**2+2*self.moment_inertia*self.length**2*self.mass_cart\\\n", " +3*self.moment_inertia*self.length**2+self.length**4*self.mass_cart+self.length**4))\n", " \n", " # x-acceleration numerator\n", " numerator_x_acc = (force*(self.moment_inertia**2+2*self.moment_inertia*self.mass_pole*self.length**2\\\n", " +self.moment_inertia*self.length**2+ \\\n", " self.mass_pole**2*self.length**4-0.25*self.mass_pole**2*self.length**2\\\n", " +self.mass_pole*self.length**4)) - \\\n", " (self.mass_pole**2*self.gravity*self.length**2*(4*self.moment_inertia+4*self.mass_pole**2\\\n", " -self.mass_pole*self.length)*self.theta) - \\\n", " (self.mass_pole**2*self.gravity*self.length**2*(self.moment_inertia+self.mass_pole*self.length**2\\\n", " -self.mass_pole*self.length+self.length**2)*self.phi)\n", " # x-acceleration\n", " x_acc = numerator_x_acc / denominator_X\n", " \n", " # Θ-acceleration numerator\n", " numerator_theta_acc = (self.mass_pole*self.length*(-self.mass_pole*self.gravity*self.length*\\\n", " (-2*self.mass_pole*self.length+0.5*self.mass_pole\\\n", " +0.5*self.mass_cart+0.2)*self.phi) + \\\n", " 2*self.gravity*(self.moment_inertia*self.mass_pole+self.moment_inertia*self.mass_cart\\\n", " +self.moment_inertia+\\\n", " self.mass_pole*self.mass_cart*self.length**2+self.mass_pole*self.length**2)\\\n", " *self.theta - \\\n", " force*(2*self.moment_inertia+2*self.mass_pole*self.length**2-\\\n", " 0.5*self.mass_pole*self.length))\n", " # Θ-acceleration\n", " theta_acc = numerator_theta_acc / denominator_X\n", " \n", " # Φ-acceleration numerator\n", " numerator_phi_acc = (self.mass_pole*self.length*(-self.mass_pole*self.gravity*self.length*\\\n", " (-4*self.mass_pole*self.length+self.mass_pole+self.mass_cart+1)\\\n", " *self.theta) + \\\n", " (self.gravity*(self.moment_inertia*self.mass_pole+self.moment_inertia*self.mass_cart\\\n", " +self.moment_inertia-3*self.mass_pole**2*self.length**2+\\\n", " self.mass_pole*self.length**2*self.mass_cart+2*self.mass_pole*self.length**2\\\n", " +self.length**2*self.mass_cart+self.length**2)*self.phi - \\\n", " force*(self.moment_inertia+self.mass_pole*self.length**2-self.mass_pole*self.length\\\n", " +self.moment_inertia**2)))\n", " # Φ-acceleration\n", " phi_acc = numerator_phi_acc / denominator_X\n", " \n", " #################################\n", "\n", " if self.kinematics_integrator == 'euler':\n", " x = x + self.tau * x_dot\n", " x_dot = x_dot + self.tau * x_acc\n", " theta = theta + self.tau * theta_dot\n", " phi = phi + self.tau * phi_dot\n", " theta_dot = theta_dot + self.tau * theta_acc\n", " phi_dot = phi_dot + self.tau * phi_acc\n", " else: # semi-implicit euler\n", " x_dot = x_dot + self.tau * x_acc\n", " x = x + self.tau * x_dot\n", " theta_dot = theta_dot + self.tau * theta_acc\n", " theta = theta + self.tau * theta_dot\n", " phi_dot = phi_dot + self.tau * phi_acc\n", " phi = phi + self.tau * phi_dot \n", " \n", " self.state = (x, x_dot, theta, theta_dot, phi, phi_dot)\n", "\n", " done = bool(\n", " x < -self.x_threshold\n", " or x > self.x_threshold\n", " or theta < -self.theta_threshold_radians\n", " or theta > self.theta_threshold_radians\n", " or phi < -self.phi_threshold_radians\n", " or phi > self.phi_threshold_radians\n", " )\n", "\n", " if not done:\n", " reward = 1.0\n", " elif self.steps_beyond_done is None:\n", " self.steps_beyond_done = 0\n", " reward = 1.0\n", " else:\n", " self.steps_beyond_done += 1\n", " reward = 0.0\n", "\n", " return np.array(self.state), reward, done, {}\n", "\n", " def reset(self):\n", " self.state = self.np_random.uniform(low=-0.05, high=0.05, size=(6,))\n", " self.steps_beyond_done = None\n", " return np.array(self.state)" ] }, { "cell_type": "markdown", "id": "blocked-electron", "metadata": {}, "source": [ "### 4.5. Test [☝](#contents)" ] }, { "cell_type": "code", "execution_count": 23, "id": "lesbian-private", "metadata": {}, "outputs": [], "source": [ "# utility function to measure time taken by each test run\n", "def exec_time(start, end):\n", " diff_time = end - start\n", " m, s = divmod(diff_time, 60)\n", " h, m = divmod(m, 60)\n", " s,m,h = int(round(s, 0)), int(round(m, 0)), int(round(h, 0))\n", " print(\"Execution Time: \" + \"{0:02d}:{1:02d}:{2:02d}\".format(h, m, s))" ] }, { "cell_type": "code", "execution_count": null, "id": "constant-friend", "metadata": { "scrolled": false }, "outputs": [], "source": [ "# start time of each test run\n", "start = time.time()\n", "\n", "# create environment\n", "env = DoubleInvertedPendulum()\n", "# number of samples processed before the model is updated\n", "batch_size = 5 \n", "# a full training pass over the entire dataset such that each example has been seen once\n", "num_epochs = 4 \n", "# controls the rate or speed at which the model learns\n", "learning_rate_alpha = 3e-4\n", "\n", "# create agent\n", "agent = Agent(num_actions=env.action_space.n, batch_size=batch_size, \n", " learning_rate_alpha=learning_rate_alpha, num_epochs=num_epochs, \n", " input_dimensions=env.observation_space.shape)\n", "\n", "# number of games\n", "num_games = 100\n", "# track best score: minimum score for the environment\n", "best_score = env.reward_range[0]\n", "# record score history\n", "score_history = []\n", "# a reward function that informs the agent how well its current actions and states are doing\n", "learn_iters = 0\n", "# track average score\n", "average_score = 0\n", "# number of steps means using one batch size of training data to train the model\n", "num_steps = 0\n", "\n", "for i in range(num_games):\n", " observation = env.reset()\n", " terminal_flag = False\n", " score = 0\n", " while not terminal_flag:\n", " # choose action based on the current state of the environment\n", " action, probability, value = agent.action_choice(observation)\n", " # get information back from environment\n", " observation_, reward, terminal_flag, info = env.step(action)\n", " # update step\n", " num_steps += 1\n", " # update score based on current reward\n", " score += reward\n", "\n", " # store transition in the agent memory\n", " agent.interface_agent_memory(observation, action, probability, value, reward, terminal_flag)\n", " if num_steps % num_steps == 0:\n", " agent.learn()\n", " learn_iters += 1\n", " observation = observation_\n", " score_history.append(score)\n", " average_score = np.mean(score_history[-100:])\n", " \n", " if average_score > best_score:\n", " best_score = average_score\n", " \n", " # format output\n", " if i+1 < 10:\n", " print('episode: ', i+1, ' | score: %.0f' % score)\n", " elif i+1 < 100:\n", " print('episode: ', i+1, ' | score: %.0f' % score) \n", " else:\n", " print('episode: ', i+1, '| score: %.0f' % score) \n", " \n", "episodes = [i+1 for i in range(len(score_history))]\n", "# end time of each test run\n", "end = time.time()\n", "# display time taken by test run\n", "print('---------')\n", "exec_time(start,end)\n", "print('---------')\n", "print(f\"Total reward for {num_games} unsupervised episodes: {sum(score_history)}\")\n", "print('---------')\n", "\n", "# visualise learning\n", "def plot_learning_curve(episode, scores):\n", " running_avg = np.zeros(len(scores))\n", " for i in range(len(running_avg)):\n", " running_avg[i] = np.mean(scores[max(0, i-100):(i+1)])\n", " plt.plot(episode, running_avg)\n", " plt.title(f\"Unsupervised learning for {num_games} games\", fontweight='bold')\n", " plt.xlabel('No. of games', fontsize=11)\n", " plt.ylabel('Average reward / episode', fontsize=11)\n", " \n", "plot_learning_curve(episodes, score_history)" ] }, { "cell_type": "markdown", "id": "seventh-jamaica", "metadata": {}, "source": [ "## 5. Conclusion [☝](#contents)\n", "\n", "Various starting angle combinations were tried. Additionally, different parameters were modulated to observe the agent's behaviour.\n", "\n", "#### Initial Parameters ([Environment](#ppo-env)):\n", "\n", "| Parameter | Value |\n", "| :-: | :-: | \n", "| gravitational constant | 9.81 m/s2\n", "| mass of the cart | 1 kg | \n", "| mass of the pendulum(s) | 0.1 kg |\n", "| length of the pendulum(s) | 0.25 m |\n", "| force | 10 N|\n", "| moment of inertia | 3.33e-3 |\n", "\n", "#### Angle variations tested:\n", "\n", "\"reward_aggregation\"/ " ] }, { "cell_type": "markdown", "id": "focused-browser", "metadata": {}, "source": [ "### 5.1. Variations in initial angle conditions [☝](#contents)\n", "\n", "* Results for **10e$^3$** episodes.\n", "\n", "| $$\\theta$$ (rad) | $$\\phi$$ (rad) | Total reward | Total time $$(min)$$ | Average Accuracy $$(\\%)$$ |\n", "| :-: | :-: | :-: | :-: | :-: |\n", "| 0.05 | 0.05 | 72,283 | 29.14 | **72.10** |\n", "| 0.10 | 0.10 | 62,919 | 27.45 | **62.86** |\n", "| 0.15 | 0.15 | 56,180 | 17.28 | **56.57** |\n", "| 0.05 | 0.10 | 62,744 | 22.12 | **62.39** |\n", "| 0.10 | 0.05 | 72,783 | 23.40 | **72.84** |\n", "| 0.00 | 0.15 | 55,859 | 17.44 | **55.74** |\n", "| 0.15 | 0.00 | 91,709 | 28.11 | **91.91** |\n", "\n", "\"reward_aggregation\" \n", "\"time_aggregation\" \n", "\"total_rewards\"\n", "\"total_time\"" ] }, { "cell_type": "markdown", "id": "geographic-acoustic", "metadata": {}, "source": [ "

**** END ****

" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.11" } }, "nbformat": 4, "nbformat_minor": 5 }