|
From: <mur...@us...> - 2011-06-18 19:13:17
|
Revision: 161
http://python-control.svn.sourceforge.net/python-control/?rev=161&view=rev
Author: murrayrm
Date: 2011-06-18 19:13:09 +0000 (Sat, 18 Jun 2011)
Log Message:
-----------
Added Eike's Welk's time response functions, including MIMO
capability. To maintain MATLAB compatibility, the underlying
functions have been moved to a new module, timeresp, and renamed
ForcedResponse (lsim), InitialResponse (initial), ImpulseResponse
(impulse), StepResponse (step). MATLAB version of the functions (with
the usual names: lsim, impulse, initial, step) use MATLAB conventions
for time vectors.
See ChangeLog for detailed list of changes.
Modified Paths:
--------------
trunk/ChangeLog
trunk/doc/conf.py
trunk/examples/pvtol-lqr.py
trunk/examples/pvtol-nested-ss.py
trunk/examples/pvtol-nested.py
trunk/src/__init__.py
trunk/src/matlab.py
trunk/src/statesp.py
trunk/tests/matlab_test.py
Added Paths:
-----------
trunk/src/timeresp.py
trunk/tests/test_control_matlab.py
trunk/tests/timeresp_test.py
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/ChangeLog 2011-06-18 19:13:09 UTC (rev 161)
@@ -1,3 +1,66 @@
+2011-06-18 Richard Murray <mu...@ma...>
+
+ * src/timeresp.py, src/matlab.py: moved documentation about time
+ series convention from matlab.py to timeresp.py
+
+ * examples/pvtol-nested-ss.py: Fixed bug in call to step (wrong
+ second argument)
+
+ * tests/matlab_test.py: Updated tests to use MATLAB time response
+ conventions.
+
+ * tests/timeresp_test.py: Created unit tests for timeresp module,
+ based on matlab_test.py
+
+2011-06-17 Richard Murray <mu...@ma...>
+
+ * src/timeresp.py (ForcedResponse): swapped order of input and time
+ arguments for linear response, following Eike's comment "T must
+ always be supplied by the user, but U has a useful default value of
+ 0."
+
+ * src/matlab.py: moved code for lsim, initial, step, and impulse to
+ timeresp.py and put in new routes that call timeresp.* versions of
+ the functions with transposeData set to True.
+
+ * src/timesim.py (_check_convert_array): added transpose argument
+ that will transpose input data before processing it.
+
+ * src/timesim.py: renamed lsim, initial, step, and impulse functions
+ to ForcedResponse, InitialResponse, StepResponse and
+ ImpulseResponse. These versions use Eike Welk's input ordering.
+
+ * examples/pvtol-nested.py: calls to step() had screwed up inputs.
+ Fixed.
+
+2011-06-17 Richard Murray <mu...@ma...>
+
+ * src/matlab.py: added MIMO extensions from Eike Welk on 12 Jun
+ 2011: adds MIMO capabilities for ``lsim``, ``step``, ``impulse``,
+ ``initial``
+
+ * src/matlab.py: added changes from Eike Welk on 12 May 2011:
+
+ - An implementation of the four simulation functions ``lsim``,
+ ``step``, ``initial``, and ``impulse`` of the module ``matlab``.
+
+ - Adds a function ``dcgain`` to the ``matlab`` module, which
+ computes the gain of a linear system for steady state and
+ constant input.
+
+ - The patch contains a bug fix for class ``StateSpace``, which
+ enables it to work properly together with Scipy's ``signal``
+ module.
+
+ - The simulation functions' return values are changed (back?) to
+ arrays, because matrices confuse Matplotlib.
+
+ - New times series convention: see _time-series-convention section
+ of matlab documentation
+
+ - SISO simulation data are squeezed on output. To turn this off,
+ pass the option squeeze=False
+
---- control-0.4c released -----
2011-06-17 Richard Murray <mu...@dh...>
Modified: trunk/doc/conf.py
===================================================================
--- trunk/doc/conf.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/doc/conf.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -26,7 +26,8 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc','numpydoc']
+extensions = ['sphinx.ext.autodoc', 'numpydoc', 'sphinx.ext.pngmath',
+ 'sphinx.ext.intersphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -87,7 +88,11 @@
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
+#This config value contains the locations and names of other projects that
+#should be linked to in this documentation.
+intersphinx_mapping = {'scipy':('http://docs.scipy.org/doc/scipy/reference/', None)}
+
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
Modified: trunk/examples/pvtol-lqr.py
===================================================================
--- trunk/examples/pvtol-lqr.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/examples/pvtol-lqr.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -119,7 +119,7 @@
subplot(221); title("Identity weights")
# plot(T, Y[:,1, 1], '-', T, Y[:,2, 2], '--'); hold(True);
-plot(Tx.T, Yx[0,:].T, '-', Ty.T, Yy[0,:].T, '--'); hold(True);
+plot(Tx.T, Yx.T, '-', Ty.T, Yy.T, '--'); hold(True);
plot([0, 10], [1, 1], 'k-'); hold(True);
axis([0, 10, -0.1, 1.4]);
@@ -141,9 +141,9 @@
[T3, Y3] = step(H1cx, T=linspace(0,10,100));
subplot(222); title("Effect of input weights")
-plot(T1.T, Y1[0,:].T, 'b-'); hold(True);
-plot(T2.T, Y2[0,:].T, 'b-'); hold(True);
-plot(T3.T, Y3[0,:].T, 'b-'); hold(True);
+plot(T1.T, Y1.T, 'b-'); hold(True);
+plot(T2.T, Y2.T, 'b-'); hold(True);
+plot(T3.T, Y3.T, 'b-'); hold(True);
plot([0 ,10], [1, 1], 'k-'); hold(True);
axis([0, 10, -0.1, 1.4]);
@@ -162,7 +162,7 @@
subplot(223); title("Output weighting")
[T2x, Y2x] = step(H2x, T=linspace(0,10,100));
[T2y, Y2y] = step(H2y, T=linspace(0,10,100));
-plot(T2x.T, Y2x[0,:].T, T2y.T, Y2y[0,:].T)
+plot(T2x.T, Y2x.T, T2y.T, Y2y.T)
ylabel('position');
xlabel('time'); ylabel('position');
legend(('x', 'y'), loc='lower right');
@@ -185,7 +185,7 @@
# step(H3x, H3y, 10);
[T3x, Y3x] = step(H3x, T=linspace(0,10,100));
[T3y, Y3y] = step(H3y, T=linspace(0,10,100));
-plot(T3x.T, Y3x[0,:].T, T3y.T, Y3y[0,:].T)
+plot(T3x.T, Y3x.T, T3y.T, Y3y.T)
title("Physically motivated weights")
xlabel('time');
legend(('x', 'y'), loc='lower right');
Modified: trunk/examples/pvtol-nested-ss.py
===================================================================
--- trunk/examples/pvtol-nested-ss.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/examples/pvtol-nested-ss.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -144,10 +144,10 @@
# 'EdgeColor', color, 'FaceColor', color);
figure(9);
-(Tvec, Yvec) = step(T, None, linspace(1, 20));
+(Tvec, Yvec) = step(T, linspace(1, 20));
plot(Tvec.T, Yvec.T); hold(True);
-(Tvec, Yvec) = step(Co*S, None, linspace(1, 20));
+(Tvec, Yvec) = step(Co*S, linspace(1, 20));
plot(Tvec.T, Yvec.T);
#TODO: PZmap for statespace systems has not yet been implemented.
Modified: trunk/examples/pvtol-nested.py
===================================================================
--- trunk/examples/pvtol-nested.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/examples/pvtol-nested.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -134,10 +134,10 @@
# 'EdgeColor', color, 'FaceColor', color);
figure(9);
-(Tvec, Yvec) = step(T, None, linspace(1, 20));
+(Tvec, Yvec) = step(T, linspace(1, 20));
plot(Tvec.T, Yvec.T); hold(True);
-(Tvec, Yvec) = step(Co*S, None, linspace(1, 20));
+(Tvec, Yvec) = step(Co*S, linspace(1, 20));
plot(Tvec.T, Yvec.T);
figure(10); clf();
Modified: trunk/src/__init__.py
===================================================================
--- trunk/src/__init__.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/src/__init__.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -66,3 +66,5 @@
from modelsimp import *
from rlocus import *
from mateqn import *
+from timeresp import ForcedResponse, InitialResponse, StepResponse, \
+ ImpulseResponse
Modified: trunk/src/matlab.py
===================================================================
--- trunk/src/matlab.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/src/matlab.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""matlab.py
MATLAB emulation functions.
@@ -18,6 +19,8 @@
"""Copyright (c) 2009 by California Institute of Technology
All rights reserved.
+Copyright (c) 2011 by Eike Welk
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
@@ -58,8 +61,9 @@
# Libraries that we make use of
import scipy as sp # SciPy library (used all over)
import numpy as np # NumPy library
-import scipy.signal as signal # Signal processing library
+from scipy.signal.ltisys import _default_response_times
from copy import deepcopy
+import warnings
# Import MATLAB-like functions that are defined in other packages
from scipy.signal import zpk2ss, ss2zpk, tf2zpk, zpk2tf
@@ -68,8 +72,10 @@
# Control system library
import ctrlutil
import freqplot
+import timeresp
from statesp import StateSpace, _rss_generate, _convertToStateSpace
from xferfcn import TransferFunction, _convertToTransferFunction
+from lti import Lti #base class of StateSpace, TransferFunction
from exception import ControlArgument
# Import MATLAB-like functions that can be used as-is
@@ -86,188 +92,216 @@
__doc__ += """
The control.matlab module defines functions that are roughly the
equivalents of those in the MATLAB Control Toolbox. Items marked by a
-\* are currently implemented; those marked with a ``-`` are not planned
+``*`` are currently implemented; those marked with a ``-`` are not planned
for implementation.
-Creating linear models.
-\* tf - create transfer function (TF) models
- zpk - create zero/pole/gain (ZPK) models.
-\* ss - create state-space (SS) models
- dss - create descriptor state-space models
- delayss - create state-space models with delayed terms
- frd - create frequency response data (FRD) models
- lti/exp - create pure continuous-time delays (TF and ZPK only)
- filt - specify digital filters
-- lti/set - set/modify properties of LTI models
-- setdelaymodel - specify internal delay model (state space only)
-
-Data extraction
- lti/tfdata - extract numerators and denominators
- lti/zpkdata - extract zero/pole/gain data
- lti/ssdata - extract state-space matrices
- lti/dssdata - descriptor version of SSDATA
- frd/frdata - extract frequency response data
- lti/get - access values of LTI model properties
- ss/getDelayModel - access internal delay model (state space only)
-
-Conversions
-\* tf - conversion to transfer function
- zpk - conversion to zero/pole/gain
-\* ss - conversion to state space
- frd - conversion to frequency data
- c2d - continuous to discrete conversion
- d2c - discrete to continuous conversion
- d2d - resample discrete-time model
- upsample - upsample discrete-time LTI systems
-\* ss2tf - state space to transfer function
- ss2zpk - transfer function to zero-pole-gain
-\* tf2ss - transfer function to state space
- tf2zpk - transfer function to zero-pole-gain
- zpk2ss - zero-pole-gain to state space
- zpk2tf - zero-pole-gain to transfer function
-
-System interconnections
- append - group LTI models by appending inputs and outputs
-\* parallel - connect LTI models in parallel (see also overloaded +)
-\* series - connect LTI models in series (see also overloaded \*)
-\* feedback - connect lti models with a feedback loop
- lti/lft - generalized feedback interconnection
- lti/connect - arbitrary interconnection of lti models
- sumblk - specify summing junction (for use with connect)
- strseq - builds sequence of indexed strings (for I/O naming)
-
-System gain and dynamics
- dcgain - steady-state (D.C.) gain
- lti/bandwidth - system bandwidth
- lti/norm - h2 and Hinfinity norms of LTI models
-\* lti/pole - system poles
-\* lti/zero - system (transmission) zeros
- lti/order - model order (number of states)
-\* pzmap - pole-zero map (TF only)
- lti/iopzmap - input/output pole-zero map
- damp - natural frequency and damping of system poles
- esort - sort continuous poles by real part
- dsort - sort discrete poles by magnitude
- lti/stabsep - stable/unstable decomposition
- lti/modsep - region-based modal decomposition
-
-Time-domain analysis
-\* step - step response
- stepinfo - step response characteristics (rise time, ...)
-\* impulse - impulse response
- initial - free response with initial conditions
-\* lsim - response to user-defined input signal
- lsiminfo - linear response characteristics
- gensig - generate input signal for LSIM
- covar - covariance of response to white noise
-
-Frequency-domain analysis
-\* bode - Bode plot of the frequency response
- lti/bodemag - Bode magnitude diagram only
- sigma - singular value frequency plot
-\* nyquist - Nyquist plot
-\* nichols - Nichols plot
- margin - gain and phase margins
- lti/allmargin - all crossover frequencies and related gain/phase margins
-\* lti/freqresp - frequency response over a frequency grid
-\* lti/evalfr - evaluate frequency response at given frequency
-
-Model simplification
- minreal - minimal realization and pole/zero cancellation
- ss/sminreal - structurally minimal realization (state space)
-\* lti/hsvd - hankel singular values (state contributions)
-\* lti/balred - reduced-order approximations of LTI models
-\* ss/modred - model order reduction
-
-Compensator design
-\* rlocus - evans root locus
-\* place - pole placement
- estim - form estimator given estimator gain
- reg - form regulator given state-feedback and estimator gains
-
-LQR/LQG design
- ss/lqg - single-step LQG design
-\* lqr - linear-Quadratic (LQ) state-feedback regulator
- dlqr - discrete-time LQ state-feedback regulator
- lqry - lq regulator with output weighting
- lqrd - discrete LQ regulator for continuous plant
- ss/lqi - linear-Quadratic-Integral (LQI) controller
- ss/kalman - Kalman state estimator
- ss/kalmd - discrete Kalman estimator for continuous plant
- ss/lqgreg - build LQG regulator from LQ gain and Kalman estimator
- ss/lqgtrack - build LQG servo-controller
- augstate - augment output by appending states
-
-State-space (SS) models
-\* rss - random stable continuous-time state-space models
-\* drss - random stable discrete-time state-space models
- ss2ss - state coordinate transformation
- canon - canonical forms of state-space models
-\* ctrb - controllability matrix
-\* obsv - observability matrix
-\* gram - controllability and observability gramians
- ss/prescale - optimal scaling of state-space models.
- balreal - gramian-based input/output balancing
- ss/xperm - reorder states.
-
-Frequency response data (FRD) models
- frd/chgunits - change frequency vector units
- frd/fcat - merge frequency responses
- frd/fselect - select frequency range or subgrid
- frd/fnorm - peak gain as a function of frequency
- frd/abs - entrywise magnitude of the frequency response
- frd/real - real part of the frequency response
- frd/imag - imaginary part of the frequency response
- frd/interp - interpolate frequency response data
- mag2db - convert magnitude to decibels (dB)
- db2mag - convert decibels (dB) to magnitude
-
-Time delays
- lti/hasdelay - true for models with time delays
- lti/totaldelay - total delay between each input/output pair
- lti/delay2z - replace delays by poles at z=0 or FRD phase shift
-\* pade - pade approximation of time delays
-
-Model dimensions and characteristics
- class - model type ('tf', 'zpk', 'ss', or 'frd')
- isa - test if model is of given type
- tf/size - model sizes
- lti/ndims - number of dimensions
- lti/isempty - true for empty models
- lti/isct - true for continuous-time models
- lti/isdt - true for discrete-time models
- lti/isproper - true for proper models
- lti/issiso - true for single-input/single-output models
- lti/isstable - true for models with stable dynamics
- lti/reshape - reshape array of linear models
-
-Overloaded arithmetic operations
-\* + and - - add and subtract systems (parallel connection)
-\* \* - multiply systems (series connection)
- / - left divide -- sys1\sys2 means inv(sys1)\*sys2
-- \ - right divide -- sys1/sys2 means sys1\*inv(sys2)
- ^ - powers of a given system
- ' - pertransposition
- .' - transposition of input/output map
- .\* - element-by-element multiplication
- [..] - concatenate models along inputs or outputs
- lti/stack - stack models/arrays along some array dimension
- lti/inv - inverse of an LTI system
- lti/conj - complex conjugation of model coefficients
-
-Matrix equation solvers and linear algebra
-\* lyap, dlyap - solve Lyapunov equations
- lyapchol, dlyapchol - square-root Lyapunov solvers
-\* care, dare - solve algebraic Riccati equations
- gcare, gdare - generalized Riccati solvers
- bdschur - block diagonalization of a square matrix
-
-Additional functions
-\* gangof4 - generate the Gang of 4 sensitivity plots
-\* linspace - generate a set of numbers that are linearly spaced
-\* logspace - generate a set of numbers that are logarithmically spaced
-\* unwrap - unwrap a phase angle to give a continuous curve
-
+== ========================== ================================================
+**Creating linear models.**
+--------------------------------------------------------------------------------
+\* :func:`tf` create transfer function (TF) models
+\ zpk create zero/pole/gain (ZPK) models.
+\* :func:`ss` create state-space (SS) models
+\ dss create descriptor state-space models
+\ delayss create state-space models with delayed terms
+\ frd create frequency response data (FRD) models
+\ lti/exp create pure continuous-time delays (TF and ZPK
+ only)
+\ filt specify digital filters
+\- lti/set set/modify properties of LTI models
+\- setdelaymodel specify internal delay model (state space only)
+\
+**Data extraction**
+--------------------------------------------------------------------------------
+\ lti/tfdata extract numerators and denominators
+\ lti/zpkdata extract zero/pole/gain data
+\ lti/ssdata extract state-space matrices
+\ lti/dssdata descriptor version of SSDATA
+\ frd/frdata extract frequency response data
+\ lti/get access values of LTI model properties
+\ ss/getDelayModel access internal delay model (state space only)
+\
+**Conversions**
+--------------------------------------------------------------------------------
+\* :func:`tf` conversion to transfer function
+\ zpk conversion to zero/pole/gain
+\* :func:`ss` conversion to state space
+\ frd conversion to frequency data
+\ c2d continuous to discrete conversion
+\ d2c discrete to continuous conversion
+\ d2d resample discrete-time model
+\ upsample upsample discrete-time LTI systems
+\* :func:`ss2tf` state space to transfer function
+\ ss2zpk transfer function to zero-pole-gain
+\* :func:`tf2ss` transfer function to state space
+\ tf2zpk transfer function to zero-pole-gain
+\ zpk2ss zero-pole-gain to state space
+\ zpk2tf zero-pole-gain to transfer function
+\
+**System interconnections**
+--------------------------------------------------------------------------------
+\ append group LTI models by appending inputs and outputs
+\* :func:`parallel` connect LTI models in parallel
+ (see also overloaded +)
+\* :func:`series` connect LTI models in series
+ (see also overloaded \*)
+\* :func:`feedback` connect lti models with a feedback loop
+\ lti/lft generalized feedback interconnection
+\ lti/connect arbitrary interconnection of lti models
+\ sumblk specify summing junction (for use with connect)
+\ strseq builds sequence of indexed strings
+ (for I/O naming)
+\
+**System gain and dynamics**
+--------------------------------------------------------------------------------
+\* :func:`dcgain` steady-state (D.C.) gain
+\ lti/bandwidth system bandwidth
+\ lti/norm h2 and Hinfinity norms of LTI models
+\* :func:`pole` system poles
+\* :func:`zero` system (transmission) zeros
+\ lti/order model order (number of states)
+\* :func:`pzmap` pole-zero map (TF only)
+\ lti/iopzmap input/output pole-zero map
+\ damp natural frequency and damping of system poles
+\ esort sort continuous poles by real part
+\ dsort sort discrete poles by magnitude
+\ lti/stabsep stable/unstable decomposition
+\ lti/modsep region-based modal decomposition
+\
+**Time-domain analysis**
+--------------------------------------------------------------------------------
+\* :func:`step` step response
+\ stepinfo step response characteristics (rise time, ...)
+\* :func:`impulse` impulse response
+\* :func:`initial` free response with initial conditions
+\* :func:`lsim` response to user-defined input signal
+\ lsiminfo linear response characteristics
+\ gensig generate input signal for LSIM
+\ covar covariance of response to white noise
+\
+**Frequency-domain analysis**
+--------------------------------------------------------------------------------
+\* :func:`bode` Bode plot of the frequency response
+\ lti/bodemag Bode magnitude diagram only
+\ sigma singular value frequency plot
+\* :func:`nyquist` Nyquist plot
+\* :func:`nichols` Nichols plot
+\* :func:`margin` gain and phase margins
+\ lti/allmargin all crossover frequencies and related gain/phase
+ margins
+\* :func:`freqresp` frequency response over a frequency grid
+\* :func:`evalfr` evaluate frequency response at given frequency
+\
+**Model simplification**
+--------------------------------------------------------------------------------
+\ minreal minimal realization and pole/zero cancellation
+\ ss/sminreal structurally minimal realization (state space)
+\* :func:`lti/hsvd` hankel singular values (state contributions)
+\* :func:`lti/balred` reduced-order approximations of LTI models
+\* :func:`ss/modred` model order reduction
+\
+**Compensator design**
+--------------------------------------------------------------------------------
+\* :func:`rlocus` evans root locus
+\* :func:`place` pole placement
+\ estim form estimator given estimator gain
+\ reg form regulator given state-feedback and
+ estimator gains
+\
+**LQR/LQG design**
+--------------------------------------------------------------------------------
+\ ss/lqg single-step LQG design
+\* :func:`lqr` linear-Quadratic (LQ) state-feedback regulator
+\ dlqr discrete-time LQ state-feedback regulator
+\ lqry lq regulator with output weighting
+\ lqrd discrete LQ regulator for continuous plant
+\ ss/lqi linear-Quadratic-Integral (LQI) controller
+\ ss/kalman Kalman state estimator
+\ ss/kalmd discrete Kalman estimator for continuous plant
+\ ss/lqgreg build LQG regulator from LQ gain and Kalman
+ estimator
+\ ss/lqgtrack build LQG servo-controller
+\ augstate augment output by appending states
+\
+**State-space (SS) models**
+--------------------------------------------------------------------------------
+\* :func:`rss` random stable continuous-time state-space models
+\* :func:`drss` random stable discrete-time state-space models
+\ ss2ss state coordinate transformation
+\ canon canonical forms of state-space models
+\* :func:`ctrb` controllability matrix
+\* :func:`obsv` observability matrix
+\* :func:`gram` controllability and observability gramians
+\ ss/prescale optimal scaling of state-space models.
+\ balreal gramian-based input/output balancing
+\ ss/xperm reorder states.
+\
+**Frequency response data (FRD) models**
+--------------------------------------------------------------------------------
+\ frd/chgunits change frequency vector units
+\ frd/fcat merge frequency responses
+\ frd/fselect select frequency range or subgrid
+\ frd/fnorm peak gain as a function of frequency
+\ frd/abs entrywise magnitude of the frequency response
+\ frd/real real part of the frequency response
+\ frd/imag imaginary part of the frequency response
+\ frd/interp interpolate frequency response data
+\ mag2db convert magnitude to decibels (dB)
+\ db2mag convert decibels (dB) to magnitude
+\
+**Time delays**
+--------------------------------------------------------------------------------
+\ lti/hasdelay true for models with time delays
+\ lti/totaldelay total delay between each input/output pair
+\ lti/delay2z replace delays by poles at z=0 or FRD phase
+ shift
+\* :func:`pade` pade approximation of time delays
+\
+**Model dimensions and characteristics**
+--------------------------------------------------------------------------------
+\ class model type ('tf', 'zpk', 'ss', or 'frd')
+\ isa test if model is of given type
+\ tf/size model sizes
+\ lti/ndims number of dimensions
+\ lti/isempty true for empty models
+\ lti/isct true for continuous-time models
+\ lti/isdt true for discrete-time models
+\ lti/isproper true for proper models
+\ lti/issiso true for single-input/single-output models
+\ lti/isstable true for models with stable dynamics
+\ lti/reshape reshape array of linear models
+\
+**Overloaded arithmetic operations**
+--------------------------------------------------------------------------------
+\* \+ and - add and subtract systems (parallel connection)
+\* \* multiply systems (series connection)
+\ / right divide -- sys1/sys2 means sys1\*inv(sys2)
+\- \\ left divide -- sys1\\sys2 means inv(sys1)\*sys2
+\ ^ powers of a given system
+\ ' pertransposition
+\ .' transposition of input/output map
+\ .\* element-by-element multiplication
+\ [..] concatenate models along inputs or outputs
+\ lti/stack stack models/arrays along some array dimension
+\ lti/inv inverse of an LTI system
+\ lti/conj complex conjugation of model coefficients
+\
+**Matrix equation solvers and linear algebra**
+--------------------------------------------------------------------------------
+\* lyap, dlyap solve Lyapunov equations
+\ lyapchol, dlyapchol square-root Lyapunov solvers
+\* care, dare solve algebraic Riccati equations
+\ gcare, gdare generalized Riccati solvers
+\ bdschur block diagonalization of a square matrix
+\
+**Additional functions**
+--------------------------------------------------------------------------------
+\* :func:`gangof4` generate the Gang of 4 sensitivity plots
+\* :func:`linspace` generate a set of numbers that are linearly
+ spaced
+\* :func:`logspace` generate a set of numbers that are
+ logarithmically spaced
+\* :func:`unwrap` unwrap a phase angle to give a continuous curve
+== ========================== ================================================
"""
def ss(*args):
@@ -752,9 +786,9 @@
def ngrid():
"""Nichols chart grid.
- Usage
- =====
- ngrid()
+ Examples
+ --------
+ >>> ngrid()
"""
from nichols import nichols_grid
nichols_grid()
@@ -815,134 +849,81 @@
% len(args))
return margins[0], margins[1], margins[3], margins[4]
-#
-# Modifications to scipy.signal functions
-#
-# Redefine lsim to use lsim2
-def lsim(sys, U=None, T=None, X0=None, **keywords):
- """Simulate the output of a linear system
- Examples
- --------
- >>> T, yout, xout = lsim(sys, u, T, X0)
+def dcgain(*args):
+ '''
+ Compute the gain of the system in steady state.
- Parameters
- ----------
- sys: StateSpace, or TransferFunction
- LTI system to simulate
- u: input array giving input at each time T
- T: time steps at which the input is defined
- X0: initial condition (optional, default = 0)
+ The function takes either 1, 2, 3, or 4 parameters:
- Returns
- -------
- T: time values of the output
- yout: response of the system
- xout: time evolution of the state vector
- """
- # Convert the system to an signal.lti for simulation
- #! This should send a warning for MIMO systems
- ltiobjs = sys.returnScipySignalLti()
- ltiobj = ltiobjs[0][0]
-
- return sp.signal.lsim2(ltiobj, U, T, X0, **keywords)
-
-#! Redefine step to use lsim2
-#! Not yet implemented
-def step(*args, **keywords):
- """Step response of a linear system
-
- Examples
- --------
- >>> T, yout = step(sys, T, X0)
-
Parameters
----------
- sys: StateSpace, or TransferFunction
- T: array
- T is the time vector (optional; autocomputed if not given)
- X0: array
- X0 is the initial condition (optional; default = 0)
+ A, B, C, D: array-like
+ A linear system in state space form.
+ Z, P, k: array-like, array-like, number
+ A linear system in zero, pole, gain form.
+ num, den: array-like
+ A linear system in transfer function form.
+ sys: Lti (StateSpace or TransferFunction)
+ A linear system object.
Returns
-------
- T: array
- Time values of the output
- yout: array
- response of the system
- """
- sys = args[0]
- ltiobjs = sys.returnScipySignalLti()
- ltiobj = ltiobjs[0][0]
+ gain: matrix
+ The gain of each output versus each input:
+ :math:`y = gain \cdot u`
+
+ Notes
+ -----
+ This function is only useful for systems with invertible system
+ matrix ``A``.
+
+ All systems are first converted to state space form. The function then
+ computes:
+
+ .. math:: gain = - C \cdot A^{-1} \cdot B + D
+ '''
+ #Convert the parameters to state space form
+ if len(args) == 4:
+ A, B, C, D = args
+ sys = ss(A, B, C, D)
+ elif len(args) == 3:
+ Z, P, k = args
+ A, B, C, D = zpk2ss(Z, P, k)
+ sys = ss(A, B, C, D)
+ elif len(args) == 2:
+ num, den = args
+ sys = tf2ss(num, den)
+ elif len(args) == 1:
+ sys, = args
+ sys = ss(sys)
+ else:
+ raise ValueError("Function ``dcgain`` needs either 1, 2, 3 or 4 "
+ "arguments.")
+ #gain = - C * A**-1 * B + D
+ gain = sys.D - sys.C * sys.A.I * sys.B
+ return gain
- out = sp.signal.step(ltiobj, **keywords)
- yout = []
- yout.append(np.mat(out[0]))
- yout.append(out[1])
- yout = tuple(yout)
- return yout
+# Simulation routines
+# Call corresponding functions in timeresp, with arguments transposed
-# Redefine initial to use lsim2
-#! Not yet implemented (uses step for now)
-def initial(*args, **keywords):
- """Initial condition response of a linear system
+def step(sys, T=None, X0=0., input=0, output=0, **keywords):
+ T, yout = timeresp.StepResponse(sys, T, X0, input, output,
+ transpose = True, **keywords)
+ return T, yout
- Examples
- --------
- >>> T, yout = initial(sys, T, X0)
+def impulse(sys, T=None, X0=0., input=0, output=0, **keywords):
+ T, yout = timeresp.ImpulseResponse(sys, T, X0, input, output,
+ transpose = True, **keywords)
+ return T, yout
- Parameters
- ----------
- sys: StateSpace, or TransferFunction
- T: array
- T is the time vector (optional; autocomputed if not given)
- X0: array
- X0 is the initial condition (optional; default = 0)
+def initial(sys, T=None, X0=0., input=0, output=0, **keywords):
+ T, yout = timeresp.InitialResponse(sys, T, X0, input, output,
+ transpose = True, **keywords)
+ return T, yout
- Returns
- -------
- T: array
- Time values of the output
- yout: array
- response of the system
-
- """
- sys = args[0]
- ltiobjs = sys.returnScipySignalLti()
- ltiobj = ltiobjs[0][0]
-
- yout = sp.signal.initial(ltiobj, **keywords)
- return np.mat(yout)
-
-# Redefine impulse to use initial()
-#! Not yet implemented (uses impulse for now)
-def impulse(*args, **keywords):
- """Impulse response of a linear system
-
- Examples
- --------
- >>> T, yout = impulse(sys, T, X0)
-
- Parameters
- ----------
- sys: StateSpace, or TransferFunction
- T: array
- T is the time vector (optional; autocomputed if not given)
- X0: array
- X0 is the initial condition (optional; default = 0)
-
- Returns
- -------
- T: array
- Time values of the output
- yout: array
- response of the system
-
- """
- sys = args[0]
- ltiobjs = sys.returnScipySignalLti()
- ltiobj = ltiobjs[0][0]
-
- yout = sp.signal.impulse(ltiobj, **keywords)
- return np.mat(yout)
+def lsim(sys, U=0., T=None, X0=0., **keywords):
+ T, yout, xout = timeresp.ForcedResponse(sys, T, U, X0,
+ transpose = True, **keywords)
+ return T, yout, xout
Modified: trunk/src/statesp.py
===================================================================
--- trunk/src/statesp.py 2011-06-18 00:20:49 UTC (rev 160)
+++ trunk/src/statesp.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
"""stateSpace.py
State space representation and functions.
@@ -72,8 +73,9 @@
"""
-from numpy import all, angle, any, array, concatenate, cos, delete, dot, \
- empty, exp, eye, matrix, ones, pi, poly, poly1d, roots, shape, sin, zeros
+from numpy import all, angle, any, array, asarray, concatenate, cos, delete, \
+ dot, empty, exp, eye, matrix, ones, pi, poly, poly1d, roots, shape, sin, \
+ zeros
from numpy.random import rand, randn
from numpy.linalg import inv, det, solve
from numpy.linalg.linalg import LinAlgError
@@ -427,8 +429,8 @@
for i in range(self.outputs):
for j in range(self.inputs):
- out[i][j] = lti(self.A, self.B[:, j], self.C[i, :],
- self.D[i, j])
+ out[i][j] = lti(asarray(self.A), asarray(self.B[:, j]),
+ asarray(self.C[i, :]), asarray(self.D[i, j]))
return out
Added: trunk/src/timeresp.py
===================================================================
--- trunk/src/timeresp.py (rev 0)
+++ trunk/src/timeresp.py 2011-06-18 19:13:09 UTC (rev 161)
@@ -0,0 +1,652 @@
+# timesim.py - time-domain simulation routes
+"""timesim.py
+
+Time domain simulation.
+
+Copyright (c) 2010 by SciPy Developers
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the California Institute of Technology nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CALTECH
+OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+Author: Eike Welk
+Date: 12 May 2011
+$Id: matlab.py 157 2011-06-17 23:51:46Z murrayrm $
+
+.. _time-series-convention:
+
+Convention for Time Series
+--------------------------
+
+This is a convention for function arguments and return values that
+represent time series: sequences of values that change over time. It is used
+throughout the library, for example in the functions :func:`lsim`, :func:`step`,
+:func:`impulse`, and :func:`initial`.
+
+.. note::
+ This convention is different from the convention used in the library
+ :mod:`scipy.signal`. In Scipy's convention the meaning of rows and columns
+ is interchanged. All 2D values must be transposed when they are used with
+ functions from :mod:`scipy.signal`.
+
+Types:
+
+ * **Arguments** can be **arrays**, **matrices**, or **nested lists**.
+ * **Return values** are **arrays** (not matrices).
+
+The time vector is either 1D, or 2D with shape (1, n)::
+
+ T = [[t1, t2, t3, ..., tn ]]
+
+Input, state, and output all follow the same convention. Columns are different
+points in time, rows are different components. When there is only one row, a
+1D object is accepted or returned, which adds convenience for SISO systems::
+
+ U = [[u1(t1), u1(t2), u1(t3), ..., u1(tn)]
+ [u2(t1), u2(t2), u2(t3), ..., u2(tn)]
+ ...
+ ...
+ [ui(t1), ui(t2), ui(t3), ..., ui(tn)]]
+
+ Same for X, Y
+
+The initial conditions are either 1D, or 2D with shape (j, 1)::
+
+ X0 = [[x1]
+ [x2]
+ ...
+ ...
+ [xj]]
+
+So, U[:,2] is the system's input at the third point in time; and U[1] or U[1,:]
+is the sequence of values for the system's second input.
+
+As all simulation functions return *arrays*, plotting is convenient::
+
+ t, y = step(sys)
+ plot(t, y)
+
+The output of a MIMO system can be plotted like this::
+
+ t, y, x = lsim(sys, u, t)
+ plot(t, y[0], label='y_0')
+ plot(t, y[1], label='y_1')
+
+The convention also works well with the state space form of linear systems. If
+``D`` is the feedthrough *matrix* of a linear system, and ``U`` is its input
+(*matrix* or *array*), then the feedthrough part of the system's response,
+can be computed like this::
+
+ ft = D * U
+
+----------------------------------------------------------------
+
+"""
+
+# Libraries that we make use of
+import scipy as sp # SciPy library (used all over)
+import numpy as np # NumPy library
+from scipy.signal.ltisys import _default_response_times
+from copy import deepcopy
+import warnings
+from statesp import StateSpace, _rss_generate, _convertToStateSpace
+from lti import Lti # base class of StateSpace, TransferFunction
+
+#
+# Solve the systems's differential equations
+#
+
+def _check_convert_array(in_obj, legal_shapes, err_msg_start, squeeze=False,
+ transpose=False):
+ """
+ Helper function for checking array-like parameters.
+
+ * Check type and shape of ``in_obj``.
+ * Convert ``in_obj`` to an array if necessary.
+ * Change shape of ``in_obj`` according to parameter ``squeeze``.
+ * If ``in_obj`` is a scalar (number) it is converted to an array with
+ a legal shape, that is filled with the scalar value.
+
+ The function raises an exception when it detects an error.
+
+ Parameters:
+
+ in_obj: array like object
+ The array or matrix which is checked.
+
+ legal_shapes: list of tuple
+ A list of shapes that in_obj can legally have.
+ The special value "any" means that there can be any
+ number of elements in a certain dimension.
+
+ * ``(2, 3)`` describes an array with 2 rows and 3 columns
+ * ``(2, "any")`` describes an array with 2 rows and any number of
+ columns
+
+ err_msg_start: str
+ String that is prepended to the error messages, when this function
+ raises an exception. It should be used to identify the argument which
+ is currently checked.
+
+ squeeze: bool
+ If True, all dimensions with only one element are removed from the
+ array. If False the array's shape is unmodified.
+
+ For example:
+ ``array([[1,2,3]])`` is converted to ``array([1, 2, 3])``
+
+ transpose: bool
+ If True, assume that input arrays are transposed for the standard
+ format. Used to convert MATLAB-style inputs to our format.
+
+ Returns:
+
+ out_array: array
+ The checked and converted contents of ``in_obj``.
+ """
+ #convert nearly everything to an array.
+ out_array = np.asarray(in_obj)
+ if (transpose):
+ out_array = np.transpose(out_array)
+
+ #Test element data type, elements must be numbers
+ legal_kinds = set(("i", "f", "c")) #integer, float, complex
+ if out_array.dtype.kind not in legal_kinds:
+ err_msg = "Wrong element data type: '{d}'. Array elements " \
+ "must be numbers.".format(d=str(out_array.dtype))
+ raise TypeError(err_msg_start + err_msg)
+
+ #If array is zero dimensional (in_obj is scalar):
+ #create array with legal shape filled with the original value.
+ if out_array.ndim == 0:
+ for s_legal in legal_shapes:
+ #search for shape that does not contain the special symbol any.
+ if "any" in s_legal:
+ continue
+ the_val = out_array[()]
+ out_array = np.empty(s_legal, 'd')
+ out_array.fill(the_val)
+ break
+
+ #Test shape
+ def shape_matches(s_legal, s_actual):
+ """Test if two shape tuples match"""
+ #Array must have required number of dimensions
+ if len(s_legal) != len(s_actual):
+ return False
+ #All dimensions must contain required number of elements. Joker: "all"
+ for n_legal, n_actual in zip(s_legal, s_actual):
+ if n_legal == "any":
+ continue
+ if n_legal != n_actual:
+ return False
+ return True
+
+ #Iterate over legal shapes, and see if any matches out_array's shape.
+ for s_legal in legal_shapes:
+ if shape_matches(s_legal, out_array.shape):
+ break
+ else:
+ legal_shape_str = " or ".join([str(s) for s in legal_shapes])
+ err_msg = "Wrong shape (rows, columns): {a}. Expected: {e}." \
+ .format(e=legal_shape_str, a=str(out_array.shape))
+ raise ValueError(err_msg_start + err_msg)
+
+ #Convert shape
+ if squeeze:
+ out_array = np.squeeze(out_array)
+ #We don't want zero dimensional arrays
+ if out_array.shape == tuple():
+ out_array = out_array.reshape((1,))
+
+ return out_array
+
+# Forced response of a linear system
+def ForcedResponse(sys, T=None, U=0., X0=0., transpose=False, **keywords):
+ """Simulate the output of a linear system.
+
+ As a convenience for parameters `U`, `X0`:
+ Numbers (scalars) are converted to constant arrays with the correct shape.
+ The correct shape is inferred from arguments `sys` and `T`.
+
+ For information on the **shape** of parameters `U`, `T`, `X0` and
+ return values `T`, `yout`, `xout` see: :ref:`time-series-convention`
+
+ Parameters
+ ----------
+ sys: Lti (StateSpace, or TransferFunction)
+ LTI system to simulate
+
+ T: array-like
+ Time steps at which the input is defined, numbers must be (strictly
+ monotonic) increasing.
+
+ U: array-like or number, optional
+ Input array giving input at each time `T` (default = 0).
+
+ If `U` is ``None`` or ``0``, a special algorithm is used. This special
+ algorithm is faster than the general algorithm, which is used otherwise.
+
+ X0: array-like or number, optional
+ Initial condition (default = 0).
+
+ transpose: bool
+ If True, transpose all input and output arrays (for backward
+ compatibility with MATLAB and scipy.signal.lsim)
+
+ **keywords:
+ Additional keyword arguments control the solution algorithm for the
+ differential equations. These arguments are passed on to the function
+ :func:`scipy.integrate.odeint`. See the documentation for
+ :func:`scipy.integrate.odeint` for information about these
+ arguments.
+
+ Returns
+ -------
+ T: array
+ Time values of the output.
+ yout: array
+ Response of the system.
+ xout: array
+ Time evolution of the state vector.
+
+ See Also
+ --------
+ StepResponse, InitialResponse, ImpulseResponse
+
+ Examples
+ --------
+ >>> T, yout, xout = ForcedResponse(sys, T, u, X0)
+ """
+ if not isinstance(sys, Lti):
+ raise TypeError('Parameter ``sys``: must be a ``Lti`` object. '
+ '(For example ``StateSpace`` or ``TransferFunction``)')
+ sys = _convertToStateSpace(sys)
+ A, B, C, D = np.asarray(sys.A), np.asarray(sys.B), np.asarray(sys.C), \
+ np.asarray(sys.D)
+# d_type = A.dtype
+ n_states = A.shape[0]
+ n_inputs = B.shape[1]
+
+ #Test if T has shape (n,) or (1, n);
+ #T must be array-like and values must be increasing.
+ #The length of T determines the length of the input vector.
+ if T is None:
+ raise ValueError('Parameter ``T``: must be array-like, and contain '
+ '(strictly monotonic) increasing numbers.')
+ T = _check_convert_array(T, [('any',), (1,'any')],
+ 'Parameter ``T``: ', squeeze=True,
+ transpose = transpose)
+ if not all(T[1:] - T[:-1] > 0):
+ raise ValueError('Parameter ``T``: time values must be '
+ '(strictly monotonic) increasing numbers.')
+ n_steps = len(T) #number of simulation steps
+
+ #create X0 if not given, test if X0 has correct shape
+ X0 = _check_convert_array(X0, [(n_states,), (n_states,1)],
+ 'Parameter ``X0``: ', squeeze=True)
+
+ #Solve the differential equation, copied from scipy.signal.ltisys.
+ dot, squeeze, = np.dot, np.squeeze #Faster and shorter code
+ #Faster algorithm if U is zero
+ if U is None or (isinstance(U, (int, float)) and U == 0):
+ #Function that computes the time derivative of the linear system
+ def f_dot(x, _t):
+ return dot(A,x)
+
+ xout = sp.integrate.odeint(f_dot, X0, T, **keywords)
+ yout = dot(C, xout.T)
+ #General algorithm that interpolates U in between output points
+ else:
+ #Test if U has correct shape and type
+ legal_shapes = [(n_steps,), (1,n_steps)] if n_inputs == 1 else \
+ [(n_inputs, n_steps)]
+ U = _check_convert_array(U, legal_shapes,
+ 'Parameter ``U``: ', squeeze=False,
+ transpose=transpose)
+ #convert 1D array to D2 array with only one row
+ if len(U.shape) == 1:
+ U = U.reshape(1,-1) #pylint: disable=E1103
+
+ #Create a callable that uses linear interpolation to
+ #calculate the input at any time.
+ compute_u = sp.interpolate.interp1d(T, U, kind='linear', copy=False,
+ axis=-1, bounds_error=False,
+ fill_value=0)
+
+ #Function that computes the time derivative of the linear system
+ def f_dot(x, t):
+ return dot(A,x) + squeeze(dot(B,compute_u([t])))
+
+ xout = sp.integrate.odeint(f_dot, X0, T, **keywords)
+ yout = dot(C, xout.T) + dot(D, U)
+
+ yout = squeeze(yout)
+ xout = xout.T
+
+ # See if we need to transpose the data back into MATLAB form
+ if (transpose):
+ T = np.transpose(T)
+ yout = np.transpose(yout)
+ xout = np.transpose(xout)
+
+ return T, yout, xout
+
+def StepResponse(sys, T=None, X0=0., input=0, output=0, \
+ transpose = False, **keywords):
+ #pylint: disable=W0622
+ """Step response of a linear system
+
+ If the system has multiple inputs or outputs (MIMO), one input and one
+ output have to be selected for the simulation. The parameters `input`
+ and `output` do this. All other inputs are set to 0, all other outputs
+ are ignored.
+
+ For information on the **shape** of parameters `T`, `X0` and
+ return values `T`, `yout` see: :ref:`time-series-convention`
+
+ Parameters
+ ----------
+ sys: StateSpace, or TransferFunction
+ LTI system to simulate
+
+ T: array-like object, optional
+ Time vector (argument is autocomputed if not given)
+
+ X0: array-like or number, optional
+ Initial condition (default = 0)
+
+ Numbers are converted to constant arrays with the correct shape.
+
+ input: int
+ Index of the input that will be used in this simulation.
+
+ output: int
+ Index of the output that will be used in this simulation.
+
+ transpose: bool
+ If True, transpose all input and output arrays (for backward
+ compatibility with MATLAB and scipy.signal.lsim)
+
+ **keywords:
+ Additional keyword arguments control the solution algorithm for the
+ differential equations. These arguments are passed on to the function
+ :func:`lsim`, which in turn passes them on to
+ :func:`scipy.integrate.odeint`. See the documentation for
+ :func:`scipy.integrate.odeint` for information about these
+ arguments.
+
+ Returns
+ -------
+ T: array
+ Time values of the output
+
+ yout: array
+ Response of the system
+
+ See Also
+ --------
+ lsim, initial, impulse
+
+ Examples
+ --------
+ >>> T, yout = step(sys, T, X0)
+ """
+ sys = _convertToStateSpace(sys)
+ sys = _mimo2siso(sys, input, output, warn_conversion=True)
+ if T is None:
+ T = _default_response_times(sys.A, 100)
+ U = np.ones_like(T)
+
+ T, yout, _xout = ForcedResponse(sys, T, U, X0,
+ transpose = transpose, **keywords)
+
+ return T, yout
+
+
+def InitialResponse(sys, T=None, X0=0., input=0, output=0, transpose=False,
+ **keywords):
+ #pylint: disable=W0622
+ """Initial condition response of a linear system
+
+ If the system has multiple inputs or outputs (MIMO), one input and one
+ output have to be selected for the simulation. The parameters `input`
+ and `output` do this. All other inputs are set to 0, all other outputs
+ are ignored.
+
+ For information on the **shape** of parameters `T`, `X0` and
+ return values `T`, `yout` see: :ref:`time-series-convention`
+
+ Parameters
+ ----------
+ sys: StateSpace, or TransferFunction
+ LTI system to simulate
+
+ T: array-like object, optional
+ Time vector (argument is autocomputed if not given)
+
+ X0: array-like object or number, optional
+ Initial condition (default = 0)
+
+ Numbers are converted to constant arrays with the correct shape.
+
+ input: int
+ Index of the input that will be used in this simulation.
+
+ output: int
+ Index of the output that will be used in this simulation.
+
+ transpose: bool
+ If True, transpose all input and output arrays (for backward
+ compatibility with MATLAB and scipy.signal.lsim)
+
+ **keywords:
+ Additional keyword arguments control the solution algorithm for the
+ differential equations. These arguments are passed on to the function
+ :func:`lsim`, which in turn passes them on to
+ :func:`scipy.integrate.odeint`. See the documentation for
+ :func:`scipy.integrate.odeint` for information about these
+ arguments.
+
+
+ Returns
+ -------
+ T: array
+ Time values of the output
+ yout: array
+ Response of the system
+
+ See Also
+ --------
+ lsim, step, impulse
+
+ Examples
+ --------
+ >>> T, yout = InitialResponsesys, T, X0)
+ """
+ sys = _convertToStateSpace(sys)
+ sys = _mimo2siso(sys, input, output, warn_conversion=True)
+ #Create time and input vectors; checking is done in ForcedResponse(...)
+ #The initial vector X0 is created in ForcedResponse(...) if necessary
+ if T is None:
+ T = _default_response_times(sys.A, 100)
+ U = np.zeros_like(T)
+
+ T, yout, _xout = ForcedResponse(sys, T, U, X0, **keywords)
+ return T, yout
+
+
+def ImpulseResponse(sys, T=None, X0=0., input=0, output=0,
+ transpose=False, **keywords):
+ #pylint: disable=W0622
+ """Impulse response of a linear system
+
+ If the system has multiple inputs or outputs (MIMO), one input and one
+ output have to be selected for the simulation. The parameters `input`
+ and `output` do this. All other inputs are set to 0, all other outputs
+ are ignored.
+
+ For information on the **shape** of parameters `T`, `X0` and
+ return values `T`, `yout` see: :ref:`time-series-convention`
+
+ Parameters
+ ----------
+ sys: StateSpace, TransferFunction
+ LTI system to simulate
+
+ T: array-like object, optional
+ Time vector (argument is autocomputed if not given)
+
+ X0: array-like object or number, optional
+ Initial condition (default = 0)
+
+ Numbers are converted to constant arrays with the correct shape.
+
+ input: int
+ Index of the input that will be used in this simulation.
+
+ output: int
+ Index of the output that will be used in this simulation.
+
+ transpose: bool
+ If True, transpose all input and output arrays (for backward
+ compatibility with MATLAB and scipy.signal.lsim)
+
+ **keywords:
+ Additional keyword arguments control the solution algorithm for the
+ differential equations. These arguments are passed on to the function
+ :func:`lsim`, which in turn passes them on to
+ :func:`scipy.integrate.odeint`. See the documentation for
+ :func:`scipy.integrate.odeint` for information about these
+ arguments.
+
+
+ Returns
+ -------
+ T: array
+ Time values of the output
+ yout: array
+ Response of the system
+
+ See Also
+ --------
+ lsim, step, initial
+
+ Examples
+ --------
+ >>> T, yout = ImpulseResponse(sys, T, X0)
+ """
+ sys = _convertToStateSpace(sys)
+ sys = _mimo2siso(sys, input, output, warn_conversion=True)
+
+ #System has direct feedthrough, can't simulate impulse response numerically.
+ if np.any(sys.D != 0):
+ warnings.warn('System has direct feedthrough: ``D != 0``. The infinite '
+ 'impulse at ``t=0`` does not appear in the output. \n'
+ 'Results may be meaningless!')
+
+ #create X0 if not given, test if X0 has correct shape.
+ #Must be done here because it is used for computations here.
+ n_states = sys.A.shape[0]
+ X0 = _check_convert_array(X0, [(n_states,), (n_states,1)],
+ 'Parameter ``X0``: \n', squeeze=True)
+
+ #Compute new X0 that contains the impulse
+ #We can't put the impulse into U because there is no numerical
+ #representation for it (infinitesimally short, infinitely high).
+ #See also: http://www.mathworks.com/support/tech-notes/1900/1901.html
+ B = np.asarray(sys.B).squeeze()
+ new_X0 = B + X0
+
+ #Compute T and U, no checks necessary, they will be checked in lsim
+ if T is None:
+ T = _default_response_times(sys.A, 100)
+ U = np.zeros_like(T)
+
+ T, yout, _xout = ForcedResponse(sys, T, U, new_X0, \
+ transpose=transpose, **keywords)
+ return T, yout
+
+#! TODO: this function probably belongs in a different file
+def _mimo2siso(sys, input, output, warn_conversion):
+ #pylint: disable=W0622
+ """
+ Convert a MIMO system to a SISO system. (Convert a system with multiple
+ inputs and/or outputs, to a system with a single input and output.)
+
+ The input and output that are used in the SISO system can be selected
+ with the parameters ``input`` and ``output``. All other inputs are set
+ to 0, all other outputs are ignored.
+
+ If ``sys`` is already a SISO system, it will be returned unaltered.
+
+ Parameters:
+
+ sys...
[truncated message content] |