|
| 1 | +# phaseplots.py - examples of phase portraits |
| 2 | +# RMM, 24 July 2011 |
| 3 | +# |
| 4 | +# This file contains examples of phase portraits pulled from "Feedback |
| 5 | +# Systems" by Astrom and Murray (Princeton University Press, 2008). |
| 6 | + |
| 7 | +import numpy as np |
| 8 | +import matplotlib.pyplot as mpl |
| 9 | +from control.phaseplot import PhasePlot |
| 10 | +from numpy import pi |
| 11 | + |
| 12 | +# Clear out any figures that are present |
| 13 | +mpl.close('all') |
| 14 | + |
| 15 | +# |
| 16 | +# Inverted pendulum |
| 17 | +# |
| 18 | + |
| 19 | +# Define the ODEs for a damped (inverted) pendulum |
| 20 | +def invpend_ode(x, t, m=1., l=1., b=0.2, g=1): |
| 21 | + return (x[1], -b/m*x[1] + (g*l/m) * np.sin(x[0])) |
| 22 | + |
| 23 | +# Set up the figure the way we want it to look |
| 24 | +mpl.figure(); mpl.clf(); |
| 25 | +mpl.axis([-2*pi, 2*pi, -2.1, 2.1]); |
| 26 | +mpl.title('Inverted pendlum') |
| 27 | + |
| 28 | +# Outer trajectories |
| 29 | +PhasePlot(invpend_ode, |
| 30 | + 'logtime', (3, 0.7), None, |
| 31 | + [ [-2*pi, 1.6], [-2*pi, 0.5], [-1.8, 2.1], |
| 32 | + [-1, 2.1], [4.2, 2.1], [5, 2.1], |
| 33 | + [2*pi, -1.6], [2*pi, -0.5], [1.8, -2.1], |
| 34 | + [1, -2.1], [-4.2, -2.1], [-5, -2.1] ], |
| 35 | + np.linspace(0, 40, 200)) |
| 36 | + |
| 37 | +# Separatrices |
| 38 | +mpl.hold(True); |
| 39 | +PhasePlot(invpend_ode, 'auto', 0, None, [[-2.3056, 2.1], [2.3056, -2.1]], 6) |
| 40 | +mpl.show(); |
| 41 | + |
| 42 | +# |
| 43 | +# Systems of ODEs: damped oscillator example (simulation + phase portrait) |
| 44 | +# |
| 45 | + |
| 46 | +def oscillator_ode(x, t, m=1., b=1, k=1): |
| 47 | + return (x[1], -k/m*x[0] - b/m*x[1]) |
| 48 | + |
| 49 | +# Generate a vector plot for the damped oscillator |
| 50 | +mpl.figure(); mpl.clf(); |
| 51 | +PhasePlot(oscillator_ode, [-1, 1, 10], [-1, 1, 10], 0.15); |
| 52 | +mpl.hold(True); mpl.plot([0], [0], '.'); |
| 53 | +# a=gca; set(a,'FontSize',20); set(a,'DataAspectRatio',[1,1,1]); |
| 54 | +mpl.xlabel('x1'); mpl.ylabel('x2'); |
| 55 | + |
| 56 | +# Generate a phase plot for the damped oscillator |
| 57 | +mpl.figure(); mpl.clf(); |
| 58 | +mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1, 1, 1]); |
| 59 | +PhasePlot(oscillator_ode, |
| 60 | + 'timepts', [0.25, 0.8, 2, 3], None, [ |
| 61 | + [-1, 1], [-0.3, 1], [0, 1], [0.25, 1], [0.5, 1], [0.75, 1], [1, 1], |
| 62 | + [1, -1], [0.3, -1], [0, -1], [-0.25, -1], [-0.5, -1], [-0.75, -1], [-1, -1] |
| 63 | + ], np.linspace(0, 8, 80)) |
| 64 | +mpl.hold(True); mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); |
| 65 | +# set(gca,'DataAspectRatio',[1,1,1]); |
| 66 | +mpl.xlabel('x1'); mpl.ylabel('x2'); |
| 67 | + |
| 68 | +mpl.show() |
| 69 | + |
| 70 | +# |
| 71 | +# Stability definitions |
| 72 | +# |
| 73 | +# This set of plots illustrates the various types of equilibrium points. |
| 74 | +# |
| 75 | + |
| 76 | +# Saddle point vector field |
| 77 | +def saddle_ode(x, t): |
| 78 | + return (x[0] - 3*x[1], -3*x[0] + x[1]); |
| 79 | + |
| 80 | +# Asy stable |
| 81 | +m = 1; b = 1; k = 1; # default values |
| 82 | +mpl.figure(); mpl.clf(); |
| 83 | +mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); |
| 84 | +PhasePlot(oscillator_ode, 'timepts', [0.3, 1, 2, 3], None, |
| 85 | + [[-1,1], [-0.3,1], [0,1], [0.25,1], [0.5,1], [0.7,1], [1,1], [1.3,1], |
| 86 | + [1,-1], [0.3,-1], [0,-1], [-0.25,-1], [-0.5,-1], [-0.7,-1], [-1,-1], |
| 87 | + [-1.3,-1]], |
| 88 | + np.linspace(0, 10, 100), parms = (m, b, k)); |
| 89 | +mpl.hold(True); mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); |
| 90 | +# set(gca,'FontSize', 16); |
| 91 | +mpl.xlabel('{\itx}_1'); mpl.ylabel('{\itx}_2'); |
| 92 | + |
| 93 | +# Saddle |
| 94 | +mpl.figure(); mpl.clf(); |
| 95 | +mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); |
| 96 | +PhasePlot(saddle_ode, 'timepts', [0.2, 0.5, 0.8], None, |
| 97 | + [ [-1, -1], [1, 1], |
| 98 | + [-1, -0.95], [-1, -0.9], [-1, -0.8], [-1, -0.6], [-1, -0.4], [-1, -0.2], |
| 99 | + [-0.95, -1], [-0.9, -1], [-0.8, -1], [-0.6, -1], [-0.4, -1], [-0.2, -1], |
| 100 | + [1, 0.95], [1, 0.9], [1, 0.8], [1, 0.6], [1, 0.4], [1, 0.2], |
| 101 | + [0.95, 1], [0.9, 1], [0.8, 1], [0.6, 1], [0.4, 1], [0.2, 1], |
| 102 | + [-0.5, -0.45], [-0.45, -0.5], [0.5, 0.45], [0.45, 0.5], |
| 103 | + [-0.04, 0.04], [0.04, -0.04] ], np.linspace(0, 2, 20)); |
| 104 | +mpl.hold(True); mpl.plot([0], [0], 'k.'); # 'MarkerSize', AM_data_markersize*3); |
| 105 | +# set(gca,'FontSize', 16); |
| 106 | +mpl.xlabel('{\itx}_1'); mpl.ylabel('{\itx}_2'); |
| 107 | + |
| 108 | +# Stable isL |
| 109 | +m = 1; b = 0; k = 1; # zero damping |
| 110 | +mpl.figure(); mpl.clf(); |
| 111 | +mpl.axis([-1, 1, -1, 1]); # set(gca, 'DataAspectRatio', [1 1 1]); |
| 112 | +PhasePlot(oscillator_ode, 'timepts', |
| 113 | + [pi/6, pi/3, pi/2, 2*pi/3, 5*pi/6, pi, 7*pi/6, 4*pi/3, 9*pi/6, 5*pi/3, 11*pi/6, 2*pi], None, |
| 114 | + [ [0.2,0], [0.4,0], [0.6,0], [0.8,0], [1,0], [1.2,0], [1.4,0] ], |
| 115 | + np.linspace(0, 20, 200), parms = (m, b, k)); |
| 116 | +mpl.hold(True); mpl.plot([0], [0], 'k.') # 'MarkerSize', AM_data_markersize*3); |
| 117 | +# set(gca,'FontSize', 16); |
| 118 | +mpl.xlabel('{\itx}_1'); mpl.ylabel('{\itx}_2'); |
| 119 | + |
| 120 | +mpl.show() |
0 commit comments