Search code examples
pythonpython-3.xmatlabtransfer-functionpython-control

How can I specify Time Delays in Linear Systems in Python?


this was asked 7 years ago in this thread:

How to define LTI systems with Time delay in Scipy?

The answer is outdated or at least I don't know how to make it work, and I would like to know if there is a way of doing this in the present.

I want to create a transfer function that looks like this, where s equals 0.1 which is the time delay.

In matlab I would do something like this:

H=tf(1,'InputDelay',0.1);

s=tf('s');
G=1/(s+1);
Q=1+0.5*s+2/s;

so that then I can operate with the transfer functions as follows:

M=feedback(Q*G,H);
M=minreal(M);
display(M);

I would like to know if there is an equivalent in python. So that I don't have to use symbolic expressions which limit the versatility of the code.

with symbolic expressions it would look like this:

s = sym.symbols('s')
G = 1/(s+1)
Q = 1+0.5*s+2/s
H = sym.exp(-0.1*s)
# Cálculo de la función de transferencia global
M = Q*G/(1+Q*G*H)
M = sym.simplify(M)
sym.pprint(M)

I thought of using numpy or sympy exp but neither works:

s = ct.tf('s')
H = np.exp(-0.1*s)

Output:

TypeError: loop of ufunc does not support argument 0 of type TransferFunction which has no callable exp method

Sympy gives this:

SympifyError: Sympify of expression 'could not parse '-0.1 s------ 1'' failed, because of exception being raised: SyntaxError: invalid syntax (<string>, line 1)

I've googled for everything I could think of and couldn't find any documentation on this, sorry for my ignorance and poor english. Thank you in advance!


Solution

  • As far as I know there are no widely supported control libraries for Python which support delays in the same way as the Matlab control toolbox does. My students and I have been working on a solution for this for a while and hope to package it up for release to pypi this year.

    The repository with our code is here and the object which allows the kinds of manipulations you're talking about using an internal delay representation is defined in InternalDelay.py.

    One slight problem with your example is that your Q is not physically realisable, which causes some errors in our library.

    The following code will produce a step response for your closed loop system, showing the effect of adding a delay. I've also used only PI control instead of PID to keep the controller physically realisable.

    from utils import InternalDelay, tf
    import matplotlib.pyplot as plt
    import numpy as np
    
    s = tf([1, 0], 1)
    G = 1/(s + 1)
    Q = 1 + 2/s
    H = tf(1, 1, deadtime=0.1)
    G = InternalDelay(G)
    Q = InternalDelay(Q)
    H = InternalDelay(H)
    one = InternalDelay(tf(1, 1))
    
    M = Q*G/(one + Q*G)
    Mdelay = Q*G/(one + Q*G*H)
    
    t = np.linspace(0, 10, 5000)
    
    y = M.simulate(lambda t: [1], t)
    ydelay = Mdelay.simulate(lambda t: [1], t)
    
    plt.plot(t, y, t, ydelay)
    plt.legend(['Delay-free', 'Delay=0.1s'])
    plt.axhline(1)
    

    example