Skip to content

pineapple-bois/Double_Pendulum_App

Repository files navigation

Double Pendulum App

This repo serves a Plotly Dash application built on Flask and deployed on Heroku from GitHub. Active development is modernizing the app while preserving the current public deployment path.

img

It is available at: www.double-pendulum.net

The application is an extension of Double_Pendulum, which derived the symbolic equations of motion.

For the current modernization direction, see ROADMAP.md. For durable production architecture and workflow notes, see documentation/.


Physics of a double pendulum

img

The above figure shows Simple and Compound pendulum models.

Both models move in the $(x,y)$-plane and the systems have two degrees of freedom. The motion is uniquely determined by the values of $\theta_1$ and $\theta_2$

Simple Model:

  • The rods $OP_1$ and $P_1P_2$ are rigid, massless and inextensible.
  • Masses at $P_1$ and $P_2$ are subject to a uniform acceleration due to gravity.

Compound Model:

  • Masses $M_1$ and $M_2$ are uniformly distributed along rod lengths $l_1$ and $l_2$.
  • Each rod is subject to a rotational kinetic energy and moment of inertia about its centre of mass.
  • Applying the parallel axis theorem, we account for the rotational dynamics about the pendulum ends.

The effects of any dissipative forces such as air resistance or friction are neglected therefore, the total mechanical energy is conserved.


Mathematical formulation

For this conservative system, the equations of motion are derived from Lagrangian, $\mathcal{L}$ which is given,

$$\mathcal{L}=T-V$$

Where $T$ is the kinetic energy and $V$ is the potential energy.

Forming a system of differential equations

  1. Lagrangian System

We solve the Euler-Lagrange equations for $\textbf{q} = [\theta_1, \theta_2]$ such that,

$$ \frac{\text{d}}{\text{d}t}\left(\frac{\partial L}{\partial \dot{\textbf{q}}}\right)-\frac{\partial L}{\partial \textbf{q}}=0 $$

The result is a system of $|\textbf{q}|$ coupled, second-order differential equations.

Uncoupling the equations involves extensive algebra and can be found in this Python derivation

  1. Hamiltonian System

The Hamiltonian $\mathcal{H}$ is the Legendre transformation of the Lagrangian and is given,

$$ \mathcal{H} = \sum_{i=1}^2 \dot{\theta_i} p_{\theta_i} - \mathcal{L} $$

Here, generalised velocities are replaced with generalised momenta and we form the equations of motion,

$$ \dot{\theta_i}=\frac{\partial \mathcal{H}}{\partial p_{\theta_i}} $$

$$ \dot{p}_{\theta_i}=-\frac{\partial \mathcal{H}}{\partial \theta_i} $$

Hamilton's equations are first-order and the Python derivation proved simpler than uncoupling the Euler-Lagrange equations.

In this instance, the Hamiltonian was the first integral of the Lagrangian, representing total energy of the system. For $\textbf{q} = [\theta_1, \theta_2]$,

$$ \mathcal{H}(\mathbf{p}, \mathbf{q}) = \sum_{i=1}^2 \dot{q_i} p_{i} - \mathcal{L}(\mathbf{q}, \dot{\mathbf{q}}) \equiv T+V \equiv E_{\text{mech}} $$

Solving the equations of motion

Closed-form, analytical solutions of the double pendulum system are not known to exist. The system must be integrated numerically.


The Application

This application represents a hybrid of web-development and dashboard engineering. The active architecture is a Dash application shell with callback-owned interaction state, Python backend simulation/model code, and a Canvas-based Simulation renderer fed by Python-built payloads.

Main Features

  • Deriving the equations:
    • The equations of motion are derived symbolically with SymPy and abstracted as reusable helpers under src/double_pendulum/math/.
    • A simple conditional logic structure controls which model is derived.
  • DoublePendulum Class:
    • Instantiating a Lagrangian or Hamiltonian double-pendulum model object; clicking the Run Simulation button, derives the symbolic equations "on-the-fly".
    • The equations are cached to reduce runtime for further simulations of the same model.
    • The equations are numerically integrated using SciPy's solve_ivp function. Integrator arguments are available in the class structure but this functionality is yet to be added to the UI.
  • Visualisation:
    • The production Simulation page now uses a Canvas renderer for motion, angular displacement, and angular state projection playback from Python-built payloads.
    • Plotly and Matplotlib remain dependencies for retained plotting helpers and future richer analytical inspection, but legacy Plotly outputs are no longer generated in the normal Simulation run flow.
    • MathJax API is used for rendering latex expressions.
  • Error Handling:
    • Robust validation of user inputs, ensures computational load is never too high.

The Canvas integration does not imply that the numerical science is fully validated. Energy diagnostics, chaos diagnostics, tolerance sensitivity, solver-method equivalence, and long-duration scientific validity remain deferred modernization work.

Directory Structure

Double_Pendulum_App/
├── assets/
│   ├── Images/
│   │   ├── github-mark.png
│   │   ├── Model_Compound_Transparent_NoText.png
│   │   ├── Model_Simple_Transparent_NoText.png
│   │   ├── Models_Joint_White.png
│   │   └── Screenshot.png
│   ├── MarkdownScripts/
│   │   ├── information.txt
│   │   ├── mathematics_hamiltonian.txt
│   │   └── mathematics_lagrangian.txt
│   ├── custom-header.html
│   ├── nav-bar.js
│   ├── scroll.js
│   ├── simulation-canvas-renderer.js
│   └── styles.css
├── app/
│   ├── callbacks/
│   ├── components/
│   ├── content/
│   ├── pages/
│   └── serialization/
├── documentation/
├── src/
│   └── double_pendulum/
│       ├── math/
│       ├── models/
│       ├── plotting/
│       └── validation/
├── tests/
├── LICENSE.md
├── ROADMAP.md
├── pendulum_app.py
├── Procfile
├── README.md
├── requirements.txt
└── .python-version
  • Deployment/runtime files:
    • Procfile specifies the command to run the app.
    • .python-version defines the Python runtime for Heroku deployment.
    • requirements.txt lists necessary dependencies.
    • runtime.txt has intentionally been removed and should not be reintroduced.
  • Dash applications automatically read and serve files located in the root of the assets/ directory:
    • custom-header.html - Defines the page meta-data.
    • nav-bar.js - Script to scroll to the top of the math pages.
    • scroll.js - Script triggered by the "Run Simulation" button scrolls to the input/figures section of the page.
    • simulation-canvas-renderer.js - Browser-side Canvas rendering, playback, and selected-frame inspection for Python-built simulation payloads.
    • styles.css - Handles app styles such as fonts, colours, media queries, and layout structure.
  • The app/ package contains Dash-facing application code:
    • app/pages/ owns route-level page layouts.
    • app/components/ owns reusable UI shell, controls, graph wrappers, references, and figure styling.
    • app/content/ owns user-facing copy, page metadata, markdown paths, and reference data.
    • app/callbacks/ owns routing and simulation callback registration.
    • app/serialization/ owns the Canvas payload API used by the Simulation page.
  • The src/double_pendulum/ package is the home for reusable simulation, symbolic math, validation, and plotting/helper logic.
  • The documentation/ directory is the durable architecture/workflow reference for production-facing decisions, including the current Canvas Simulation architecture under documentation/simulation-canvas/.

Future Development

The chaos/non-linear dynamics page is a work in progress.

The active product and architecture direction is tracked in ROADMAP.md. The local development/ directory may contain ignored exploratory/reference work, including Simulation Workbench, math-fidelity, and solver-contract evidence. Durable summaries live under documentation/, and accepted findings should be encoded in production code and tracked tests.

The current roadmap continues from the deployed Simulation baseline. Phase 9 established the production layout and deployment hooks; Phase 10 is focused on the chaos-analysis framework before any production Chaos page redesign.

Future chaos work aims to:

  1. Produce a semi-structured database of angles, velocities, positions, and momenta within specified bounds using the Hamiltonian derivation.
  2. Produce bifurcation diagrams, and Poincaré sections to qualitatively analyse periodicity.
  3. Analyse the truncation error of the numerical integration.
  4. Analyse orbits quantitatively using Lyapunov exponents.

Running the App Locally

1. Fork and Clone the Repository

  git clone <your-forked-repo-url>
  cd Double_Pendulum_App

2. Set Up a Virtual Environment

python3.12 -m venv .venv
source .venv/bin/activate   # On macOS/Linux
.\.venv\Scripts\activate    # On Windows

3. Install Dependencies

pip install -r requirements.txt

4. Configure Local and Deployment Flags

Local HTTP development does not redirect by default. Deployment-specific HTTPS redirects are controlled by the FORCE_HTTPS environment flag in app/config.py; set FORCE_HTTPS=true only when the server should redirect plain HTTP requests to HTTPS. The direct local run debug flag is controlled separately with DASH_DEBUG; leave it false for deployment-style checks and set DASH_DEBUG=true only for local development.

For the existing Heroku deployment, keep using the tracked Procfile:

web: gunicorn pendulum_app:server

Set deployment config through Heroku config vars rather than editing pendulum_app.py:

heroku config:set FORCE_HTTPS=true
heroku config:unset DASH_DEBUG

5. Run the Application Safely

python pendulum_app.py

For Dash debug mode during local development:

DASH_DEBUG=true python pendulum_app.py

6. Access the app at http://127.0.0.1:8050/ (The development server)

Before starting the Dash app for a smoke check, confirm port 8050 is not already occupied:

lsof -nP -iTCP:8050 -sTCP:LISTEN

If port 8050 is already occupied, do not blindly kill the process. Identify it if possible, or choose a clearly documented temporary port only when appropriate.

If you start the Dash development server, capture the process ID, stop that exact process after testing, and verify you did not leave a Flask/Dash process running. This cleanup rule is more important than completing a browser smoke check.


Running the Test Suite

Install the app and test dependencies in the Python 3.12 virtual environment:

pip install -r requirements.txt
pip install -r requirements-dev.txt

Run the full test suite with:

python -m pytest

For Simulation UI work, a manual/browser smoke check should cover a simple valid run, Canvas rendering, playback controls, stale state after input changes, and invalid-input validation. See documentation/development-workflow.md for the full safe smoke-test procedure.

The current test layout is organized by purpose:

  • tests/unit/ covers validation and lightweight symbolic fidelity checks.
  • tests/integration/ covers app import, route layout smoke behavior, and the Flask server object used by Gunicorn.
  • tests/numerical/ covers basic Lagrangian and Hamiltonian simulation shape, finite values, and initial-condition consistency.

Validation scope note: these tests support deployment and modernization work, but they are not a complete numerical validation project. Full derivation audits, compound-equation symbolic checks, energy-conservation tolerances, trajectory regression fixtures, and a Hamiltonian state/input convention audit remain scientific-validation work rather than deployment blockers.


Project Dependencies

Core Libraries

  • dash
  • dash-bootstrap-components

Web Server and Framework

  • Flask
  • gunicorn

Math and Science Libraries

  • numpy
  • scipy
  • sympy

Visualisation

  • matplotlib
  • plotly

The requirements.txt file intentionally lists only top-level application/runtime dependencies. The old fully frozen dependency list is preserved in requirements-old-freeze.txt for reference.

Development and test-only dependencies are listed separately in requirements-dev.txt.


Licence: MIT Pineapple Bois


About

Dash App - Simulation of double pendulum equations of motion

Topics

Resources

License

Stars

Watchers

Forks

Contributors