From 70dc1da915fc8616baca12ddcc09060e1f063bc7 Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Thu, 10 Apr 2025 12:44:19 -0600 Subject: Added notebooks and scipts to module 3 --- tutorials/module_3/Fourbar.ipynb | 64344 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64344 insertions(+) create mode 100644 tutorials/module_3/Fourbar.ipynb (limited to 'tutorials/module_3/Fourbar.ipynb') diff --git a/tutorials/module_3/Fourbar.ipynb b/tutorials/module_3/Fourbar.ipynb new file mode 100644 index 0000000..621ba69 --- /dev/null +++ b/tutorials/module_3/Fourbar.ipynb @@ -0,0 +1,64344 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "id": "6e81f53e-d5d7-45d9-b596-5b5aaea1afb6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + " \n", + "
\n", + " \n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.animation as animation\n", + "from scipy.optimize import fsolve\n", + "\n", + "# Render animation in Jupyter Notebook\n", + "%matplotlib inline\n", + "plt.rcParams[\"animation.html\"] = \"jshtml\"\n", + "plt.rcParams['figure.dpi'] = 75\n", + "\n", + "# Link lengths (arbitrary units)\n", + "L1 = 4.0 # Ground link\n", + "L2 = 2.0 # Input crank\n", + "L3 = 3.0 # Coupler\n", + "L4 = 3.5 # Output rocker\n", + "\n", + "# Fixed pivots\n", + "A = np.array([0, 0])\n", + "D = np.array([L1, 0])\n", + "\n", + "# Input crank angle range\n", + "theta2_vals = np.linspace(0, 2 * np.pi, 360)\n", + "\n", + "# Store previous angles to ensure continuity\n", + "previous_guess = [np.pi / 2, np.pi / 2]\n", + "\n", + "# Solve joint positions using loop closure equations\n", + "def solve_positions(theta2):\n", + " global previous_guess\n", + " B = A + L2 * np.array([np.cos(theta2), np.sin(theta2)])\n", + "\n", + " def loop_closure(vars):\n", + " theta3, theta4 = vars\n", + " eq1 = L2 * np.cos(theta2) + L3 * np.cos(theta3) - L4 * np.cos(theta4) - L1\n", + " eq2 = L2 * np.sin(theta2) + L3 * np.sin(theta3) - L4 * np.sin(theta4)\n", + " return [eq1, eq2]\n", + "\n", + " theta3, theta4 = fsolve(loop_closure, previous_guess)\n", + " previous_guess = [theta3, theta4] # update guess for continuity\n", + "\n", + " C = B + L3 * np.array([np.cos(theta3), np.sin(theta3)])\n", + " return A, B, C, D\n", + "\n", + "# Set up plot\n", + "fig, ax = plt.subplots()\n", + "\n", + "# Animation function\n", + "def animate(i):\n", + " ax.cla()\n", + " A, B, C, D = solve_positions(theta2_vals[i])\n", + " x_vals = [A[0], B[0], C[0], D[0]]\n", + " y_vals = [A[1], B[1], C[1], D[1]]\n", + " ax.plot(x_vals, y_vals, 'o-', lw=2)\n", + " ax.set_xlim(-5, 8)\n", + " ax.set_ylim(-5, 5)\n", + " ax.set_aspect('equal')\n", + " ax.set_title(\"Four-Bar Linkage Simulation\")\n", + "\n", + "ani = animation.FuncAnimation(fig, animate, frames=len(theta2_vals), interval=20)\n", + "ani" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1adaacdd-80ff-4f1d-bf5a-a9bb2b0b3dc5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.2.3