Skip to content

Commit 3128e0b

Browse files
committed
move plotting -> response and conventions -> {linear, timeplot, config}
1 parent d874bca commit 3128e0b

4 files changed

Lines changed: 746 additions & 0 deletions

File tree

File renamed without changes.

doc/linear.rst

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
.. _conventions-ref:
2+
3+
.. currentmodule:: control
4+
5+
*******************
6+
Library conventions
7+
*******************
8+
9+
The python-control library uses a set of standard conventions for the
10+
way that different types of standard information used by the library.
11+
Throughout this manual, we assume the `control` package has been
12+
imported as `ct`.
13+
14+
LTI system representation
15+
=========================
16+
17+
Linear time invariant (LTI) systems are represented in python-control in
18+
state space, transfer function, or frequency response data (FRD) form. Most
19+
functions in the toolbox will operate on any of these data types, and
20+
functions for converting between compatible types are provided.
21+
22+
State space systems
23+
-------------------
24+
The :class:`StateSpace` class is used to represent state-space realizations
25+
of linear time-invariant (LTI) systems:
26+
27+
.. math::
28+
29+
\frac{dx}{dt} &= A x + B u \\
30+
y &= C x + D u
31+
32+
where u is the input, y is the output, and x is the state.
33+
34+
To create a state space system, use the :func:`ss` function::
35+
36+
sys = ct.ss(A, B, C, D)
37+
38+
State space systems can be manipulated using standard arithmetic operations
39+
as well as the :func:`feedback`, :func:`parallel`, and :func:`series`
40+
function. A full list of functions can be found in :ref:`function-ref`.
41+
42+
Transfer functions
43+
------------------
44+
The :class:`TransferFunction` class is used to represent input/output
45+
transfer functions
46+
47+
.. math::
48+
49+
G(s) = \frac{\text{num}(s)}{\text{den}(s)}
50+
= \frac{a_0 s^m + a_1 s^{m-1} + \cdots + a_m}
51+
{b_0 s^n + b_1 s^{n-1} + \cdots + b_n},
52+
53+
where n is generally greater than or equal to m (for a proper transfer
54+
function).
55+
56+
To create a transfer function, use the :func:`tf` function::
57+
58+
sys = ct.tf(num, den)
59+
60+
Transfer functions can be manipulated using standard arithmetic operations
61+
as well as the :func:`feedback`, :func:`parallel`, and :func:`series`
62+
function. A full list of functions can be found in :ref:`function-ref`.
63+
64+
Frequency response data (FRD) systems
65+
-------------------------------------
66+
The :class:`FrequencyResponseData` (FRD) class is used to represent systems in
67+
frequency response data form.
68+
69+
The main data members are `omega` and `fresp`, where `omega` is a 1D array
70+
with the frequency points of the response, and `fresp` is a 3D array, with
71+
the first dimension corresponding to the output index of the system, the
72+
second dimension corresponding to the input index, and the 3rd dimension
73+
corresponding to the frequency points in omega.
74+
75+
FRD systems can be created with the :func:`~control.frd` factory function.
76+
Frequency response data systems have a somewhat more limited set of
77+
functions that are available, although all of the standard algebraic
78+
manipulations can be performed.
79+
80+
The FRD class is also used as the return type for the
81+
:func:`frequency_response` function (and the equivalent method for the
82+
:class:`StateSpace` and :class:`TransferFunction` classes). This
83+
object can be assigned to a tuple using::
84+
85+
mag, phase, omega = response
86+
87+
where `mag` is the magnitude (absolute value, not dB or log10) of the
88+
system frequency response, `phase` is the wrapped phase in radians of
89+
the system frequency response, and `omega` is the (sorted) frequencies
90+
at which the response was evaluated. If the system is SISO and the
91+
`squeeze` argument to :func:`frequency_response` is not True,
92+
`magnitude` and `phase` are 1D, indexed by frequency. If the system
93+
is not SISO or `squeeze` is False, the array is 3D, indexed by the
94+
output, input, and frequency. If `squeeze` is True then
95+
single-dimensional axes are removed. The processing of the `squeeze`
96+
keyword can be changed by calling the response function with a new
97+
argument::
98+
99+
mag, phase, omega = response(squeeze=False)
100+
101+
Frequency response objects are also available as named properties of the
102+
``response`` object: ``response.magnitude``, ``response.phase``, and
103+
``response.response`` (for the complex response). For MIMO systems, these
104+
elements of the frequency response can be accessed using the names of the
105+
inputs and outputs::
106+
107+
response.magnitude['y[0]', 'u[1]']
108+
109+
where the signal names are based on the system that generated the frequency
110+
response.
111+
112+
Note: The ``fresp`` data member is stored as a NumPy array and cannot be
113+
accessed with signal names. Use ``response.response`` to access the
114+
complex frequency response using signal names.
115+
116+
Discrete time systems
117+
---------------------
118+
A discrete time system is created by specifying a nonzero 'timebase', dt.
119+
The timebase argument can be given when a system is constructed:
120+
121+
* `dt = 0`: continuous time system (default)
122+
* `dt > 0`: discrete time system with sampling period 'dt'
123+
* `dt = True`: discrete time with unspecified sampling period
124+
* `dt = None`: no timebase specified
125+
126+
Only the :class:`StateSpace`, :class:`TransferFunction`, and
127+
:class:`InputOutputSystem` classes allow explicit representation of
128+
discrete time systems.
129+
130+
Systems must have compatible timebases in order to be combined. A discrete
131+
time system with unspecified sampling time (`dt = True`) can be combined with
132+
a system having a specified sampling time; the result will be a discrete time
133+
system with the sample time of the latter system. Similarly, a system with
134+
timebase `None` can be combined with a system having a specified timebase; the
135+
result will have the timebase of the latter system. For continuous time
136+
systems, the :func:`sample_system` function or the :meth:`StateSpace.sample`
137+
and :meth:`TransferFunction.sample` methods can be used to create a discrete
138+
time system from a continuous time system. See
139+
:ref:`utility-and-conversions`. The default value of `dt` can be changed by
140+
changing the value of `control.config.defaults['control.default_dt']`.
141+
142+
Conversion between representations
143+
----------------------------------
144+
LTI systems can be converted between representations either by calling the
145+
constructor for the desired data type using the original system as the sole
146+
argument or using the explicit conversion functions :func:`ss2tf` and
147+
:func:`tf2ss`.
148+
149+
Subsystems
150+
----------
151+
Subsets of input/output pairs for LTI systems can be obtained by indexing
152+
the system using either numerical indices (including slices) or signal
153+
names::
154+
155+
subsys = sys[[0, 2], 0:2]
156+
subsys = sys[['y[0]', 'y[2]'], ['u[0]', 'u[1]']]
157+
158+
Signal names for an indexed subsystem are preserved from the original
159+
system and the subsystem name is set according to the values of
160+
``control.config.defaults['iosys.indexed_system_name_prefix']`` and
161+
``control.config.defaults['iosys.indexed_system_name_suffix']``. The default
162+
subsystem name is the original system name with '$indexed' appended.
163+
164+
Simulating LTI systems
165+
======================
166+
167+
A number of functions are available for computing the output (and
168+
state) response of an LTI systems:
169+
170+
.. autosummary::
171+
:toctree: generated/
172+
173+
initial_response
174+
step_response
175+
impulse_response
176+
forced_response
177+
178+
Each of these functions returns a :class:`TimeResponseData` object
179+
that contains the data for the time response (described in more detail
180+
in the next section).
181+
182+
The :func:`forced_response` system is the most general and allows by
183+
the zero initial state response to be simulated as well as the
184+
response from a non-zero initial condition.
185+
186+
For linear time invariant (LTI) systems, the :func:`impulse_response`,
187+
:func:`initial_response`, and :func:`step_response` functions will
188+
automatically compute the time vector based on the poles and zeros of
189+
the system. If a list of systems is passed, a common time vector will be
190+
computed and a list of responses will be returned in the form of a
191+
:class:`TimeResponseList` object. The :func:`forced_response` function can
192+
also take a list of systems, to which a single common input is applied.
193+
The :class:`TimeResponseList` object has a `plot()` method that will plot
194+
each of the responses in turn, using a sequence of different colors with
195+
appropriate titles and legends.
196+
197+
In addition the :func:`input_output_response` function, which handles
198+
simulation of nonlinear systems and interconnected systems, can be
199+
used. For an LTI system, results are generally more accurate using
200+
the LTI simulation functions above. The :func:`input_output_response`
201+
function is described in more detail in the :ref:`iosys-module` section.
202+
203+
.. currentmodule:: control
204+
.. _time-series-convention:
205+
206+
Time series data
207+
----------------
208+
A variety of functions in the library return time series data: sequences of
209+
values that change over time. A common set of conventions is used for
210+
returning such data: columns represent different points in time, rows are
211+
different components (e.g., inputs, outputs or states). For return
212+
arguments, an array of times is given as the first returned argument,
213+
followed by one or more arrays of variable values. This convention is used
214+
throughout the library, for example in the functions
215+
:func:`forced_response`, :func:`step_response`, :func:`impulse_response`,
216+
and :func:`initial_response`.
217+
218+
.. note::
219+
The convention used by python-control is different from the convention
220+
used in the `scipy.signal
221+
<https://docs.scipy.org/doc/scipy/reference/signal.html>`_ library. In
222+
Scipy's convention the meaning of rows and columns is interchanged.
223+
Thus, all 2D values must be transposed when they are used with functions
224+
from `scipy.signal`_.
225+
226+
The time vector is a 1D array with shape (n, )::
227+
228+
T = [t1, t2, t3, ..., tn ]
229+
230+
Input, state, and output all follow the same convention. Columns are different
231+
points in time, rows are different components::
232+
233+
U = [[u1(t1), u1(t2), u1(t3), ..., u1(tn)]
234+
[u2(t1), u2(t2), u2(t3), ..., u2(tn)]
235+
...
236+
...
237+
[ui(t1), ui(t2), ui(t3), ..., ui(tn)]]
238+
239+
(and similarly for `X`, `Y`). So, `U[:, 2]` is the system's input at the
240+
third point in time; and `U[1]` or `U[1, :]` is the sequence of values for
241+
the system's second input.
242+
243+
When there is only one row, a 1D object is accepted or returned, which adds
244+
convenience for SISO systems:
245+
246+
The initial conditions are either 1D, or 2D with shape (j, 1)::
247+
248+
X0 = [[x1]
249+
[x2]
250+
...
251+
...
252+
[xj]]
253+
254+
Functions that return time responses (e.g., :func:`forced_response`,
255+
:func:`impulse_response`, :func:`input_output_response`,
256+
:func:`initial_response`, and :func:`step_response`) return a
257+
:class:`TimeResponseData` object that contains the data for the time
258+
response. These data can be accessed via the
259+
:attr:`~TimeResponseData.time`, :attr:`~TimeResponseData.outputs`,
260+
:attr:`~TimeResponseData.states` and :attr:`~TimeResponseData.inputs`
261+
properties::
262+
263+
sys = ct.rss(4, 1, 1)
264+
response = ct.step_response(sys)
265+
plt.plot(response.time, response.outputs)
266+
267+
The dimensions of the response properties depend on the function being
268+
called and whether the system is SISO or MIMO. In addition, some time
269+
response function can return multiple "traces" (input/output pairs),
270+
such as the :func:`step_response` function applied to a MIMO system,
271+
which will compute the step response for each input/output pair. See
272+
:class:`TimeResponseData` for more details.
273+
274+
The input, output, and state elements of the response can be accessed using
275+
signal names in place of integer offsets::
276+
277+
plt.plot(response. time, response.states['x[1]']
278+
279+
For multi-trace systems generated by :func:`step_response` and
280+
:func:`impulse_response`, the input name used to generate the trace can be
281+
used to access the appropriate input output pair::
282+
283+
plt.plot(response.time, response.outputs['y[0]', 'u[1]'])
284+
285+
The time response functions can also be assigned to a tuple, which extracts
286+
the time and output (and optionally the state, if the `return_x` keyword is
287+
used). This allows simple commands for plotting::
288+
289+
t, y = ct.step_response(sys)
290+
plot(t, y)
291+
292+
The output of a MIMO LTI system can be plotted like this::
293+
294+
t, y = ct.forced_response(sys, t, u)
295+
plot(t, y[0], label='y_0')
296+
plot(t, y[1], label='y_1')
297+
298+
The convention also works well with the state space form of linear
299+
systems. If `D` is the feedthrough matrix (2D array) of a linear system,
300+
and `U` is its input (array), then the feedthrough part of the system's
301+
response, can be computed like this::
302+
303+
ft = D @ U
304+
305+
Finally, the `to_pandas()` function can be used to create a pandas dataframe::
306+
307+
df = response.to_pandas()
308+
309+
The column labels for the data frame are `time` and the labels for the input,
310+
output, and state signals (`u[i]`, `y[i]`, and `x[i]` by default, but these
311+
can be changed using the `inputs`, `outputs`, and `states` keywords when
312+
constructing the system, as described in :func:`ss`, :func:`tf`, and other
313+
system creation function. Note that when exporting to pandas, "rows" in the
314+
data frame correspond to time and "cols" (DataSeries) correspond to signals.
315+
316+
.. currentmodule:: control
317+
.. _package-configuration-parameters:
318+
319+
Package configuration parameters
320+
================================
321+
322+
The python-control library can be customized to allow for different default
323+
values for selected parameters. This includes the ability to set the style
324+
for various types of plots and establishing the underlying representation for
325+
state space matrices.
326+
327+
To set the default value of a configuration variable, set the appropriate
328+
element of the `control.config.defaults` dictionary::
329+
330+
ct.config.defaults['module.parameter'] = value
331+
332+
The :func:`~control.set_defaults` function can also be used to
333+
set multiple configuration parameters at the same time::
334+
335+
ct.set_defaults('module', param1=val1, param2=val2, ...]
336+
337+
Finally, there are also functions available set collections of variables based
338+
on standard configurations.
339+
340+
Selected variables that can be configured, along with their default values:
341+
342+
* freqplot.dB (False): Bode plot magnitude plotted in dB (otherwise powers
343+
of 10)
344+
345+
* freqplot.deg (True): Bode plot phase plotted in degrees (otherwise radians)
346+
347+
* freqplot.Hz (False): Bode plot frequency plotted in Hertz (otherwise
348+
rad/sec)
349+
350+
* freqplot.grid (True): Include grids for magnitude and phase plots
351+
352+
* freqplot.number_of_samples (1000): Number of frequency points in Bode plots
353+
354+
* freqplot.feature_periphery_decade (1.0): How many decades to include in
355+
the frequency range on both sides of features (poles, zeros).
356+
357+
* statesp.default_dt and xferfcn.default_dt (None): set the default value
358+
of dt when constructing new LTI systems
359+
360+
* statesp.remove_useless_states (True): remove states that have no effect
361+
on the input-output dynamics of the system
362+
363+
Additional parameter variables are documented in individual functions
364+
365+
Functions that can be used to set standard configurations:
366+
367+
.. autosummary::
368+
:toctree: generated/
369+
370+
reset_defaults
371+
use_fbs_defaults
372+
use_matlab_defaults
373+
use_legacy_defaults
File renamed without changes.

0 commit comments

Comments
 (0)