.. 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_03_freudenstein_equation.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_03_freudenstein_equation.py: Freudenstein's equation for four-bar synthesis (1954) ===================================================== Before computers, linkages that generate a prescribed function were designed by graphical construction. Ferdinand Freudenstein (1954) wrote the four-bar's loop closure as .. math:: K_1\cos\theta_4 - K_2\cos\theta_2 + K_3 = \cos(\theta_2 - \theta_4), which is *linear* in three link-length ratios. Prescribing three pairs of input and output angles, the precision points, gives three linear equations (:func:`~engineeringkit.mechanical_engineering.freudenstein_coefficients`), and the link lengths follow (:func:`~engineeringkit.mechanical_engineering.freudenstein_link_lengths`). The example designs a linkage whose output angle is proportional to :math:`\log_{10} x` for :math:`1 \le x \le 2`, using Chebyshev spacing of the precision points to keep the error small between them. .. GENERATED FROM PYTHON SOURCE LINES 22-27 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from engineeringkit.mechanical_engineering import fourbar_output_angle, freudenstein_coefficients, freudenstein_link_lengths .. GENERATED FROM PYTHON SOURCE LINES 28-35 Precision points ---------------- The input crank turns 60 degrees from 40 degrees as :math:`x` runs from 1 to 2. The output turns 90 degrees from -60 degrees as :math:`\log_{10} x` runs from 0 to :math:`\log_{10} 2`. Chebyshev spacing puts the three precision points at :math:`1.5 - 0.5\cos((2j - 1)\pi/6)`. .. GENERATED FROM PYTHON SOURCE LINES 35-54 .. code-block:: Python x0, x1 = 1.0, 2.0 def crank(x): return np.radians(40 + 60 * (x - x0) / (x1 - x0)) def rocker(x): return np.radians(-60 + 90 * np.log10(x) / np.log10(x1)) xs = (x0 + x1) / 2 - (x1 - x0) / 2 * np.cos((2 * np.arange(1, 4) - 1) * np.pi / 6) K = freudenstein_coefficients(crank(xs), rocker(xs)) a, b, c, d = freudenstein_link_lengths(K, ground=0.1) print("precision points x =", np.round(xs, 4).tolist()) print(f"K = {np.round(K, 5).tolist()}") print(f"crank {1e3 * a:.1f} mm, coupler {1e3 * b:.1f} mm, rocker {1e3 * c:.1f} mm, ground {1e3 * d:.1f} mm") .. rst-class:: sphx-glr-script-out .. code-block:: none precision points x = [1.067, 1.5, 1.933] K = [0.48881, 0.3593, -0.14296] crank 204.6 mm, coupler 381.6 mm, rocker 278.3 mm, ground 100.0 mm .. GENERATED FROM PYTHON SOURCE LINES 55-61 Check the design by analysis ---------------------------- Solving the synthesised linkage's loop closure must return the prescribed output exactly at the precision points. Between them the *structural error* is small but not zero. .. GENERATED FROM PYTHON SOURCE LINES 61-83 .. code-block:: Python assert np.allclose(fourbar_output_angle(a, b, c, d, crank(xs)), rocker(xs), atol=1e-10) x = np.linspace(x0, x1, 401) error = np.degrees(fourbar_output_angle(a, b, c, d, crank(x)) - rocker(x)) print(f"largest structural error {np.max(np.abs(error)):.3f} deg over a 90 deg output range") assert np.max(np.abs(error)) < 0.05 fig, axes = plt.subplots(1, 2, figsize=(10, 3.8)) axes[0].plot(x, error) axes[0].plot(xs, 0 * xs, "o", label="precision points") axes[0].set(xlabel="x", ylabel="output error [deg]", title="Structural error") axes[0].legend() for xi in (x0, 1.5, x1): t2, t4 = crank(xi), fourbar_output_angle(a, b, c, d, crank(xi)) A, B = a * np.array([np.cos(t2), np.sin(t2)]), 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-", label=f"x = {xi}") axes[1].set_aspect("equal") axes[1].set(xlabel="x [m]", ylabel="y [m]", title="Log-function generator") axes[1].legend(fontsize=8) fig.tight_layout() plt.show() .. image-sg:: /api/gallery/mechanical_engineering/mechanisms/images/sphx_glr_plot_03_freudenstein_equation_001.png :alt: Structural error, Log-function generator :srcset: /api/gallery/mechanical_engineering/mechanisms/images/sphx_glr_plot_03_freudenstein_equation_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none largest structural error 0.041 deg over a 90 deg output range .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.047 seconds) .. _sphx_glr_download_api_gallery_mechanical_engineering_mechanisms_plot_03_freudenstein_equation.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_03_freudenstein_equation.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_03_freudenstein_equation.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_03_freudenstein_equation.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_03_freudenstein_equation.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_