.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/control_systems/root_locus/plot_01_evans_root_locus.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_control_systems_root_locus_plot_01_evans_root_locus.py: Evans's root locus ================== Walter Evans at North American Aviation (1948) showed how to sketch the paths of the closed-loop poles as a single gain :math:`K` rises from zero, without solving a polynomial for each gain (:func:`~engineeringkit.control_systems.root_locus`). For :math:`K/(s(s+2)(s+4))` the branches leave the poles at 0, -2 and -4. Two of them meet and break away from the real axis where :math:`\tfrac{d}{ds}[s(s+2)(s+4)] = 0`, at :math:`s = -2 + 2/\sqrt3`. They cross the imaginary axis at :math:`\pm j\sqrt8` when :math:`K = 48`. .. GENERATED FROM PYTHON SOURCE LINES 16-24 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from engineeringkit.control_systems import root_locus from engineeringkit.control_systems.visualizers import plot_root_locus num, den = [1.0], [1.0, 6.0, 8.0, 0.0] .. GENERATED FROM PYTHON SOURCE LINES 25-27 Break-away point and imaginary-axis crossing -------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 27-45 .. code-block:: Python s_b = -2 + 2 / np.sqrt(3) K_b = -np.polyval(den, s_b) pair = np.sort_complex(root_locus(num, den, [K_b])[0])[1:] print(f"break-away at s = {s_b:.4f} for K = {K_b:.4f}: roots {np.round(pair, 3)}") assert np.allclose(pair, s_b, atol=1e-4) crossing = root_locus(num, den, [48.0])[0] print("K = 48 roots:", np.round(crossing, 6)) assert np.isclose(np.abs(crossing.imag).max(), np.sqrt(8)) and abs(crossing.real[np.argmax(crossing.imag)]) < 1e-9 ax = plot_root_locus(num, den, np.concatenate((np.linspace(0, 5, 400), np.linspace(5, 200, 800)))) ax.plot([0, 0], [-np.sqrt(8), np.sqrt(8)], "C3o", label="$K = 48$") ax.plot(s_b, 0, "C2s", label="break-away") ax.set(xlim=(-8, 3), ylim=(-6, 6), title=r"Root locus of $K/(s(s+2)(s+4))$") ax.legend() plt.show() .. image-sg:: /api/gallery/control_systems/root_locus/images/sphx_glr_plot_01_evans_root_locus_001.png :alt: Root locus of $K/(s(s+2)(s+4))$ :srcset: /api/gallery/control_systems/root_locus/images/sphx_glr_plot_01_evans_root_locus_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none break-away at s = -0.8453 for K = 3.0792: roots [-0.845+0.j -0.845+0.j] K = 48 roots: [-6.+0.j 0.+2.828427j 0.-2.828427j] .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.153 seconds) .. _sphx_glr_download_api_gallery_control_systems_root_locus_plot_01_evans_root_locus.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/control_systems/root_locus/plot_01_evans_root_locus.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_evans_root_locus.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_evans_root_locus.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_evans_root_locus.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_