{ "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 }