Python Control Systems Library

Overview

Python Control Systems Library

The Python Control Systems Library is a Python module that implements basic operations for analysis and design of feedback control systems.

Features

  • Linear input/output systems in state-space and frequency domain
  • Block diagram algebra: serial, parallel, and feedback interconnections
  • Time response: initial, step, impulse
  • Frequency response: Bode and Nyquist plots
  • Control analysis: stability, reachability, observability, stability margins
  • Control design: eigenvalue placement, linear quadratic regulator
  • Estimator design: linear quadratic estimator (Kalman filter)

Links

Dependencies

The package requires numpy, scipy, and matplotlib. In addition, some routines use a module called slycot, that is a Python wrapper around some FORTRAN routines. Many parts of python-control will work without slycot, but some functionality is limited or absent, and installation of slycot is recommended (see below). The Slycot wrapper can be found at:

https://github.com/python-control/Slycot

Installation

Conda and conda-forge

The easiest way to get started with the Control Systems library is using Conda.

The Control Systems library has been packages for the conda-forge Conda channel, and as of Slycot version 0.3.4, binaries for that package are available for 64-bit Windows, OSX, and Linux.

To install both the Control Systems library and Slycot in an existing conda environment, run:

conda install -c conda-forge control slycot

Pip

To install using pip:

pip install slycot   # optional; see below
pip install control

If you install Slycot using pip you'll need a development environment (e.g., Python development files, C and Fortran compilers).

Distutils

To install in your home directory, use:

python setup.py install --user

To install for all users (on Linux or Mac OS):

python setup.py build
sudo python setup.py install

Development

Code

You can check out the latest version of the source code with the command:

git clone https://github.com/python-control/python-control.git

Testing

You can run the unit tests with pytest to make sure that everything is working correctly. Inside the source directory, run:

pytest -v

or to test the installed package:

pytest --pyargs control -v

License

This is free software released under the terms of the BSD 3-Clause License. There is no warranty; not even for merchantability or fitness for a particular purpose. Consult LICENSE for copying conditions.

When code is modified or re-distributed, the LICENSE file should accompany the code or any subset of it, however small. As an alternative, the LICENSE text can be copied within files, if so desired.

Contributing

Your contributions are welcome! Simply fork the GitHub repository and send a pull request.

Please see the Developer's Wiki for detailed instructions.

Comments
  • Release 0.8.4 and 0.9.0 sequencing

    Release 0.8.4 and 0.9.0 sequencing

    I'm opening this issue to create a place to talk through how we are going to merge the many PRs that have built up over the past month (which is great!) in an order that makes sense (which might be hard).

    As a starter, it would be good to tag PRs as something that can go in release 0.8.4 (patch level change => no existing code should stop running) versus 0.9.0 (minor version change => some code might need to be adjusted to work with the release).

    I'll update this post later to try to include a list of the existing PRs, any dependencies, and which of these two releases they should go with.

    opened by murrayrm 49
  • proposal to standardize squeezing output from systems

    proposal to standardize squeezing output from systems

    Proposal: When computing frequency and time response output of systems, standardize on indexing first element so output is a 1D array if system is SISO and squeeze=True. This is instead of applying numpy.squeeze to output.

    Currently, there are two ways that python-control squeezes output:

    1. apply 'squeeze' to the output at the end. This is what functions in timeresp.py do, e.g. forced_response (edit: and iosys time responses). An m x n MIMO system (m-output, n-input, m,n>1) produces a [m x n x k] array, where k is the number of data points in time. But a 1 x n system's output gets squeezed to [n x k] and a m x 1 is squeezed to [m x k].

    2. use indexing to extract the first element if SISO, otherwise leave a full array. This is what the frequency response functions evalfr, freqresp do. If SISO, give [k] length array; MIMO systems always produce [m x n x k] arrays.

    I propose to standardize on the latter: a MIMO system should always output [m x n x k] arrays. Rationale: this facilitates interconnection and keeps indexing the system and its outputs consistent. Along with the proposal: retain the squeeze=True keyword argument because it's already in use, but do the 'squeeze' by indexing the first element, and only do it if SISO.

    Documentation would read something like:

    "If squeeze is True (default) and sys is single input single output (SISO), returns a 1D array equal to the length k of the input, otherwise returns an (n_outputs, n_inputs, k) array for multiple input multiple output (MIMO) systems."

    This is relevant for #449 and popped up in #442.

    enhancement discussion 
    opened by sawyerbfuller 30
  • use __call__ instead of evalfr in lti system classes

    use __call__ instead of evalfr in lti system classes

    fixes problem reported in #434 and extends #179.

    • move to __call__ as primary frequency response method to be used in TransferFunction, StateSpace, and FrequencyResponseData systems. (__call__ is new for StateSpace, and FrequencyResponse)
    • the new __call__ has same interface for all three classes, and can now take one or an array of s, unlike the old _evalfr, which could only take one s
    • it also adds a convenient keyword argument squeeze=True that automatically squeezes output if sys is SISO
    • for FrequencyResponseData.__call__(s), s must be purely imaginary or an error is raised
    • private method _evalfr that was inconsistent with matlab module matlab.evalfr was removed in favor of __call__
    • method sys.evalfr(s) has been deprecated for 2.5 years and is now removed. use __call__ instead, or matlab.evalfr(sys, s) (following discussion in #434)
    • method sys.freqresp(omega) is now deprecated. Use new pythonic methodsys.frequency_respose instead, or freqresp(sys, omega) from matlab module (following discussion in #434)
    • horner(s) now does the same thing for both TransferFunction and StateSpace systems: can evaluate at multiple values of s
    • de-duplication of code, cleanup, pythonization and vectorization of code where possible
    • FRD.eval behavior was left as-is, except for an optional squeeze argument
    opened by sawyerbfuller 26
  • Move away from SLICOT?

    Move away from SLICOT?

    Reported by Clancy Rowley on 2014-07-26 I'm considering rewriting some of the routines in python-control so that it will no longer depend on SLICOT. The main reasons for this are that 1) because SLICOT is written in Fortran, installation can be a pain (see several other comments in this forum); 2) SLICOT has apparently now gone closed-source; 3) most of the key functionality SLICOT provides (e.g., solving Lyapunov equations and Riccati equations) is now included in scipy.linalg, so I'm thinking this might not be too much of a pain.

    Does anybody have thoughts or opinions on this?

    discussion 
    opened by murrayrm 25
  • sgrid() and zgrid() call matplotlib.pyplot.figure()

    sgrid() and zgrid() call matplotlib.pyplot.figure()

    While debugging some code I noticed that examples/pvtol-nested.py was producing a blank figure instead of a pole-zero map that was expected. I chased this down tto the fact that the sgrid() function calls matplotlib.pyplot.figure(). This is in contrast to all other plotting routines and the consequence is that you get a new set of axes. This causes the following code (from examples/pvtol-nested.py) not to work as expected:

    figure(10); clf();
    (P, Z) = pzmap(T, Plot=True)
    print("Closed loop poles and zeros: ", P, Z)
    
    # Gang of Four
    figure(11); clf();
    gangof4(Hi*Po, Co);
    

    Figure 10, which should have the output of pzmap will be blank since pzmap calls figure() (through sgrid) and creates a new set of axis (figure #11). Figure #11 will then get erased (away goes the pole/zero map) and be replace by the Gang of 4.

    opened by murrayrm 24
  • Default dt is 0

    Default dt is 0

    Changes the new default to be dt=0 (continuous-time), rather than dt=None (timebase unspecified) for state space, transfer function, and input output systems. This follows matlab convention as discussed in issue #422

    • new default is dt=0 in these three modules (edit: setting now is in a single location: defaults['control.default_dt'])
    • to make interconnection behavior match what is described in conventions, a new function: lti.common_timebase(dt1, dt2) was introduced. It performs logic to correctly combine timebases of combined systems. The new function now correctly allows discrete-time systems with unspecified sampling time (dt=True) to be combined with systems with specified sampling time (dt!=0, dt!=None, eg dt=0.1).
    • new functions _isstaticgain (edit: now is a method is_static_gain) were added to detect upon initialization whether a state space or transfer function is a static gain. If so, dt=None for such systems so they may be combined with either discrete- or continuous-time systems.
    • I needed to take dt out of the arguments list in iosys init functions because library-wide defaults are not available when modules are first imported, which is when default values in function declarations are evaluated. My solution was to move the dt keyword in the **kwargs dict.
    • fixes to unit tests
    • use_legacy_defaults('0.8.3') reverts to old default behavior of dt=None
    opened by sawyerbfuller 21
  • add unsupervised calculation on gains for root locus plot.

    add unsupervised calculation on gains for root locus plot.

    Add gains up to a tolerance is achived. @slivingston I wait for reviews. I have a file with some examples that are an exersice taken from Franklyn book. Let me know if you need it to test the algorithm. Do I have to put in a particular place? Where? Thanks in advance.

    opened by gonmolina 20
  • Decide on how to handle (to be deprecated?) np.matrix class

    Decide on how to handle (to be deprecated?) np.matrix class

    The latest version of numpy is listing the matrix class as something that may be deprecated in the future (see numpy-discussion thread). This is currently generating warning messages in our unit tests (see issue #232) but otherwise not causing any harm.

    At some point we have to decide whether to switch out internal operations to use the array class, as recommended in the numpy documentation.

    enhancement 
    opened by murrayrm 19
  • Elegant way to generate a transfer function matrix

    Elegant way to generate a transfer function matrix

    Hi everybody, I want to know if there is a more elegant way to generate a transfer-function-matrix for a hinf-controller.

    In matlab I just do: P11 = [0 0; W2*G W2] P12 = [W1; W2*G] P21 = [G 1] P22 = [G] P_ = [P11 P12; P21 P22] sys = ss(P_, 'minimal');

    In python with control, I habe to do: import control from control import * Gss = ss([[-1.0, -10.0], [1, 0]], [[10.0], [0]], [0, 1], [0]) G = tf(Gss) W1 = tf([100], [0.1, 1]) W2 = tf([100], [0.1, 1]) W2G = W2*G num = [ [ [0], [0], W1.num[0][0] ], [W2G.num[0][0], W2.num[0][0], G.num[0][0]], [G.num[0][0], [1], G.num[0][0] ] ]
    den = [ [ [1], [1], W1.den[0][0] ], [W2G.den[0][0], W2.den[0][0], G.den[0][0]], [G.den[0][0], [1], G.den[0][0] ] ] P = tf( num, den ) print(P)

    The problem is that the return of the numerator and denominator is not directly the list.

    And I get a high order system. Should I use just the balanced trunction? Pss = ss(P) Pbr = balred(Pss, 4)


    Matlab is using minreal with exist also in "control", but I have to find manually a suitable tolerance...

    opened by iljastas 18
  • update examples to python 3

    update examples to python 3

    Hi, it is mainly about the print brackets for python3.

    Also, as many examples do not show the actual plot, I recommend to use import matplotlib.pyplot as plt at the beginning and put a plt.show() at the end. Otherwise, it is hard for newbies to know what is going on.

    enhancement documentation 
    opened by Robomate 18
  • Add Project to the Python Package Index [sf#3]

    Add Project to the Python Package Index [sf#3]

    Reported by eike on 2011-06-12 13:43 UTC The Python Control project should be added to the Python Package Index. http://pypi.python.org/pypi

    This would ease some administrative work:

    • Uploading packages can be easily automated.
    • Each package has a documentation website. Uploading the the generated website can be automated too.
    • Users can install the library with easy_install. A user would only need to type easy_install python-control to download and install the package.
    • It would also give the project additional visibility.

    An introduction how to automate build and upload tasks, in conjunction with the Python Package Index, is here: http://packages.python.org/an_example_pypi_project/

    opened by murrayrm 18
  • control.damp(sys)

    control.damp(sys)

    control.damp(sys) do not deal correctly with overdamped modes and built in print function inside it should be deactivated because even if you put it wn[i],damping[i],eig[i]=control.damp(sys[i]) it is still printing every thing

    opened by Nabil-Bishtawi 0
  • test_optimal: More failures on exotic platforms

    test_optimal: More failures on exotic platforms

    optimal_test.py::test_optimal_doc[shooting-3-u0-None] fails on all non-intel platforms when packaging for openSUSE Tumbleweed:

    Same failure on aarch64 (64-bit ARM) s390x (IBM), ppc64le and ppc64 (PowerPC)

    [  102s] =================================== FAILURES ===================================
    [  102s] _____________________ test_optimal_doc[shooting-3-u0-None] _____________________
    [  102s] 
    [  102s] method = 'shooting', npts = 3, initial_guess = array([10.,  0.]), fail = None
    [  102s] 
    [  102s]     @pytest.mark.parametrize(
    [  102s]         "method, npts, initial_guess, fail", [
    [  102s]             ('shooting', 3, None, 'xfail'),         # doesn't converge
    [  102s]             ('shooting', 3, 'zero', 'xfail'),       # doesn't converge
    [  102s]             ('shooting', 3, 'u0', None),            # github issue #782
    [  102s]             ('shooting', 3, 'input', 'endpoint'),   # doesn't converge to optimal
    [  102s]             ('shooting', 5, 'input', 'endpoint'),   # doesn't converge to optimal
    [  102s]             ('collocation', 3, 'u0', 'endpoint'),   # doesn't converge to optimal
    [  102s]             ('collocation', 5, 'u0', 'endpoint'),
    [  102s]             ('collocation', 5, 'input', 'openloop'),# open loop sim fails
    [  102s]             ('collocation', 10, 'input', None),
    [  102s]             ('collocation', 10, 'u0', None),        # from documentation
    [  102s]             ('collocation', 10, 'state', None),
    [  102s]             ('collocation', 20, 'state', None),
    [  102s]         ])
    [  102s]     def test_optimal_doc(method, npts, initial_guess, fail):
    [  102s]         """Test optimal control problem from documentation"""
    [  102s]         def vehicle_update(t, x, u, params):
    [  102s]             # Get the parameters for the model
    [  102s]             l = params.get('wheelbase', 3.)         # vehicle wheelbase
    [  102s]             phimax = params.get('maxsteer', 0.5)    # max steering angle (rad)
    [  102s]     
    [  102s]             # Saturate the steering input
    [  102s]             phi = np.clip(u[1], -phimax, phimax)
    [  102s]     
    [  102s]             # Return the derivative of the state
    [  102s]             return np.array([
    [  102s]                 np.cos(x[2]) * u[0],            # xdot = cos(theta) v
    [  102s]                 np.sin(x[2]) * u[0],            # ydot = sin(theta) v
    [  102s]                 (u[0] / l) * np.tan(phi)        # thdot = v/l tan(phi)
    [  102s]             ])
    [  102s]     
    [  102s]         def vehicle_output(t, x, u, params):
    [  102s]             return x                            # return x, y, theta (full state)
    [  102s]     
    [  102s]         # Define the vehicle steering dynamics as an input/output system
    [  102s]         vehicle = ct.NonlinearIOSystem(
    [  102s]             vehicle_update, vehicle_output, states=3, name='vehicle',
    [  102s]             inputs=('v', 'phi'), outputs=('x', 'y', 'theta'))
    [  102s]     
    [  102s]         # Define the initial and final points and time interval
    [  102s]         x0 = np.array([0., -2., 0.]); u0 = np.array([10., 0.])
    [  102s]         xf = np.array([100., 2., 0.]); uf = np.array([10., 0.])
    [  102s]         Tf = 10
    [  102s]     
    [  102s]         # Define the cost functions
    [  102s]         Q = np.diag([0, 0, 0.1])          # don't turn too sharply
    [  102s]         R = np.diag([1, 1])               # keep inputs small
    [  102s]         P = np.diag([1000, 1000, 1000])   # get close to final point
    [  102s]         traj_cost = opt.quadratic_cost(vehicle, Q, R, x0=xf, u0=uf)
    [  102s]         term_cost = opt.quadratic_cost(vehicle, P, 0, x0=xf)
    [  102s]     
    [  102s]         # Define the constraints
    [  102s]         constraints = [ opt.input_range_constraint(vehicle, [8, -0.1], [12, 0.1]) ]
    [  102s]     
    [  102s]         # Define an initial guess at the trajectory
    [  102s]         timepts = np.linspace(0, Tf, npts, endpoint=True)
    [  102s]         if initial_guess == 'zero':
    [  102s]             initial_guess = 0
    [  102s]     
    [  102s]         elif initial_guess == 'u0':
    [  102s]             initial_guess = u0
    [  102s]     
    [  102s]         elif initial_guess == 'input':
    [  102s]             # Velocity = constant that gets us from start to end
    [  102s]             initial_guess = np.zeros((vehicle.ninputs, timepts.size))
    [  102s]             initial_guess[0, :] = (xf[0] - x0[0]) / Tf
    [  102s]     
    [  102s]             # Steering = rate required to turn to proper slope in first segment
    [  102s]             straight_seg_length = timepts[-2] - timepts[1]
    [  102s]             curved_seg_length = (Tf - straight_seg_length)/2
    [  102s]             approximate_angle = math.atan2(xf[1] - x0[1], xf[0] - x0[0])
    [  102s]             initial_guess[1, 0] = approximate_angle / (timepts[1] - timepts[0])
    [  102s]             initial_guess[1, -1] = -approximate_angle / (timepts[-1] - timepts[-2])
    [  102s]     
    [  102s]         elif initial_guess == 'state':
    [  102s]             input_guess = np.outer(u0, np.ones((1, npts)))
    [  102s]             state_guess = np.array([
    [  102s]                 x0 + (xf - x0) * time/Tf for time in timepts]).transpose()
    [  102s]             initial_guess = (state_guess, input_guess)
    [  102s]     
    [  102s]         # Solve the optimal control problem
    [  102s]         result = opt.solve_ocp(
    [  102s]             vehicle, timepts, x0, traj_cost, constraints,
    [  102s]             terminal_cost=term_cost, initial_guess=initial_guess,
    [  102s]             trajectory_method=method,
    [  102s]             # minimize_method='COBYLA', # SLSQP',
    [  102s]         )
    [  102s]     
    [  102s]         if fail == 'xfail':
    [  102s]             assert not result.success
    [  102s]             pytest.xfail("optimization fails to converge")
    [  102s]         elif fail == 'precision':
    [  102s]             assert result.status == 2
    [  102s]             pytest.xfail("optimization precision not achieved")
    [  102s]         else:
    [  102s]             # Make sure the optimization was successful
    [  102s]             assert result.success
    [  102s]     
    [  102s]             # Make sure we started and stopped at the right spot
    [  102s]             if fail == 'endpoint':
    [  102s]                 assert not np.allclose(result.states[:, -1], xf, rtol=1e-4)
    [  102s]                 pytest.xfail("optimization does not converge to endpoint")
    [  102s]             else:
    [  102s]                 np.testing.assert_almost_equal(result.states[:, 0], x0, decimal=4)
    [  102s] >               np.testing.assert_almost_equal(result.states[:, -1], xf, decimal=2)
    [  102s] 
    [  102s] control/tests/optimal_test.py:723: 
    [  102s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    [  102s] /usr/lib64/python3.8/contextlib.py:75: in inner
    [  102s]     return func(*args, **kwds)
    [  102s] /usr/lib64/python3.8/contextlib.py:75: in inner
    [  102s]     return func(*args, **kwds)
    [  102s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
    [  102s] 
    [  102s] args = (<function assert_array_almost_equal.<locals>.compare at 0x3ff61d50430>, array([100.,  -2.,   0.]), array([100.,   2.,   0.]))
    [  102s] kwds = {'err_msg': '', 'header': 'Arrays are not almost equal to 2 decimals', 'precision': 2, 'verbose': True}
    [  102s] 
    [  102s]     @wraps(func)
    [  102s]     def inner(*args, **kwds):
    [  102s]         with self._recreate_cm():
    [  102s] >           return func(*args, **kwds)
    [  102s] E           AssertionError: 
    [  102s] E           Arrays are not almost equal to 2 decimals
    [  102s] E           
    [  102s] E           Mismatched elements: 1 / 3 (33.3%)
    [  102s] E           Max absolute difference: 4.
    [  102s] E           Max relative difference: 2.
    [  102s] E            x: array([100.,  -2.,   0.])
    [  102s] E            y: array([100.,   2.,   0.])
    [  102s] 
    [  102s] /usr/lib64/python3.8/contextlib.py:75: AssertionError
    [  102s] ----------------------------- Captured stdout call -----------------------------
    [  102s] Summary statistics:
    [  102s] * Cost function calls: 7
    [  102s] * Constraint calls: 16
    [  102s] * System simulations: 22
    [  102s] * Final cost: 16000.0
    
    opened by bnavigator 0
  • Readthedocs points to wrong version of source code for .postN release

    Readthedocs points to wrong version of source code for .postN release

    I though I fixed this in #836, but it looks like readthedocs is still pointing to the main branch for v0.9.3.post2. Not a big deal, but flagging it here for fixing in the next release.

    opened by murrayrm 0
  • Incorrect nyquist plot

    Incorrect nyquist plot

    I'm using the control package with python 3.10 in Pycharm and Jupiter lab. I have stumbled upon a possible issue while trying to create a Nyquist plot for a simple system

    import control as ct
    
    s = ct.tf('s'))
    plant_1 = 1/(s*(s + 5)*(s + 7)))
    ct.nyquist_plot(plant_1)
    
    

    The result I'm getting is this:

    download

    While in MATLAB I'm getting different results

    clear all;
    close all;
    clc;
    
    
    s = tf('s');
    plant_1 = 1/(s*(s + 5)*(s + 7));
    nyquistplot(plant_1)
    
    

    image

    Is there a limitation that might be causing this issue or am I missing something?

    opened by Avitan01 1
  • Modest proposal for discussion: eliminate `LinearICSystem` class

    Modest proposal for discussion: eliminate `LinearICSystem` class

    It is not clear to me what purpose there is for a LinearICSystem. One possibility is as a biquad cascade*, but this can already be implemented by forcing the interconnected systems to be NonlinearIOSystems, and is not currently supported by LinearICSystems anyway because the constituent systems are combined into a single system with A, B, C, D matrices and signal names.

    Is there any other use case for a LinearICSystem? I can't figure out what benefit there is to preserving other characteristics of an InterconnectedSystem, if such a system is always used in an equivalent way to a LinearIOSystem.

    *There are cases when you don't want a combined interconnected series of systems to be tunred into a single state-space or transfer function system. For example, if you want to numerically interconnect a series of linear systems to create a biquad cascade to avoid numerical issues that crop up when combining large and small coefficients. This comes up for example when implementing a high-order pade approximation (see e.g. https://www.embeddedrelated.com/showarticle/927.php)

    discussion 
    opened by sawyerbfuller 0
  • support multiple gain margins

    support multiple gain margins

    Hello,

    I'm computing stability margins of a system.

    The phase margin (PM) is computed correctly, but the gain margin (GM) shows zero (actually it shows 1E-16).

    Analyzing the bode plot of the open-loop (OL) transfer function, it clearly shows that the GM should be infinite, since the phase of the

    OL never crosses the -180 deg line (it only converges to it asymptotically as omega approaces infinity).

    See below the bode plot of the OL, including stability margins.

    Any idea why it happens?

    Thanks, -Shai

    zero_gain_margin

    enhancement 
    opened by shaikinast 14
Releases(0.9.3)
  • 0.9.3(Dec 31, 2022)

    What's Changed

    • Handle t_eval for static systems in input_output_response by @murrayrm in https://github.com/python-control/python-control/pull/743
    • add GitHub URL for PyPi by @andriyor in https://github.com/python-control/python-control/pull/708
    • Remove Deprecated API calls to Pytest, SciPy <1.3, Python 2 by @bnavigator in https://github.com/python-control/python-control/pull/745
    • Add passivity module, ispassive function, and passivity_test. Introduces optional dependency cvxopt. by @Mark-Yeatman in https://github.com/python-control/python-control/pull/739
    • Slycot source uses setuptools_scm now by @bnavigator in https://github.com/python-control/python-control/pull/751
    • Passivity indices and support for discrete time systems. by @Mark-Yeatman in https://github.com/python-control/python-control/pull/750
    • Switch CI to mambaforge and conda-forge channel by @bnavigator in https://github.com/python-control/python-control/pull/757
    • Fix timebase bug in InterconnectedSystem (issue #754) by @murrayrm in https://github.com/python-control/python-control/pull/755
    • fix issue with slycot balred change in state by @bnavigator in https://github.com/python-control/python-control/pull/762
    • Build system and test suite update by @bnavigator in https://github.com/python-control/python-control/pull/759
    • fix control.matlab.lsim bug for discrete time system by @murrayrm in https://github.com/python-control/python-control/pull/765
    • Add B-splines and solve_flat_ocp to flatsys by @murrayrm in https://github.com/python-control/python-control/pull/763
    • CI: switch slycot and cvxopt installation order by @murrayrm in https://github.com/python-control/python-control/pull/769
    • Fixed a couple of typos in documentation by @fredrhen in https://github.com/python-control/python-control/pull/775
    • Allow new matplotlib 3.6 error message in kwargs tests by @bnavigator in https://github.com/python-control/python-control/pull/777
    • Move sys._update_params(params) before TimeResponseData return when nstate == 0 by @hyumo in https://github.com/python-control/python-control/pull/774
    • Update MANIFEST.in by @bnavigator in https://github.com/python-control/python-control/pull/779
    • Improve compatibility of state space representation using LaTeX by @gonmolina in https://github.com/python-control/python-control/pull/780
    • Fix interconnect type conversion bug for StateSpace systems by @murrayrm in https://github.com/python-control/python-control/pull/788
    • fix _isstatic() to use nstates==0 by @murrayrm in https://github.com/python-control/python-control/pull/790
    • fix error when an IOSystem is combined with a TransferFunction system by @sawyerbfuller in https://github.com/python-control/python-control/pull/793
    • check for and fix mutable keyword defaults by @murrayrm in https://github.com/python-control/python-control/pull/794
    • Fixes for bugs found by pylint by @roryyorke in https://github.com/python-control/python-control/pull/795
    • Support Python 3.11 and drop Python 3.7 by @bnavigator in https://github.com/python-control/python-control/pull/796
    • Fix find_eqpt when y0 is None by @adswid in https://github.com/python-control/python-control/pull/798
    • Preserve signal names upon conversion to discrete-time by @sawyerbfuller in https://github.com/python-control/python-control/pull/797
    • Update benchmarks to help with optimal control tuning by @murrayrm in https://github.com/python-control/python-control/pull/800
    • Update optimal.rst by @htadashi in https://github.com/python-control/python-control/pull/802
    • Add collocation method for optimal control problems by @murrayrm in https://github.com/python-control/python-control/pull/799
    • Update README.rst by @sawyerbfuller in https://github.com/python-control/python-control/pull/810
    • Update docstring for impulse for discrete sys by @sawyerbfuller in https://github.com/python-control/python-control/pull/812
    • Enable scalar division of state-space objects by @roryyorke in https://github.com/python-control/python-control/pull/811
    • fix gain handling in rlocus and sisotool by @sawyerbfuller in https://github.com/python-control/python-control/pull/809
    • Removed epsilon perturbation value in solve_passivity_LMI. Fix associated unit test. by @Mark-Yeatman in https://github.com/python-control/python-control/pull/814
    • docstring improvements by @sawyerbfuller in https://github.com/python-control/python-control/pull/804
    • add zpk() function by @murrayrm in https://github.com/python-control/python-control/pull/816
    • Fix readthedocs to use pip-based install by @murrayrm in https://github.com/python-control/python-control/pull/817
    • Relax comparison of floats in tests by @bnavigator in https://github.com/python-control/python-control/pull/818
    • Add test matrix against operating environments by @murrayrm in https://github.com/python-control/python-control/pull/821
    • Update find_eqpts to handle discrete time systems by @murrayrm in https://github.com/python-control/python-control/pull/824
    • Small fixes and tweaks by @murrayrm in https://github.com/python-control/python-control/pull/826
    • update docs to use use numpydoc + linkcode by @murrayrm in https://github.com/python-control/python-control/pull/828
    • Add gain scheduling to create_statefbk_iosystem() by @murrayrm in https://github.com/python-control/python-control/pull/827
    • continuous time system support for create_estimator_iosystem by @murrayrm in https://github.com/python-control/python-control/pull/829
    • Small docstring fixes for release by @murrayrm in https://github.com/python-control/python-control/pull/832

    New Contributors

    • @andriyor made their first contribution in https://github.com/python-control/python-control/pull/708
    • @Mark-Yeatman made their first contribution in https://github.com/python-control/python-control/pull/739
    • @fredrhen made their first contribution in https://github.com/python-control/python-control/pull/775
    • @hyumo made their first contribution in https://github.com/python-control/python-control/pull/774
    • @adswid made their first contribution in https://github.com/python-control/python-control/pull/798
    • @htadashi made their first contribution in https://github.com/python-control/python-control/pull/802

    Full Changelog: https://github.com/python-control/python-control/compare/0.9.2...0.9.3

    Source code(tar.gz)
    Source code(zip)
  • 0.9.2(May 28, 2022)

    What's Changed

    • Round to nearest integer decade for default omega vector by @bnavigator in https://github.com/python-control/python-control/pull/688
    • Fix in documentation of ss2tf by @miroslavfikar in https://github.com/python-control/python-control/pull/695
    • Interpret str-type args to interconnect as non-sequence by @roryyorke in https://github.com/python-control/python-control/pull/698
    • Fixes to various optimization-based control functions by @murrayrm in https://github.com/python-control/python-control/pull/709
    • I/O system enhancements by @murrayrm in https://github.com/python-control/python-control/pull/710
    • Optimal control enhancements by @murrayrm in https://github.com/python-control/python-control/pull/712
    • Keyword argument checking by @murrayrm in https://github.com/python-control/python-control/pull/713
    • Stochastic systems additions by @murrayrm in https://github.com/python-control/python-control/pull/714
    • Updated system class functionality by @murrayrm in https://github.com/python-control/python-control/pull/721
    • Bug fix and improvements to Nyquist plots by @murrayrm in https://github.com/python-control/python-control/pull/722
    • Add linform to compute linear system L-infinity norm by @roryyorke in https://github.com/python-control/python-control/pull/729
    • Improvements to Nichols chart plotting by @roryyorke in https://github.com/python-control/python-control/pull/723
    • Add envs to gitignore by @s35t in https://github.com/python-control/python-control/pull/731
    • Added binder link by @jonititan in https://github.com/python-control/python-control/pull/693
    • Update python-package-conda workflow to use conda instead of conda-forge by @murrayrm in https://github.com/python-control/python-control/pull/736
    • Fix README.rst for twine by @murrayrm in https://github.com/python-control/python-control/pull/738

    New Contributors

    • @s35t made their first contribution in https://github.com/python-control/python-control/pull/731
    • @jonititan made their first contribution in https://github.com/python-control/python-control/pull/693

    Full Changelog: https://github.com/python-control/python-control/compare/0.9.1...0.9.2

    Source code(tar.gz)
    Source code(zip)
  • 0.9.1(Dec 31, 2021)

    Version 0.9.1 is a minor release that includes new functionality for discrete time systems (dlqr, dlqe, drss), flat systems (optimization and constraints), a new time response data class, and many individual improvements and bug fixes.

    New features:

    • Add optimization to flat systems trajectory generation (#569 by murrayrm)
    • Return a discrete time system with drss() (#589 by bnavigator)
    • A first implementation of the singular value plot (#593 by forgi86)
    • Include InfValue into settling min/max calculation for step_info (#600 by bnavigator)
    • New time response data class (#649 by murrayrm)
    • Check for unused subsystem signals in InterconnectedSystem (#652 by roryyorke)
    • New PID design function built on sisotool (#662 by sawyerbfuller)
    • Modify discrete-time contour for Nyquist plots to indent around poles (#668 by sawyerbfuller)
    • Additional I/O system type conversions (#672 by murrayrm)
    • Remove Python 2.7 support and leverage @ operator (#679 by bnavigator)
    • Discrete time LQR and LQE (#670 by sawyerbfuller, murrayrm)

    Improvements, bug fixes:

    • Change step_info undershoot percentage calculation (#590 by juanodecc)
    • IPython LaTeX output only generated for small systems (#607 by roryyorke)
    • Fix warnings generated by sisotool (#608 by roryyorke)
    • Discrete time LaTeX repr of StateSpace systems (#609 by bnavigator)
    • Updated rlocus.py to remove warning by sisotool() with rlocus_grid=True (#616 by nirjhar-das)
    • Refine automatic contour determination in Nyquist plot (#620 by bnavigator)
    • Fix damp method for discrete time systems with a negative real-valued pole (#647 by vincentchoqueuse)
    • Plot Nyquist frequency correctly in Bode plot in Hz (#651 by murrayrm)
    • Return frequency response for 0 and 1-state systems directly (#663 by bnavigator)
    • Fixed prewarp not working in c2d and sample_system, margin docstring improvements (#669 by sawyerbfuller)
    • Improved lqe calling functionality (#673 by murrayrm)
    • Vectorize FRD feedback function (#680 by bnavigator)
    • BUG: extrapolation in ufun throwing errors (#682 by miroslavfikar)
    • Allow use of SciPy for LQR, LQE (#683 by murrayrm)
    • Improve forced_response and its documentation (#588 by bnavigator)
    • Add documentation about use of axis('equal') in pzmap, rlocus (#685 by murrayrm)

    Additional changes:

    • Replace Travis badge with GHA workflows, add PyPI and conda badges (#584 by bnavigator)
    • Don't install toplevel benchmarks package (#585 by bnavigator)
    • LTI squeeze: ndarray.ndim == 0 is also a scalar (#595 by bnavigator)
    • xfail testmarkovResults until #588 is merged (#601 by bnavigator)
    • Remove from readme.rst that you need a fortran compiler (#602 by sawyerbfuller)
    • Remove statement that slycot only on linux (#603 by sawyerbfuller)
    • Allow float precision in result assertions (#615 by bnavigator)
    • Improved unit test coverage for root_locus: dtime and sisotool (#617 by bnavigator)
    • Add DefaultDict for deprecation handling (#619 by bnavigator)
    • Documentation updates (#633 by murrayrm)
    • Various docstring edits + fixed plot legends on cruise control example (#643 by billtubbs)
    • Ease test tolerance on timeseries (#659 by bnavigator)
    • Use conda-forge for numpy (CI fix) (#667 by bnavigator)
    • Fix doc escape (#674 by bnavigator)
    • Remove duplicate Slycot error handling, require Slycot >=0.4 (#678 by bnavigator)
    • Full list of merged pull requests associated with this release.
    • Full list of commits associated with this release.
    Source code(tar.gz)
    Source code(zip)
  • 0.9.0(Mar 20, 2021)

    Version 0.9.0 of the Python Control Toolbox (python-control) contains a number of enhanced features and changes to functions. Some of these changes may require modifications to existing user code and, in addition, some default settings have changed that may affect the appearance of plots or operation of certain functions.

    Significant new additions including improvements in the I/O systems modules that allow automatic interconnection of signals having the same name (via the interconnect function), generation and plotting of describing functions for closed loop systems with static nonlinearities, and a new optimal control module that allows basic computation of optimal controls (including model predictive controllers). Some of the changes that may break use code include the deprecation of the NumPy matrix type (2D NumPy arrays are used instead), changes in the return value for Nyquist plots (now returns number of encirclements rather than the frequency response), switching the default timebase of systems to be 0 rather than None (no timebase), and changes in the processing of return values for time and frequency responses (to make them more consistent). In many cases, the earlier behavior can be restored by calling use_legacy_defaults('0.8.4'). A full list of additions and changes is described below.

    New features

    • Optimal control module, including rudimentary MPC control (#549 by murrayrm)
    • Describing functions plots (#521 by murrayrm)
    • MIMO impulse and step response (#514 by murrayrm)
    • I/O system improvements:
      • linearize() retains signal names plus new interconnect() function (#497 by murrayrm)
      • Add summing junction + implicit signal interconnection (#517 by murrayrm)
    • Implementation of initial_phase, wrap_phase keywords for bode_plot (#494 by murrayrm)
    • Added IPython LaTeX representation method for StateSpace objects (#450 by roryyorke)
    • New dynamics() and output() methods in StateSpace (#566 by sawyerbfuller)
    • FRD systems can now be created from a discrete time LTI system (#568 by bnavigator)
    • Cost and constraints are now allowed for flatsys.point_to_point() (#569 by murrayrm)

    Interface changes

    • Switch default state space matrix type to 'array' (instead of 'matrix') (#480 by murrayrm, #486 by bnavigator, #433 by sawyerbfuller)
    • Use __call__ instead of evalfr in lti system classes (#449 by sawyerbfuller)
    • Default dt is now 0 instead of None (#431 by sawyerbfuller, #490 by bnavigator)
    • Change default value of statesp.remove_useless_states to False (#509 by murrayrm)
    • Standardize time response return values, return_x/squeeze keyword processing (#511 by murrayrm)
    • Standardize squeeze processing in frequency response functions (#507 by murrayrm)
    • Nyquist plot now returns number of encirclements (#534 by murrayrm)
    • Switch LTI class and subclasses to use ninputs, noutputs, nstates (#515 by murrayrm)
    • Use standard time series convention for markov() input data (#508 by murrayrm)
    • TransferFunction array priority plus system type conversion checking (#498 by murrayrm)
    • Generate error for tf2ss of non-proper transfer function (#492 by murrayrm)
    • Updated return values for frequency response evaluated at poles (#542 by murrayrm)

    Improvements, bug fixes

    • Nyquist plot improvements: better arrows, handle poles on imaginary axis (#534 by murrayrm)
    • Sisotool small visual cleanup, new feature to show step response of different input-output than loop (#531 by sawyerbfuller)
    • Add bdschur() and fox modal form with repeated eigenvalues (#495 by roryyorke)
    • Fix rlocus timeout due to inefficient _default_wn calculation (#527 by murrayrm)
    • Fix #523: finding z for |H(z)|=1 computed the wrong polynomials (#525 by bnavigator)
    • Freqplot improvements (#522 by sawyerbfuller)
    • Fix rlocus plotting problem in Jupyter notebooks (#503 by murrayrm)
    • Handle empty pole vector for timevector calculation (#485 by bnavigator)
    • Fix lqe() docstring and input array type (#483 by bnavigator)
    • Updated markov() to add tranpose keyword + default warning (#478 by murrayrm)
    • Fix impulse size for discrete-time impulse response (#447 by sawyerbfuller)
    • Extend returnScipySignalLTI() to handle discrete-time systems (#445 by bnavigator)
    • Bug fixes and extensions for step_info() (#555 by sawyerbfuller, #567 by juanodecc, #577 by bnavigator)

    Additional changes

    • Address NumPy deprecations np.int, np.float (#539 by dapperfu, #548 by murrayrm)
    • Shift CI tests from Travis CI to GitHub Actions (#504 by murrayrm)
    • Link to developer wiki in docs. (#502 by sawyerbfuller)
    • Reduce Python 3 testing to speed up Travis CI testing (#487 by murrayrm)
    • Refactor the test suite using pytest for array and matrix types (#438 by bnavigator)
    • Full list of merged pull requests associated with this release.
    • Full list of commits associated with this release.
    Source code(tar.gz)
    Source code(zip)
  • 0.8.4(Dec 28, 2020)

    This release introduces several new features as well as bug fixes and documentation improvements:

    • Improved default time vector for time response functions (bnavigator, sawyerbfuller)
    • New use_legacy_defaults function to allow compatibility with previous versions (sawyerbfuller)
    • Allow creation of non-proper transfer functions (bnavigator, rlegnain)
    • Added ability to set arrow head length and width option in nyquist_plot (geekonloose)
    • Added ability to 'prewarp' the conversion of continuous to discrete-time systems (sawyerbfuller)
    • Added rlocus capability for discrete-time systems (sawyerbfuller)
    • Updated pzmap grid to be compatible with matplotlib updates (bnavigator)
    • Implement loadable string representation (repr) for tf, ss, and frd (repagh)
    • Fixed margin computation for discrete time systems (bnavigator)
    • Fixed indexing bug in bdalg.connect (sawyerbfuller)
    • Fixed InterconnectedSystem naming bugs, improved conventions (samlaf)
    • Fixed LinearIOSystem output bug in output function (francescoseccamonte)
    • Fixed bug in forced_response that overrode squeeze parameter (bnavigator)
    • Use rad/sec for Bode plot in MATLAB bode (was erroneously defaulting to Hertz) (paulvicioso)
    • Removed deprecated scipy calls and updated to latest numpy (bnavigator)
    • Multiple documentation updates (bnavigator, laurensvalk)
    • New and improved examples for sisotool, pvtol (repagh, samlaf)
    • The rlocus function no longer automatically creates a new figure
    • Updated unit tests + switch to pytest (bnavigator, sawyerbfuller)
    • Return type for eigenvalues in lqe changed to 1D array (matches lqr)
    • Small fixes + documentation updates to markov

    More info:

    Source code(tar.gz)
    Source code(zip)
  • 0.8.3(Jan 4, 2020)

    This release introduces several new features as well as bug fixes and documentation improvements:

    • New input/output systems module for creating nonlinear systems from individual I/O subsystems, with find_eqpt, input_output_response, and linearize functionality
    • Initial implementation of differential flatness module for computing feasible trajectories for differentially flat (nonlinear) systems
    • Preliminary version of lqe function (sawyerbfuller)
    • New dict-based implementation of user-configurable package/module configuration parameters
    • Added similarity transformation function
    • Add 's' and 'z' variable support to tf()
    • Fixed discrete time simulation time step issue
    • Reordered Gang of Four plots to match FBS
    • Check for symmetric matrices with machine precision (bnavigator)
    • Changed root precision tolerance and imaginary detection in xferfcn._common_den (bnavigator)
    • Fixed bug in timeresp.forced_response (adm78)
    • Improved latex representation for exp format and multi-digit exponents of s or z (bnavigator)
    • Renamed FRD class name FrequencyResponseData to fix MacOS sphinx build problems (FRD still defined for backward compatibility`
    • Allow np.array or np.matrix for state space matrices, operations via use_numpy_matrix
    • Improved detection of when to add additional points in root_locus
    • Adaptive gain click criterion and zoom bug fix for root_locus (icam0)
    • Improved code for ctrb and obsv (billtubbs)
    • Documentation updates (bnavigator, murrayrm, roryyorke)
    • Updated examples to be PEP compliant
    • Improved unit tests (bnavigator, murrayrm), increased coverage to ~80%

    More info:

    Source code(tar.gz)
    Source code(zip)
  • 0.8.2(Apr 20, 2019)

    This is mainly a maintenance release with lots of small bug fixes and performance improvements:

    • Fixed a number of small bugs , including discrete time simulations (bnavigator), integer values in state space matrics (don4get), missing zeros on pole/zero plots (Sup3rGeo)

    • First cut at a new step_info() function, similar to MATLAB (joaoantoniocardoso)

    • Added a new function for dynamically setting gain in sisotool (icam0)

    • Anti-stabilizing solutions for Riccati equations are now available (dbacc)

    • Printout out state space systems in Jupyter notebooks now formats using LaTeX (alchemyst)

    • Additional performance and visualiation improvements: _remove_useless_states (adm78), margins on Bode plots ( icam0), improved damping lines in discrete pzmap (Sup3rGeo)

    Source code(tar.gz)
    Source code(zip)
  • 0.8.1(Dec 23, 2018)

    This release fixes a number of small issues and adds a few new figures:

    • A new canonical function modal_form can be used to convert a state space system to modal form (ipa-lth)
    • Improved pole placement algorithm place_varga (rabraker)
    • Bug fix in computing poles of MIMO transfer functions
    • Indexing of MIMO transfer functions (hungpham2511)
    • Additional small bug fixes (adm78, stertingen)
    • Documentation updates and fixes (joaoantoniocardoso)
    • List of all changes in this release
    Source code(tar.gz)
    Source code(zip)
  • 0.8.0(Jul 7, 2018)

    • Updated and corrected docstrings (PR #198, PR #216)
    • Better support for MIMO systems in pole() and zero() functions (PR #205, PR #206)
    • Support for SciPy-1.0.0 updates to the scipy.signal module that is used for some python-control functions and support for numpy data types (int32, int64, etc) in all python-control functions (PR #170)
    • Support for static gains (0D state space systems and constant transfer functions) (PR #104, PR #110, PR #126, PR #129, PR #145)
      • Note: Open issues related to this: #165
    • New functions obsv (observable canonical form, PR #103), augw and mixsyn (mixed sensitivity synthesis, PR #151)
    • List of merged pull requests associated with this release.
    • List of commits associated with this release
    Source code(tar.gz)
    Source code(zip)
Owner
Control Systems Library for Python
Control Systems Library for Python
A python API act as Control Center to control your Clevo Laptop via wmi on windows.

ClevoPyControlCenter A python API act as Control Center to control your Clevo Laptop via wmi on windows. Usage # pip3 install pymi from clevo_wmi impo

null 3 Sep 19, 2022
TurtleBot Control App - TurtleBot Control App With Python

TURTLEBOT CONTROL APP INDEX: 1. Introduction 2. Environments 2.1. Simulated Envi

Rafanton 4 Aug 3, 2022
Inverted-pendulum-with-fuzzy-control - Inverted pendulum with fuzzy control

Fuzzy Inverted Pendulum Basically, this project consists of an inverted pendulum

Mahan Ahmadvand 1 Aug 25, 2022
A Python library to simulate a Zoom H6 recorder remote control

H6 A Python library to emulate a Zoom H6 recorder remote control Introduction This library allows you to control your Zoom H6 recorder from your compu

Matias Godoy 68 Nov 2, 2022
inverted pendulum fuzzy control python code (python 2.7.18)

inverted-pendulum-fuzzy-control- inverted pendulum fuzzy control python code (python 2.7.18) We have 3 general functions for 3 main steps: fuzzificati

arian mottaghi 4 May 23, 2022
Intelligent Systems Project In Python

Intelligent Systems Project In Python

RLLAB 3 May 16, 2022
Using Python to parse through email logs received through several backup systems.

outlook-automated-backup-control Backup monitoring on a mailbox: In this mailbox there will be backup logs. The identification will based on the follo

Connor 2 Sep 28, 2022
Parser for RISC OS Font control characters in Python

RISC OS Font control parsing in Python This repository contains a class (FontControlParser) for parsing font control codes from a byte squence, in Pyt

Charles Ferguson 1 Nov 2, 2021
Simple control of Thorlabs Elliptec devices from Python.

Elliptec Simple control of Thorlabs Elliptec devices. No docs yet » Get started · Report a bug · Request a feature About The Project ThorLabs Elliptec

David Roesel 8 Sep 22, 2022
A simple python project which control paint brush in microsoft paint app

Paint Buddy In Python A simple python project which control paint brush in micro

Ordinary Pythoneer 1 Dec 27, 2021
Projeto-menu - This project is designed to learn more about control mechanisms in Python programming

Projeto-menu - This project is designed to learn more about control mechanisms in Python programming

Henrik Ricarte 2 Mar 1, 2022
Structural basis for solubility in protein expression systems

Structural basis for solubility in protein expression systems Large-scale protein production for biotechnology and biopharmaceutical applications rely

ProteinQure 16 Aug 18, 2022
LSO, also known as Linux Swap Operator, is a software with both GUI and terminal versions that you can manage the Swap area for Linux operating systems.

LSO - Linux Swap Operator Türkçe - LSO Nedir? LSO, diğer adıyla Linux Swap Operator Linux işletim sistemleri için Swap alanını yönetebileceğiniz hem G

Eren İnce 4 Feb 9, 2022
ASVspoof 2021 Baseline Systems

ASVspoof 2021 Baseline Systems Baseline systems are grouped by task: Speech Deepfake (DF) Logical Access (LA) Physical Access (PA) Please find more de

null 91 Dec 28, 2022
Test reproducibility of leiden/umap on different systems

Demonstrate that UMAP and Leiden analysis is not reproducible between different cpu architectures.

Gregor Sturm 2 Oct 16, 2021
EasyBuild is a software build and installation framework that allows you to manage (scientific) software on High Performance Computing (HPC) systems in an efficient way.

EasyBuild is a software build and installation framework that allows you to manage (scientific) software on High Performance Computing (HPC) systems in an efficient way.

EasyBuild community 87 Dec 27, 2022
Demo code for "Logs in distributed systems" webinar

Hexlet Logs Demo Пререквизиты docker-compose python3 Учетка в DataDog Базовое понимание, что такое логи (можно почитать гайд

Anton Markelov 1 Dec 1, 2021
Cylc: a workflow engine for cycling systems

Cylc: a workflow engine for cycling systems. Repository master branch: core meta-scheduler component of cylc-8 (in development); Repository 7.8.x branch: full cylc-7 system.

The Cylc Workflow Engine 205 Dec 20, 2022
Unzip Japanese Shift-JIS zip archives on non-Japanese systems.

Unzip JP GUI Unzip Japanese Shift-JIS zip archives on non-Japanese systems. This script unzips the file while converting the file names from Shift-JIS

Emile Bangma 9 Dec 7, 2022