|
| 1 | +.. currentmodule:: control |
| 2 | + |
| 3 | +Phase plane plots |
| 4 | +================= |
| 5 | +Insight into nonlinear systems can often be obtained by looking at phase |
| 6 | +plane diagrams. The :func:`~control.phase_plane_plot` function allows the |
| 7 | +creation of a 2-dimensional phase plane diagram for a system. This |
| 8 | +functionality is supported by a set of mapping functions that are part of |
| 9 | +the `phaseplot` module. |
| 10 | + |
| 11 | +The default method for generating a phase plane plot is to provide a |
| 12 | +2D dynamical system along with a range of coordinates and time limit:: |
| 13 | + |
| 14 | + sys = ct.nlsys( |
| 15 | + lambda t, x, u, params: np.array([[0, 1], [-1, -1]]) @ x, |
| 16 | + states=['position', 'velocity'], inputs=0, name='damped oscillator') |
| 17 | + axis_limits = [-1, 1, -1, 1] |
| 18 | + T = 8 |
| 19 | + ct.phase_plane_plot(sys, axis_limits, T) |
| 20 | + |
| 21 | +.. image:: figures/phaseplot-dampedosc-default.png |
| 22 | + |
| 23 | +By default, the plot includes streamlines generated from starting |
| 24 | +points on limits of the plot, with arrows showing the flow of the |
| 25 | +system, as well as any equilibrium points for the system. A variety |
| 26 | +of options are available to modify the information that is plotted, |
| 27 | +including plotting a grid of vectors instead of streamlines and |
| 28 | +turning on and off various features of the plot. |
| 29 | + |
| 30 | +To illustrate some of these possibilities, consider a phase plane plot for |
| 31 | +an inverted pendulum system, which is created using a mesh grid:: |
| 32 | + |
| 33 | + def invpend_update(t, x, u, params): |
| 34 | + m, l, b, g = params['m'], params['l'], params['b'], params['g'] |
| 35 | + return [x[1], -b/m * x[1] + (g * l / m) * np.sin(x[0]) + u[0]/m] |
| 36 | + invpend = ct.nlsys(invpend_update, states=2, inputs=1, name='invpend') |
| 37 | + |
| 38 | + ct.phase_plane_plot( |
| 39 | + invpend, [-2*pi, 2*pi, -2, 2], 5, |
| 40 | + gridtype='meshgrid', gridspec=[5, 8], arrows=3, |
| 41 | + plot_equilpoints={'gridspec': [12, 9]}, |
| 42 | + params={'m': 1, 'l': 1, 'b': 0.2, 'g': 1}) |
| 43 | + plt.xlabel(r"$\theta$ [rad]") |
| 44 | + plt.ylabel(r"$\dot\theta$ [rad/sec]") |
| 45 | + |
| 46 | +.. image:: figures/phaseplot-invpend-meshgrid.png |
| 47 | + |
| 48 | +This figure shows several features of more complex phase plane plots: |
| 49 | +multiple equilibrium points are shown, with saddle points showing |
| 50 | +separatrices, and streamlines generated along a 5x8 mesh of initial |
| 51 | +conditions. At each mesh point, a streamline is created that goes 5 time |
| 52 | +units forward and backward in time. A separate grid specification is used |
| 53 | +to find equilibrium points and separatrices (since the course grid spacing |
| 54 | +of 5x8 does not find all possible equilibrium points). Together, the |
| 55 | +multiple features in the phase plane plot give a good global picture of the |
| 56 | +topological structure of solutions of the dynamical system. |
| 57 | + |
| 58 | +Phase plots can be built up by hand using a variety of helper functions that |
| 59 | +are part of the :mod:`~control.phaseplot` (pp) module:: |
| 60 | + |
| 61 | + import control.phaseplot as pp |
| 62 | + |
| 63 | + def oscillator_update(t, x, u, params): |
| 64 | + return [x[1] + x[0] * (1 - x[0]**2 - x[1]**2), |
| 65 | + -x[0] + x[1] * (1 - x[0]**2 - x[1]**2)] |
| 66 | + oscillator = ct.nlsys( |
| 67 | + oscillator_update, states=2, inputs=0, name='nonlinear oscillator') |
| 68 | + |
| 69 | + ct.phase_plane_plot(oscillator, [-1.5, 1.5, -1.5, 1.5], 0.9) |
| 70 | + pp.streamlines( |
| 71 | + oscillator, np.array([[0, 0]]), 1.5, |
| 72 | + gridtype='circlegrid', gridspec=[0.5, 6], dir='both') |
| 73 | + pp.streamlines( |
| 74 | + oscillator, np.array([[1, 0]]), 2*pi, arrows=6, color='b') |
| 75 | + plt.gca().set_aspect('equal') |
| 76 | + |
| 77 | +.. image:: figures/phaseplot-oscillator-helpers.png |
| 78 | + |
| 79 | +The following helper functions are available: |
| 80 | + |
| 81 | +.. autosummary:: |
| 82 | + |
| 83 | + phaseplot.equilpoints |
| 84 | + phaseplot.separatrices |
| 85 | + phaseplot.streamlines |
| 86 | + phaseplot.vectorfield |
| 87 | + |
| 88 | +The :func:`~control.phase_plane_plot` function calls these helper functions |
| 89 | +based on the options it is passed. |
| 90 | + |
| 91 | +Note that unlike other plotting functions, phase plane plots do not involve |
| 92 | +computing a response and then plotting the result via a `plot()` method. |
| 93 | +Instead, the plot is generated directly be a call to the |
| 94 | +:func:`~control.phase_plane_plot` function (or one of the |
| 95 | +:mod:`~control.phaseplot` helper functions. |
| 96 | + |
| 97 | + |
0 commit comments