.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/mechanical_engineering/mechanisms/plot_02_grashof_condition.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_mechanical_engineering_mechanisms_plot_02_grashof_condition.py: Grashof's condition for four-bar linkages (1883) ================================================ Franz Grashof (1883) gave the rule that decides whether any link of a four-bar chain can turn a full circle. With :math:`s` and :math:`l` the shortest and longest links and :math:`p, q` the others, the shortest link rotates fully relative to its neighbours if and only if :math:`s + l \le p + q` (:func:`~engineeringkit.mechanical_engineering.fourbar_grashof`). Which link is grounded then decides the machine. Grounding a neighbour of the shortest link gives a crank-rocker, grounding the shortest gives a double crank, and grounding the link opposite it gives a double rocker. The example checks all four inversions of a Grashof chain, and of a non-Grashof chain, by trying to assemble each one at every input angle (:func:`~engineeringkit.mechanical_engineering.fourbar_output_angle`). .. GENERATED FROM PYTHON SOURCE LINES 20-43 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from engineeringkit.mechanical_engineering import fourbar_grashof, fourbar_output_angle angles = np.linspace(0, 2 * np.pi, 721) def rotates_fully(ground, crank, coupler, rocker): try: fourbar_output_angle(crank, coupler, rocker, ground, angles) except ValueError: return False return True def classify(chain, g): """Ground link ``g`` of the cyclic chain; test each neighbour as a full-turn input.""" d, a, b, c = (chain[(g + i) % 4] for i in range(4)) first, second = rotates_fully(d, a, b, c), rotates_fully(d, c, b, a) return {2: "double crank", 1: "crank-rocker", 0: "double rocker"}[first + second] .. GENERATED FROM PYTHON SOURCE LINES 44-46 Four inversions of each chain ----------------------------- .. GENERATED FROM PYTHON SOURCE LINES 46-58 .. code-block:: Python expected = {"shortest grounded": "double crank", "neighbour grounded": "crank-rocker", "opposite grounded": "double rocker"} for chain in ([2.0, 7.0, 9.0, 6.0], [3.0, 5.0, 9.0, 4.0]): grashof = fourbar_grashof(chain) print(f"chain {chain}: s + l = {min(chain) + max(chain)}, p + q = {sum(chain) - min(chain) - max(chain)}, Grashof: {grashof}") shortest = int(np.argmin(chain)) for g in range(4): kind = classify(chain, g) role = "shortest" if g == shortest else "opposite" if (g - shortest) % 4 == 2 else "neighbour" print(f" ground link {chain[g]:.0f} ({role}): {kind}") assert kind == (expected[f"{role} grounded"] if grashof else "double rocker") .. rst-class:: sphx-glr-script-out .. code-block:: none chain [2.0, 7.0, 9.0, 6.0]: s + l = 11.0, p + q = 13.0, Grashof: True ground link 2 (shortest): double crank ground link 7 (neighbour): crank-rocker ground link 9 (opposite): double rocker ground link 6 (neighbour): crank-rocker chain [3.0, 5.0, 9.0, 4.0]: s + l = 12.0, p + q = 9.0, Grashof: False ground link 3 (shortest): double rocker ground link 5 (neighbour): double rocker ground link 9 (opposite): double rocker ground link 4 (neighbour): double rocker .. GENERATED FROM PYTHON SOURCE LINES 59-65 Crank-rocker motion ------------------- Ground a 7-unit link next to the 2-unit crank, with a 9-unit coupler and a 6-unit rocker: the crank turns fully and the rocker swings back and forth. .. GENERATED FROM PYTHON SOURCE LINES 65-84 .. code-block:: Python d, a, b, c = 7.0, 2.0, 9.0, 6.0 theta4 = fourbar_output_angle(a, b, c, d, angles) print(f"rocker swing {np.degrees(theta4.max() - theta4.min()):.1f} deg") fig, axes = plt.subplots(1, 2, figsize=(10, 3.8)) axes[0].plot(np.degrees(angles), np.degrees(theta4)) axes[0].set(xlabel="crank angle [deg]", ylabel="rocker angle [deg]", title="Crank-rocker") for angle in np.radians([0, 90, 180, 270]): A = a * np.array([np.cos(angle), np.sin(angle)]) t4 = fourbar_output_angle(a, b, c, d, angle) B = np.array([d + c * np.cos(t4), c * np.sin(t4)]) axes[1].plot([0, A[0], B[0], d], [0, A[1], B[1], 0], "o-", alpha=0.7) axes[1].plot([0, d], [0, 0], "k", lw=3) axes[1].set_aspect("equal") axes[1].set(title="Positions at 0, 90, 180, 270 deg") fig.tight_layout() plt.show() .. image-sg:: /api/gallery/mechanical_engineering/mechanisms/images/sphx_glr_plot_02_grashof_condition_001.png :alt: Crank-rocker, Positions at 0, 90, 180, 270 deg :srcset: /api/gallery/mechanical_engineering/mechanisms/images/sphx_glr_plot_02_grashof_condition_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none rocker swing 50.8 deg .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.044 seconds) .. _sphx_glr_download_api_gallery_mechanical_engineering_mechanisms_plot_02_grashof_condition.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/mechanical_engineering/mechanisms/plot_02_grashof_condition.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_grashof_condition.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_grashof_condition.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_grashof_condition.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_