Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixes to docstrings and conventions.rst to match convention of dt=0 a…
…s default system timebase
  • Loading branch information
sawyerbfuller committed Jul 20, 2020
commit f5c3face51e5a1a1151529b5a2ea1d83805d3fc0
64 changes: 33 additions & 31 deletions control/dtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,19 @@

# Sample a continuous time system
def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):
"""Convert a continuous time system to discrete time

Creates a discrete time system from a continuous time system by
sampling. Multiple methods of conversion are supported.
"""
Convert a continuous time system to discrete time by sampling

Parameters
----------
sysc : linsys
sysc : LTI (StateSpace or TransferFunction)
Continuous time system to be converted
Ts : real
Ts : real > 0
Sampling period
method : string
Method to use for conversion: 'matched', 'tustin', 'zoh' (default)
Method to use for conversion, e.g. 'bilinear', 'zoh' (default)

prewarp_frequency : float within [0, infinity)
prewarp_frequency : real within [0, infinity)
The frequency [rad/s] at which to match with the input continuous-
time system's magnitude and phase

Expand All @@ -78,13 +76,13 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):

Notes
-----
See `TransferFunction.sample` and `StateSpace.sample` for
See :meth:`StateSpace.sample` or :meth:`TransferFunction.sample`` for
further details.

Examples
--------
>>> sysc = TransferFunction([1], [1, 2, 1])
>>> sysd = sample_system(sysc, 1, method='matched')
>>> sysd = sample_system(sysc, 1, method='bilinear')
"""

# Make sure we have a continuous time system
Expand All @@ -95,35 +93,39 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):


def c2d(sysc, Ts, method='zoh', prewarp_frequency=None):
'''
Return a discrete-time system
"""
Convert a continuous time system to discrete time by sampling

Parameters
----------
sysc: LTI (StateSpace or TransferFunction), continuous
System to be converted
sysc : LTI (StateSpace or TransferFunction)
Continuous time system to be converted
Ts : real > 0
Sampling period
method : string
Method to use for conversion, e.g. 'bilinear', 'zoh' (default)

Ts: number
Sample time for the conversion
prewarp_frequency : real within [0, infinity)
The frequency [rad/s] at which to match with the input continuous-
time system's magnitude and phase

method: string, optional
Method to be applied,
'zoh' Zero-order hold on the inputs (default)
'foh' First-order hold, currently not implemented
'impulse' Impulse-invariant discretization, currently not implemented
'tustin' Bilinear (Tustin) approximation, only SISO
'matched' Matched pole-zero method, only SISO
Returns
-------
sysd : linsys
Discrete time system, with sampling rate Ts

Notes
-----
See :meth:`StateSpace.sample` or :meth:`TransferFunction.sample`` for
further details.

prewarp_frequency : float within [0, infinity)
The frequency [rad/s] at which to match with the input continuous-
time system's magnitude and phase
Examples
--------
>>> sysc = TransferFunction([1], [1, 2, 1])
>>> sysd = sample_system(sysc, 1, method='bilinear')
"""

'''
# Call the sample_system() function to do the work
sysd = sample_system(sysc, Ts, method, prewarp_frequency)

# TODO: is this check needed? If sysc is StateSpace, sysd is too?
if isinstance(sysc, StateSpace) and not isinstance(sysd, StateSpace):
return _convertToStateSpace(sysd) # pragma: no cover

return sysd
46 changes: 26 additions & 20 deletions control/iosys.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ class for a set of subclasses that are used to implement specific
states : int, list of str, or None
Description of the system states. Same format as `inputs`.
dt : None, True or float, optional
System timebase. None (default) indicates continuous time, True
indicates discrete time with undefined sampling time, positive number
is discrete time with specified sampling time.
System timebase. 0 (default) indicates continuous
time, True indicates discrete time with unspecified sampling
time, positive number is discrete time with specified
sampling time, None indicates unspecified timebase (either
continuous or discrete time).
params : dict, optional
Parameter values for the systems. Passed to the evaluation functions
for the system as default values, overriding internal defaults.
Expand All @@ -89,9 +91,11 @@ class for a set of subclasses that are used to implement specific
Dictionary of signal names for the inputs, outputs and states and the
index of the corresponding array
dt : None, True or float
System timebase. None (default) indicates continuous time, True
indicates discrete time with undefined sampling time, positive number
is discrete time with specified sampling time.
System timebase. 0 (default) indicates continuous
time, True indicates discrete time with unspecified sampling
time, positive number is discrete time with specified
sampling time, None indicates unspecified timebase (either
continuous or discrete time).
params : dict, optional
Parameter values for the systems. Passed to the evaluation functions
for the system as default values, overriding internal defaults.
Expand Down Expand Up @@ -137,10 +141,11 @@ def __init__(self, inputs=None, outputs=None, states=None, params={},
states : int, list of str, or None
Description of the system states. Same format as `inputs`.
dt : None, True or float, optional
System timebase. None (default) indicates continuous
time, True indicates discrete time with undefined sampling
System timebase. 0 (default) indicates continuous
time, True indicates discrete time with unspecified sampling
time, positive number is discrete time with specified
sampling time.
sampling time, None indicates unspecified timebase (either
continuous or discrete time).
params : dict, optional
Parameter values for the systems. Passed to the evaluation
functions for the system as default values, overriding internal
Expand Down Expand Up @@ -600,10 +605,11 @@ def __init__(self, linsys, inputs=None, outputs=None, states=None,
states : int, list of str, or None, optional
Description of the system states. Same format as `inputs`.
dt : None, True or float, optional
System timebase. None (default) indicates continuous
time, True indicates discrete time with undefined sampling
System timebase. 0 (default) indicates continuous
time, True indicates discrete time with unspecified sampling
time, positive number is discrete time with specified
sampling time.
sampling time, None indicates unspecified timebase (either
continuous or discrete time).
params : dict, optional
Parameter values for the systems. Passed to the evaluation
functions for the system as default values, overriding internal
Expand Down Expand Up @@ -722,10 +728,10 @@ def __init__(self, updfcn, outfcn=None, inputs=None, outputs=None,
operating in continuous or discrete time. It can have the
following values:

* dt = None No timebase specified
* dt = 0 Continuous time system
* dt > 0 Discrete time system with sampling time dt
* dt = True Discrete time with unspecified sampling time
* dt = 0: continuous time system (default)
* dt > 0: discrete time system with sampling period 'dt'
* dt = True: discrete time with unspecified sampling period
* dt = None: no timebase specified

name : string, optional
System name (used for specifying signals).
Expand Down Expand Up @@ -866,10 +872,10 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
operating in continuous or discrete time. It can have the
following values:

* dt = None No timebase specified
* dt = 0 Continuous time system
* dt > 0 Discrete time system with sampling time dt
* dt = True Discrete time with unspecified sampling time
* dt = 0: continuous time system (default)
* dt > 0: discrete time system with sampling period 'dt'
* dt = True: discrete time with unspecified sampling period
* dt = None: no timebase specified

name : string, optional
System name (used for specifying signals).
Expand Down
28 changes: 17 additions & 11 deletions control/statesp.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,22 @@ class StateSpace(LTI):
`numpy.ndarray` objects. The :func:`~control.use_numpy_matrix` function
can be used to set the storage type.

Discrete-time state space system are implemented by using the 'dt'
instance variable and setting it to the sampling period. If 'dt' is not
None, then it must match whenever two state space systems are combined.
Setting dt = 0 specifies a continuous system, while leaving dt = None
means the system timebase is not specified. If 'dt' is set to True, the
system will be treated as a discrete time system with unspecified sampling
time. The default value of 'dt' is None and can be changed by changing the
value of ``control.config.defaults['control.default_dt']``.

A discrete time system is created by specifying a nonzero 'timebase', dt
when the system is constructed:

* dt = 0: continuous time system (default)
* dt > 0: discrete time system with sampling period 'dt'
* dt = True: discrete time with unspecified sampling period
* dt = None: no timebase specified

Systems must have compatible timebases in order to be combined. A discrete
time system with unspecified sampling time (`dt = True`) can be combined
with a system having a specified sampling time; the result will be a
discrete time system with the sample time of the latter system. Similarly,
a system with timebase `None` can be combined with a system having any
timebase; the result will have the timebase of the latter system.
The default value of dt can be changed by changing the value of
``control.config.defaults['control.default_dt']``.
"""

# Allow ndarray * StateSpace to give StateSpace._rmul_() priority
Expand Down Expand Up @@ -1270,8 +1277,7 @@ def ss(*args):
Output matrix
D: array_like or string
Feed forward matrix
dt: If present, specifies the sampling period and a discrete time
system is created
dt: If present, specifies the timebase of the system

Returns
-------
Expand Down
24 changes: 16 additions & 8 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
_xferfcn_defaults = {}

class TransferFunction(LTI):

"""TransferFunction(num, den[, dt])

A class for representing transfer functions
Expand All @@ -88,12 +87,21 @@ class TransferFunction(LTI):
means that the numerator of the transfer function from the 6th input to the
3rd output is set to s^2 + 4s + 8.

Discrete-time transfer functions are implemented by using the 'dt'
instance variable and setting it to something other than 'None'. If 'dt'
has a non-zero value, then it must match whenever two transfer functions
are combined. If 'dt' is set to True, the system will be treated as a
discrete time system with unspecified sampling time. The default value of
'dt' is None and can be changed by changing the value of
A discrete time transfer function is created by specifying a nonzero
'timebase' dt when the system is constructed:

* dt = 0: continuous time system (default)
* dt > 0: discrete time system with sampling period 'dt'
* dt = True: discrete time with unspecified sampling period
* dt = None: no timebase specified

Systems must have compatible timebases in order to be combined. A discrete
time system with unspecified sampling time (`dt = True`) can be combined
with a system having a specified sampling time; the result will be a
discrete time system with the sample time of the latter system. Similarly,
a system with timebase `None` can be combined with a system having any
timebase; the result will have the timebase of the latter system.
The default value of dt can be changed by changing the value of
``control.config.defaults['control.default_dt']``.

The TransferFunction class defines two constants ``s`` and ``z`` that
Expand All @@ -103,8 +111,8 @@ class TransferFunction(LTI):

>>> s = TransferFunction.s
>>> G = (s + 1)/(s**2 + 2*s + 1)

"""

def __init__(self, *args):
"""TransferFunction(num, den[, dt])

Expand Down
21 changes: 9 additions & 12 deletions doc/conventions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,24 @@ Discrete time systems
A discrete time system is created by specifying a nonzero 'timebase', dt.
The timebase argument can be given when a system is constructed:

* dt = None: no timebase specified (default)
* dt = 0: continuous time system
* dt = 0: continuous time system (default)
* dt > 0: discrete time system with sampling period 'dt'
* dt = True: discrete time with unspecified sampling period
* dt = None: no timebase specified

Only the :class:`StateSpace`, :class:`TransferFunction`, and
:class:`InputOutputSystem` classes allow explicit representation of
discrete time systems.

Systems must have compatible timebases in order to be combined. A system
with timebase `None` can be combined with a system having a specified
timebase; the result will have the timebase of the latter system.
Similarly, a discrete time system with unspecified sampling time (`dt =
True`) can be combined with a system having a specified sampling time;
the result will be a discrete time system with the sample time of the latter
system. For continuous time systems, the :func:`sample_system` function or
the :meth:`StateSpace.sample` and :meth:`TransferFunction.sample` methods
Systems must have compatible timebases in order to be combined. A discrete time
system with unspecified sampling time (`dt = True`) can be combined with a system
having a specified sampling time; the result will be a discrete time system with the sample time of the latter
system. Similarly, a system with timebase `None` can be combined with a system having a specified
timebase; the result will have the timebase of the latter system. For continuous
time systems, the :func:`sample_system` function or the :meth:`StateSpace.sample` and :meth:`TransferFunction.sample` methods
can be used to create a discrete time system from a continuous time system.
See :ref:`utility-and-conversions`. The default value of 'dt' can be changed by
changing the values of ``control.config.defaults['statesp.default_dt']`` and
``control.config.defaults['xferfcn.default_dt']``.
changing the value of ``control.config.defaults['control.default_dt']``.

Conversion between representations
----------------------------------
Expand Down