|
From: <mur...@us...> - 2011-02-13 16:50:05
|
Revision: 134
http://python-control.svn.sourceforge.net/python-control/?rev=134&view=rev
Author: murrayrm
Date: 2011-02-13 16:49:58 +0000 (Sun, 13 Feb 2011)
Log Message:
-----------
Copied over latest changes from v0.3d:
* Added in latest nichols() code from Allan McInnes (including 13 Feb commits)
* Turned svn:keyword Id back on for source code files
* Set version number to 0.4a
Modified Paths:
--------------
branches/control-0.4a/ChangeLog
branches/control-0.4a/setup.py
branches/control-0.4a/src/__init__.py
branches/control-0.4a/src/bdalg.py
branches/control-0.4a/src/ctrlutil.py
branches/control-0.4a/src/delay.py
branches/control-0.4a/src/freqplot.py
branches/control-0.4a/src/matlab.py
branches/control-0.4a/src/rlocus.py
branches/control-0.4a/src/statesp.py
branches/control-0.4a/src/xferfcn.py
Added Paths:
-----------
branches/control-0.4a/examples/bdalg-matlab.py
branches/control-0.4a/examples/test-response.py
branches/control-0.4a/examples/test-statefbk.py
Property Changed:
----------------
branches/control-0.4a/src/__init__.py
branches/control-0.4a/src/bdalg.py
branches/control-0.4a/src/ctrlutil.py
branches/control-0.4a/src/delay.py
branches/control-0.4a/src/exception.py
branches/control-0.4a/src/freqplot.py
branches/control-0.4a/src/lti.py
branches/control-0.4a/src/matlab.py
branches/control-0.4a/src/modelsimp.py
branches/control-0.4a/src/pzmap.py
branches/control-0.4a/src/rlocus.py
branches/control-0.4a/src/robust.py
branches/control-0.4a/src/statefbk.py
branches/control-0.4a/src/statesp.py
branches/control-0.4a/src/test.py
branches/control-0.4a/src/xferfcn.py
Modified: branches/control-0.4a/ChangeLog
===================================================================
--- branches/control-0.4a/ChangeLog 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/ChangeLog 2011-02-13 16:49:58 UTC (rev 134)
@@ -1,3 +1,18 @@
+2011-02-13 Richard Murray <mu...@su...>
+
+ * src/*.py: added svn:keywords Id properly
+
+ * src/matlab.py (ngrid): added ngrid() from v0.3d
+
+ * src/freqplot.py (nichols_grid, closed_loop_contours, m_circles,
+ n_circles): copied over changes from Allan McInnes in v0.3d; ngrid()
+ functiality + split out some of the nichols chart code into separate
+ functions
+
+2011-02-12 Richard Murray <mu...@su...>
+
+ * setup.py: updated version number to 0.4a
+
2010-11-05 Richard Murray <mu...@su...>
* external/yottalab.py: New file containing Roberto Bucher's control
Copied: branches/control-0.4a/examples/bdalg-matlab.py (from rev 132, trunk/examples/bdalg-matlab.py)
===================================================================
--- branches/control-0.4a/examples/bdalg-matlab.py (rev 0)
+++ branches/control-0.4a/examples/bdalg-matlab.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -0,0 +1,17 @@
+# bdalg-matlab.py - demonstrate some MATLAB commands for block diagram altebra
+# RMM, 29 May 09
+
+from control.matlab import * # MATLAB-like functions
+
+# System matrices
+A1 = [[0, 1.], [-4, -1]]
+B1 = [[0], [1.]]
+C1 = [[1., 0]]
+sys1ss = ss(A1, B1, C1, 0)
+sys1tf = ss2tf(sys1ss)
+
+sys2tf = tf([1, 0.5], [1, 5]);
+sys2ss = tf2ss(sys2tf);
+
+# Series composition
+series1 = sys1ss + sys2ss;
Copied: branches/control-0.4a/examples/test-response.py (from rev 132, trunk/examples/test-response.py)
===================================================================
--- branches/control-0.4a/examples/test-response.py (rev 0)
+++ branches/control-0.4a/examples/test-response.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -0,0 +1,18 @@
+# test-response.py - Unit tests for system response functions
+# RMM, 11 Sep 2010
+
+from matplotlib.pyplot import * # Grab MATLAB plotting functions
+from control.matlab import * # Load the controls systems library
+from scipy import arange # function to create range of numbers
+
+# Create several systems for testing
+sys1 = tf([1], [1, 2, 1])
+sys2 = tf([1, 1], [1, 1, 0])
+
+# Generate step responses
+(T1a, y1a) = step(sys1)
+(T1b, y1b) = step(sys1, T = arange(0, 10, 0.1))
+(T1c, y1c) = step(sys1, X0 = [1, 0])
+(T2a, y2a) = step(sys2, T = arange(0, 10, 0.1))
+
+plot(T1a, y1a, T1b, y1b, T1c, y1c, T2a, y2a)
Copied: branches/control-0.4a/examples/test-statefbk.py (from rev 132, trunk/examples/test-statefbk.py)
===================================================================
--- branches/control-0.4a/examples/test-statefbk.py (rev 0)
+++ branches/control-0.4a/examples/test-statefbk.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -0,0 +1,27 @@
+# test-statefbk.py - Unit tests for state feedback code
+# RMM, 6 Sep 2010
+
+import numpy as np # Numerical library
+from scipy import * # Load the scipy functions
+from control.matlab import * # Load the controls systems library
+
+# Parameters defining the system
+m = 250.0 # system mass
+k = 40.0 # spring constant
+b = 60.0 # damping constant
+
+# System matrices
+A = matrix([[1, -1, 1.], [1, -k/m, -b/m], [1, 1, 1]])
+B = matrix([[0], [1/m], [1]])
+C = matrix([[1., 0, 1.]])
+sys = ss(A, B, C, 0);
+
+# Controllability
+Wc = ctrb(A, B)
+print "Wc = ", Wc
+
+# Observability
+Wo = obsv(A, C)
+print "Wo = ", Wo
+
+
Modified: branches/control-0.4a/setup.py
===================================================================
--- branches/control-0.4a/setup.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/setup.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -3,7 +3,7 @@
from distutils.core import setup
setup(name='control',
- version='0.3c',
+ version='0.4a',
description='Python Control Systems Library',
author='Richard Murray',
author_email='mu...@cd...',
Modified: branches/control-0.4a/src/__init__.py
===================================================================
--- branches/control-0.4a/src/__init__.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/__init__.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -37,7 +37,7 @@
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $Id: __init__.py 29 2010-11-06 13:03:55Z murrayrm $
+# $Id$
"""Control System Library
Property changes on: branches/control-0.4a/src/__init__.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/bdalg.py
===================================================================
--- branches/control-0.4a/src/bdalg.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/bdalg.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -47,7 +47,7 @@
Date: 24 May 09
Revised: Kevin K. Chen, Dec 10
-$Id: bdalg.py 17 2010-05-29 23:50:52Z murrayrm $
+$Id$
"""
Property changes on: branches/control-0.4a/src/bdalg.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/ctrlutil.py
===================================================================
--- branches/control-0.4a/src/ctrlutil.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/ctrlutil.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -38,7 +38,7 @@
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $Id: ctrlutil.py 21 2010-06-06 17:29:42Z murrayrm $
+# $Id$
# Packages that we need access to
import scipy as sp
Property changes on: branches/control-0.4a/src/ctrlutil.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/delay.py
===================================================================
--- branches/control-0.4a/src/delay.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/delay.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -38,7 +38,7 @@
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $Id: pade.py 17 2010-05-29 23:50:52Z murrayrm $
+# $Id$
def pade(T, n=1):
"""
Property changes on: branches/control-0.4a/src/delay.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/exception.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/freqplot.py
===================================================================
--- branches/control-0.4a/src/freqplot.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/freqplot.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -38,7 +38,7 @@
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $Id: freqplot.py 33 2010-11-26 21:59:57Z murrayrm $
+# $Id$
import matplotlib.pyplot as plt
import scipy as sp
@@ -212,16 +212,15 @@
plt.plot([-1], [0], 'r+')
return x, y, omega
-
# Nichols plot
# Contributed by Allan McInnes <All...@ca...>
#! TODO: need unit test code
-def nichols(syslist, omega=None, Plot=True):
+def nichols(syslist, omega=None):
"""Nichols plot for a system
Usage
=====
- mag, phase, freq = nichols(sys, omega=None, Plot=True)
+ magh = nichols(sys, omega=None)
Plots a Nichols plot for the system over a (optional) frequency range.
@@ -231,15 +230,10 @@
List of linear input/output systems (single system is OK)
omega : freq_range
Range of frequencies (list or bounds) in rad/sec
- Plot : boolean
- if True, plot the Nichols frequency response
Return values
-------------
- mag : array of magnitudes
- phase : array of phases
- freq : array of frequencies
-
+ None
"""
# If argument was a singleton, turn it into a list
@@ -250,35 +244,107 @@
if (omega == None):
omega = default_frequency_range(syslist)
-
for sys in syslist:
- if (sys.inputs > 1 or sys.outputs > 1):
- #TODO: Add MIMO nichols plots.
- raise NotImplementedError("Nichols is currently only implemented for SISO systems.")
- else:
- # Get the magnitude and phase of the system
- mag_tmp, phase_tmp, omega = sys.freqresp(omega)
- mag = np.squeeze(mag_tmp)
- phase = np.squeeze(phase_tmp)
-
- # Convert to Nichols-plot format (phase in degrees,
- # and magnitude in dB)
- x = unwrap(sp.degrees(phase), 360)
- y = 20*sp.log10(mag)
+ # Get the magnitude and phase of the system
+ mag, phase, omega = sys.freqresp(omega)
- if (Plot):
- # Generate the plot
- plt.plot(x, y)
+ # Convert to Nichols-plot format (phase in degrees,
+ # and magnitude in dB)
+ x = unwrap(sp.degrees(phase), 360)
+ y = 20*sp.log10(mag)
+
+ # Generate the plot
+ plt.plot(x, y)
- plt.xlabel('Phase (deg)')
- plt.ylabel('Magnitude (dB)')
- plt.title('Nichols Plot')
+ plt.xlabel('Phase (deg)')
+ plt.ylabel('Magnitude (dB)')
+ plt.title('Nichols Plot')
- # Mark the -180 point
- plt.plot([-180], [0], 'r+')
+ # Mark the -180 point
+ plt.plot([-180], [0], 'r+')
- return mag, phase, omega
+# Nichols grid
+def nichols_grid():
+ """Nichols chart grid
+
+ Usage
+ =====
+ nichols_grid()
+ Plots a Nichols chart grid on the current axis.
+
+ Parameters
+ ----------
+ None
+
+ Return values
+ -------------
+ None
+ """
+ mag_min_default = -40.0 # dB
+ mag_step = 20.0 # dB
+
+ # Chart defaults
+ phase_min, phase_max, mag_min, mag_max = -360.0, 0.0, mag_min_default, 40.0
+
+ # Set actual chart bounds based on current plot
+ if plt.gcf().gca().has_data():
+ phase_min, phase_max, mag_min, mag_max = plt.axis()
+
+ # M-circle magnitudes.
+ # The "fixed" set are always generated, since this guarantees a recognizable
+ # Nichols chart grid.
+ mags_fixed = np.array([-40.0, -20.0, -12.0, -6.0, -3.0, -1.0, -0.5, 0.0,
+ 0.25, 0.5, 1.0, 3.0, 6.0, 12.0])
+
+ if mag_min < mag_min_default:
+ # Outside the "fixed" set of magnitudes, the generated M-circles
+ # are extended in steps of 'mag_step' dB to cover anything made
+ # visible by the range of the existing plot
+ mags_adjust = np.arange(mag_step*np.floor(mag_min/mag_step),
+ mag_min_default, mag_step)
+ mags = np.concatenate((mags_adjust, mags_fixed))
+ else:
+ mags = mags_fixed
+
+ # N-circle phases (should be in the range -360 to 0)
+ phases = np.array([-0.25, -10.0, -20.0, -30.0, -45.0, -60.0, -90.0,
+ -120.0, -150.0, -180.0, -210.0, -240.0, -270.0,
+ -310.0, -325.0, -340.0, -350.0, -359.75])
+
+ # Find the M-contours
+ m = m_circles(mags, phase_min=np.min(phases), phase_max=np.max(phases))
+ m_mag = 20*sp.log10(np.abs(m))
+ m_phase = sp.mod(sp.degrees(sp.angle(m)), -360.0) # Unwrap
+
+ # Find the N-contours
+ n = n_circles(phases, mag_min=np.min(mags), mag_max=np.max(mags))
+ n_mag = 20*sp.log10(np.abs(n))
+ n_phase = sp.mod(sp.degrees(sp.angle(n)), -360.0) # Unwrap
+
+ # Plot the contours behind other plot elements.
+ # The "phase offset" is used to produce copies of the chart that cover
+ # the entire range of the plotted data, starting from a base chart computed
+ # over the range -360 < phase < 0 (see above). Given the range
+ # the base chart is computed over, the phase offset should be 0
+ # for -360 < phase_min < 0.
+ phase_offset_min = 360.0*np.ceil(phase_min/360.0)
+ phase_offset_max = 360.0*np.ceil(phase_max/360.0) + 360.0
+ phase_offsets = np.arange(phase_offset_min, phase_offset_max, 360.0)
+ for phase_offset in phase_offsets:
+ plt.plot(m_phase + phase_offset, m_mag, color='gray',
+ linestyle='dashed', zorder=0)
+ plt.plot(n_phase + phase_offset, n_mag, color='gray',
+ linestyle='dashed', zorder=0)
+
+ # Add magnitude labels
+ for x, y, m in zip(m_phase[:][-1], m_mag[:][-1], mags):
+ align = 'right' if m < 0.0 else 'left'
+ plt.text(x, y, str(m) + ' dB', size='small', ha=align)
+
+ # Make sure axes conform to any pre-existing plot.
+ plt.axis([phase_min, phase_max, mag_min, mag_max])
+
# Gang of Four
#! TODO: think about how (and whether) to handle lists of systems
def gangof4(P, C, omega=None):
@@ -395,3 +461,85 @@
np.ceil(np.max(features))+1)
return omega
+
+# Compute contours of a closed-loop transfer function
+def closed_loop_contours(Hmag, Hphase):
+ """Contours of the function H = G/(1+G).
+
+ Usage
+ =====
+ contours = closed_loop_contours(mags, phases)
+
+ Parameters
+ ----------
+ mags : array-like
+ Meshgrid array of magnitudes of the contours
+ phases : array-like
+ Meshgrid array of phases in radians of the contours
+
+ Return values
+ -------------
+ contours : complex array
+ Array of complex numbers corresponding to the contours.
+ """
+ # Compute the contours in H-space
+ H = Hmag*sp.exp(1.j*Hphase)
+
+ # Invert H = G/(1+G) to get an expression for the contours in G-space
+ return H/(1.0 - H)
+
+# M-circle
+def m_circles(mags, phase_min=-359.75, phase_max=-0.25):
+ """Constant-magnitude contours of the function H = G/(1+G).
+
+ Usage
+ =====
+ contours = m_circles(mags)
+
+ Parameters
+ ----------
+ mags : array-like
+ Array of magnitudes in dB of the M-circles
+ phase_min : degrees
+ Minimum phase in degrees of the N-circles
+ phase_max : degrees
+ Maximum phase in degrees of the N-circles
+
+ Return values
+ -------------
+ contours : complex array
+ Array of complex numbers corresponding to the contours.
+ """
+ # Convert magnitudes and phase range into a grid suitable for
+ # building contours
+ phases = sp.radians(sp.linspace(phase_min, phase_max, 500))
+ Hmag, Hphase = sp.meshgrid(10.0**(mags/20.0), phases)
+ return closed_loop_contours(Hmag, Hphase)
+
+# N-circle
+def n_circles(phases, mag_min=-40.0, mag_max=12.0):
+ """Constant-phase contours of the function H = G/(1+G).
+
+ Usage
+ =====
+ contour = n_circles(angles)
+
+ Parameters
+ ----------
+ phases : array-like
+ Array of phases in degrees of the N-circles
+ mag_min : dB
+ Minimum magnitude in dB of the N-circles
+ mag_max : dB
+ Maximum magnitude in dB of the N-circles
+
+ Return values
+ -------------
+ contours : complex array
+ Array of complex numbers corresponding to the contours.
+ """
+ # Convert phases and magnitude range into a grid suitable for
+ # building contours
+ mags = sp.linspace(10**(mag_min/20.0), 10**(mag_max/20.0), 2000)
+ Hphase, Hmag = sp.meshgrid(sp.radians(phases), mags)
+ return closed_loop_contours(Hmag, Hphase)
Property changes on: branches/control-0.4a/src/freqplot.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/lti.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/matlab.py
===================================================================
--- branches/control-0.4a/src/matlab.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/matlab.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -51,7 +51,7 @@
Date: 29 May 09
Revised: Kevin K. Chen, Dec 10
-$Id: matlab.py 33 2010-11-26 21:59:57Z murrayrm $
+$Id$
"""
@@ -744,6 +744,16 @@
# Call the bode command
return freqplot.bode(syslist, omega, **keywords)
+# Nichols chart grid
+def ngrid():
+ """Nichols chart grid.
+
+ Usage
+ =====
+ ngrid()
+ """
+ freqplot.nichols_grid()
+
#
# Modifications to scipy.signal functions
#
Property changes on: branches/control-0.4a/src/matlab.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/modelsimp.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/pzmap.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/rlocus.py
===================================================================
--- branches/control-0.4a/src/rlocus.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/rlocus.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -40,7 +40,7 @@
# or a controls.TransferFunction object.
# * Added some comments to make sure I understand the code
#
-# $Id: rlocus.py 29 2010-11-06 13:03:55Z murrayrm $
+# $Id$
# Packages used by this module
from scipy import *
Property changes on: branches/control-0.4a/src/rlocus.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/robust.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/statefbk.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/statesp.py
===================================================================
--- branches/control-0.4a/src/statesp.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/statesp.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -68,7 +68,7 @@
Date: 24 May 09
Revised: Kevin K. Chen, Dec 10
-$Id: statepy 21 2010-06-06 17:29:42Z murrayrm $
+$Id$
"""
Property changes on: branches/control-0.4a/src/statesp.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: branches/control-0.4a/src/test.py
___________________________________________________________________
Added: svn:keywords
+ Id
Modified: branches/control-0.4a/src/xferfcn.py
===================================================================
--- branches/control-0.4a/src/xferfcn.py 2011-02-13 13:21:29 UTC (rev 133)
+++ branches/control-0.4a/src/xferfcn.py 2011-02-13 16:49:58 UTC (rev 134)
@@ -70,7 +70,7 @@
Date: 24 May 09
Revised: Kevin K. Chewn, Dec 10
-$Id: xferfcn.py 21 2010-06-06 17:29:42Z murrayrm $
+$Id$
"""
Property changes on: branches/control-0.4a/src/xferfcn.py
___________________________________________________________________
Added: svn:keywords
+ Id
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|