{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Whipper Simulation\n", "\n", "This notebook demonstrates a whipper-style trebuchet.\n", "A whipper trebuchet features a hinged counterweight system, but with the counterweight hanger positioned at the top of the throwing arm. \n", "When cocked, the arm points forward in the direction of the throw. At the start, the weight and projectile 'rest' on the trebuchet arm.\n", "\n", "What you'll see here:\n", "\n", "- Build a default whipper configuration (`Trebuchet.default_whipper()`)\n", "- Solve the multi-phase motion for the whipper mechanism\n", "- Report key timing and range metrics\n", "- Animate the launch sequence\n", "\n", "Tip: For clearer visuals, tweak `skip` (frame thinning) and `delay` (milliseconds per frame) in the animation cell." ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "from pytrebuchet.simulation import Simulation, SimulationPhases\n", "from pytrebuchet.differential_equations.sling_phase import SlingPhases\n", "from pytrebuchet.trebuchet import WhipperTrebuchet" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "## 1. Setup & Solve\n", "\n", "We create a whipper `Trebuchet` and a default `Projectile`, then call `Simulation.solve()` to integrate the equations of motion through the whipper-specific phases:\n", "\n", "- Both constrained: arm, whipper, and projectile move kinematically linked\n", "- Projectile constrained: projectile remains constrained while the whip transitions\n", "- Sling unconstrained: sling dynamics prior to release\n", "- Ballistic: free-flight trajectory after release\n", "\n", "Printed metrics include sling release time, ground impact time, and horizontal range." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": {}, "outputs": [], "source": [ "trebuchet = WhipperTrebuchet.default()\n", "simulation = Simulation(trebuchet)\n", "\n", "simulation.solve()\n", "\n", "print(\n", " f\"Sling release time: {\n", " simulation.get_phase_end_time(\n", " sim_phase=SimulationPhases.SLING, sling_phase=SlingPhases.UNCONSTRAINED\n", " ):.4f} s\"\n", ")\n", "print(\n", " f\"Ground impact time: {\n", " simulation.get_phase_end_time(sim_phase=SimulationPhases.BALLISTIC):.4f} s\"\n", ")\n", "print(f\"Horizontal range: {simulation.distance_traveled:.2f} m\")" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "## 2. Animation\n", "\n", "Below we animate the whipper launch sequence.\n", "\n", "Adjust parameters in `animate_launch(simulation, skip=10, delay=50)` for smoother or faster playback." ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "from matplotlib import rc\n", "from pytrebuchet.plotting import animate_launch\n", "from IPython.display import HTML\n", "\n", "# Configure matplotlib to render animations as interactive JavaScript\n", "rc(\"animation\", html=\"jshtml\")\n", "\n", "ani = animate_launch(simulation, skip=10, delay=50, show=False)\n", "HTML(ani.to_jshtml())" ] } ], "metadata": { "kernelspec": { "display_name": ".venv (3.13.9)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.9" } }, "nbformat": 4, "nbformat_minor": 5 }