Skip to content

Commit 724d1df

Browse files
committed
all time response functions return InputOutput response object
1 parent bb12598 commit 724d1df

2 files changed

Lines changed: 92 additions & 16 deletions

File tree

control/iosys.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,8 +1571,8 @@ def input_output_response(
15711571
for i in range(len(T)):
15721572
u = U[i] if len(U.shape) == 1 else U[:, i]
15731573
y[:, i] = sys._out(T[i], [], u)
1574-
return _process_time_response(
1575-
sys, T, y, np.array((0, 0, np.asarray(T).size)),
1574+
return InputOutputResponse(
1575+
T, y, np.array((0, 0, np.asarray(T).size)), None, sys=sys,
15761576
transpose=transpose, return_x=return_x, squeeze=squeeze)
15771577

15781578
# create X0 if not given, test if X0 has correct shape

control/timeresp.py

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,50 @@ class InputOutputResponse:
9191
type for time domain simulations (step response, input/output response,
9292
etc).
9393
94+
Input/output responses can be stored for multiple input signals, with
95+
the output and state indexed by the input number. This allows for
96+
input/output response matrices, which is mainly useful for impulse and
97+
step responses for linear systems. For mulit-input responses, the same
98+
time vector must be used for all inputs.
99+
94100
Attributes
95101
----------
96102
t : array
97-
Time values of the output.
103+
Time values of the input/output response(s).
98104
99105
y : array
100-
Response of the system, indexed by the output number and time.
106+
Output response of the system, indexed by either the output and time
107+
(if only a single input is given) or the output, input, and time
108+
(for muitiple inputs).
101109
102110
x : array
103-
Time evolution of the state vector, indexed by state number and time.
111+
Time evolution of the state vector, indexed indexed by either the
112+
state and time (if only a single input is given) or the state,
113+
input, and time (for muitiple inputs).
104114
105-
u : array
106-
Input to the system, indexed by the input number and time.
115+
u : 1D or 2D array
116+
Input(s) to the system, indexed by input (optional) and time. If a
117+
1D vector is passed, the output and state responses should be 2D
118+
arrays. If a 2D array is passed, then the state and output vectors
119+
should be 3D (indexed by input).
107120
108121
Methods
109122
-------
110123
plot(**kwargs)
111124
Plot the input/output response. Keywords are passed to matplotlib.
112125
126+
Examples
127+
--------
128+
>>> sys = ct.rss(4, 2, 2)
129+
>>> response = ct.step_response(sys)
130+
>>> response.plot() # 2x2 matrix of step responses
131+
>>> response.plot(output=1, input=0) # First input to second output
132+
133+
>>> T = np.linspace(0, 10, 100)
134+
>>> U = np.sin(np.linspace(T))
135+
>>> response = ct.forced_response(sys, T, U)
136+
>>> t, y = response.t, response.y
137+
113138
Notes
114139
-----
115140
1. For backward compatibility with earlier versions of python-control,
@@ -137,14 +162,64 @@ class InputOutputResponse:
137162

138163
def __init__(
139164
self, t, y, x, u, sys=None, dt=None,
140-
transpose=False, return_x=False, squeeze=None
165+
transpose=False, return_x=False, squeeze=None,
166+
input=None, output=None
141167
):
168+
"""Create an input/output time response object.
169+
170+
Parameters
171+
----------
172+
sys : LTI or InputOutputSystem
173+
System that generated the data (used to check if SISO/MIMO).
174+
175+
T : 1D array
176+
Time values of the output. Ignored if None.
177+
178+
yout : ndarray
179+
Response of the system. This can either be a 1D array indexed
180+
by time (for SISO systems), a 2D array indexed by output and
181+
time (for MIMO systems with no input indexing, such as
182+
initial_response or forced response) or a 3D array indexed by
183+
output, input, and time.
184+
185+
xout : array, optional
186+
Individual response of each x variable (if return_x is
187+
True). For a SISO system (or if a single input is specified),
188+
this should be a 2D array indexed by the state index and time
189+
(for single input systems) or a 3D array indexed by state,
190+
input, and time. Ignored if None.
191+
192+
transpose : bool, optional
193+
If True, transpose all input and output arrays (for backward
194+
compatibility with MATLAB and :func:`scipy.signal.lsim`).
195+
Default value is False.
196+
197+
return_x : bool, optional
198+
If True, return the state vector (default = False).
199+
200+
squeeze : bool, optional
201+
By default, if a system is single-input, single-output (SISO) then
202+
the output response is returned as a 1D array (indexed by time).
203+
If squeeze=True, remove single-dimensional entries from the shape
204+
of the output even if the system is not SISO. If squeeze=False,
205+
keep the output as a 3D array (indexed by the output, input, and
206+
time) even if the system is SISO. The default value can be set
207+
using config.defaults['control.squeeze_time_response'].
208+
209+
input : int, optional
210+
If present, the response represents only the listed input.
211+
212+
output : int, optional
213+
If present, the response represents only the listed output.
214+
215+
"""
142216
#
143217
# Process and store the basic input/output elements
144218
#
145219
t, y, x = _process_time_response(
146220
sys, t, y, x,
147-
transpose=transpose, return_x=True, squeeze=squeeze)
221+
transpose=transpose, return_x=True, squeeze=squeeze,
222+
input=input, output=output)
148223

149224
# Time vector
150225
self.t = np.atleast_1d(t)
@@ -180,9 +255,10 @@ def __init__(
180255
# Keep track of whether to squeeze inputs, outputs, and states
181256
self.squeeze = squeeze
182257

183-
# Store legacy keyword values (only used for legacy interface)
258+
# Store legacy keyword values (only needed for legacy interface)
184259
self.transpose = transpose
185260
self.return_x = return_x
261+
self.input, self.output = input, output
186262

187263
# Getter for output (implements squeeze processing)
188264
@property
@@ -898,9 +974,9 @@ def step_response(sys, T=None, X0=0., input=None, output=None, T_num=None,
898974
if return_x:
899975
xout[:, i, :] = out[2]
900976

901-
return _process_time_response(
902-
sys, out[0], yout, xout, transpose=transpose, return_x=return_x,
903-
squeeze=squeeze, input=input, output=output)
977+
return InputOutputResponse(
978+
out[0], yout, xout, None, sys=sys, transpose=transpose,
979+
return_x=return_x, squeeze=squeeze, input=input, output=output)
904980

905981

906982
def step_info(sysdata, T=None, T_num=None, yfinal=None,
@@ -1370,9 +1446,9 @@ def impulse_response(sys, T=None, X0=0., input=None, output=None, T_num=None,
13701446
if return_x:
13711447
xout[:, i, :] = out[2]
13721448

1373-
return _process_time_response(
1374-
sys, out[0], yout, xout, transpose=transpose, return_x=return_x,
1375-
squeeze=squeeze, input=input, output=output)
1449+
return InputOutputResponse(
1450+
out[0], yout, xout, None, sys=sys, transpose=transpose,
1451+
return_x=return_x, squeeze=squeeze, input=input, output=output)
13761452

13771453

13781454
# utility function to find time period and time increment using pole locations

0 commit comments

Comments
 (0)