# ControlSystems -- transfer functions with delay?

**URL:** <https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003>\
**Category:** Performance\
**Tags:** control\
**Created:** [March 26, 2021, 10:16am UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003 "2021-03-26T10:16:00Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 26, 2021, 10:16am UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/1 "2021-03-26T10:16:00Z")

</div>

From the documentation:

[`ControlSystems.tf`](https://juliacontrol.github.io/ControlSystems.jl/stable/lib/constructors/#ControlSystems.tf) — Function.

`sys = tf(num, den, Ts=0), sys = tf(gain, Ts=0)`

→ Is it possible to define a time delay for functions `tf` and `zpk`?

I’m trying to “sell” Julia to a friend, and he currently works with a system that has a time delay.

→ If not possible, should I propose to use a Padé approximation?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 26, 2021, 12:15pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/2 "2021-03-26T12:15:39Z")

</div>

The package has a `delay()` function. See examples [here](https://github.com/JuliaControl/ControlSystems.jl).

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 26, 2021, 1:21pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/3 "2021-03-26T13:21:27Z")

</div>

Thanks! That looks perfect – can also be used when the model is posed in the time delay :-).

# 

Shouldn’t this be listed under Constructors? I didn’t find it in the documentation.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 26, 2021, 2:26pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/4 "2021-03-26T14:26:51Z")

</div>

Follow-up… `lsimplot` works _without_ time delay, but doesn’t seem to work _with_ time delay??

```julia
using Plots, ControlSystems, DataInterpolations
#
sys = tf([2],[0.5,1])*tf([1],[3,1])#*delay(2)
#
tval() = rand(range(2,10,length=5))
uval() = rand(range(-1,1,length=5))
#
Nchanges = 20
tvec = [tval() for i in 1:Nchanges] |> cumsum
uvec = [uval() for i in 1:Nchanges]
uinterp = ConstantInterpolation(uvec,tvec)
u(x,t) = uinterp(t)
#
tfin = tvec[end]
plot(t->u(0,t),0,tfin,label="u_exp")

```

gives the “experimental input”:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/1/61baed90c5228a6256882f18940f1f107febf093.png)

I can finally simulate the system with experiment:

```julia
tsim = range(0,tfin,length=200)
lsimplot(sys,u,tsim)

```

leading to:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/a/2ae7afe02ed852ba7adb7b9ae5f879e810748cf6.png)

Here I have started with default states at zero.

If I change the line `sys = tf([2],[0.5,1])*tf([1],[3,1])#*delay(2)` to `sys = tf([2],[0.5,1])*tf([1],[3,1])*delay(2)`, I can still do `stepplot` of the system, but `lsimplot` with input as above leads to zero output for all time…

_Questions_:

1. How can I make `lsim` work with time delay?
2. What initial states could I possibly choose when I have time-delay? Would it be reasonable to assume that `x0` refers to the states of the system _without_ time delay, and that no states should be chosen for the (discretization of) time delay?

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [March 27, 2021, 4:08pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/5 "2021-03-27T16:08:47Z")

</div>

So one thing is that the `lsim` called for a delayed system seems to expect `u` that only depends on time, and if you send a function that takes two variables it assumes it is the inplace version `u(uout, t) = uout .= f(t)` and this would result in the `uout` sent in during the simulation to always be 0, which explains the output being 0.

So instead doing `u(t) = uinterp(u)` should solve the first problem I think.

This seems very confusing since it for non-delayed systems is `u(x,t)` as you used, so maybe something should be changed here.

For the states I’m pretty sure the internal states would be the same with a delayed input in this case, x’(t)=Ax(t)+Bu(t-tau), though that might depend on how delay is multiplied into the rest.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 27, 2021, 4:37pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/6 "2021-03-27T16:37:12Z")

</div>

> [@albheim](#):
>
> So instead doing `u(t) = uinterp(u)` should solve the first problem I think.

Thanks for your suggestions and explanation (I didn’t understand it completely, though).

Do you mean I should do `u(t) = uinterp(t)`? Or do you mean `u(t) = uinterp(u)`? Remember: `uinterp` is an interpolation function with `t` as argument, _not_ with `u` as argument.

If you mean that I should change `u(x,t) = uinterp(t)` to `u(t) = uinterp(t)`, then the statement:

```julia
lsimplot(sys,uinterp,tsim)

```

should also work… but it doesn’t: it throws a lengthy error message.

It would indeed be confusing to the user if in `lsim`, `u` should have arguments `u(x,t)` when there is no time delay, and `u(t)` when there is time delay. If this is the case, then that would certainly be confusing.

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [March 27, 2021, 5:28pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/7 "2021-03-27T17:28:00Z")

</div>

Yeah I meant `u(t)=uinterp(t)` which works for me when copying your example. The reason that `lsimplot(sys, uinterp, tsim)` does not work is that `uinterp` is an AbstractVector type, and lsim checks the type of u and depending on type will handle it slightly differently. Since it is interpreted as a vector type it is called like a vector which causes an error. Not sure if this is intended, have never used the Interpolation types before so not sure how they interact with stuff.

Internally it looks like this

```julia
function lsim(sys::DelayLtiSystem{T,S}, u, t::AbstractArray{<:Real}; x0=fill(zero(T), nstates(sys)), alg=MethodOfSteps(Tsit5()), kwargs...) where {T,S}
    # Make u! in-place function of u
    u! = if isa(u, Number) || isa(u,AbstractVector) # Allow for u to be a constant number or vector
        (uout, t) -> uout .= u
    elseif DiffEqBase.isinplace(u, 2) # If u is an inplace (more than 1 argument function)
        u
    else # If u is a regular u(t) function
        (out, t) -> (out .= u(t))
    end
    _lsim(sys, u!, t, x0, alg; kwargs...)
end

```

where if it was handled under the last else clause it should have been fine to call it with uinterp, but as it is now it is caught by the first clause and errors. While the function `u(t)=uinterp(t)` will be hendled by the third clause and should hopefully work.

Yes it is weird as it is now, and I have opened an issue regarding this so will hopefully be looked over.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 27, 2021, 5:40pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/8 "2021-03-27T17:40:51Z")

</div>

Thanks for following it up. The arguments for `u` is not documented in the documentation. And even if they were, I agree with you that they should be the same irrespective of a delay or not.

Also, it would make things clearer if the documentation states whether `x0` includes states for the delay approximation, or not. Probably `x0` should not include delay states… but I haven’t thought through what they should be if they are automatically chosen.

Another problem: named argument `x0` in `lsim` doesn’t work. So if I do `lsim(...; x0 = [1,1])`, I get an error message. However, if I do `lsim(...; x = [1,1])` _then_ the simulation runs.

Could it be that the named argument has been changed from `x0` to `x` without updating the documentation?

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [March 27, 2021, 8:01pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/9 "2021-03-27T20:01:25Z")

</div>

Checking `help?> lsim` in the repl shows me this information, though it seems like it is missing from the online docs. Have added that to the issue about lsim for delay system.

Looking at the code it seems x0 is the name and it does not include the delay states, the delay states seems to be initialized to zero if I understand correctly.

Does the simulation do anything different with `x=[1, 1]`? Because there is a catchall kwarg so I assume it is just the same as not sending anything in. The problem with the `x0=[1,1]` is that the dispatch is not perfectly made so it does not find the method since you make an int array, try `x0=[1.0, 1]` and it should work. Will also add this to the rest of the issues you found and hopefully it can be fixed soon.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 27, 2021, 8:10pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/10 "2021-03-27T20:10:01Z")

</div>

Will test to use floats in `x0`. Problem is I set `x0 = zeros(2)`, and then setting `x0 = x0`, the code complained that the “symbol” didn’t find a zero, or something really weird.

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [March 27, 2021, 8:11pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/11 "2021-03-27T20:11:28Z")

</div>

Yeah, I got that too. If you try with only `lsim` and not `lsimplot` it seems to be slightly more reasonable error message, so I assume that is from the plottingrecepies being what they are (dark magic).

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [March 27, 2021, 8:23pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/12 "2021-03-27T20:23:01Z")

</div>

You are right. The problem with keyword `x0` is only in `lsimplot`… And your interpretation of me using `x` is probably correct – that `lsimplot` just neglects it.

To sum up, I think there are the following two or three problems with `lsim`/`lsimplot`:

- The weird thing that `u` is supposed to have arguments `u(x,t)` when there is no delay, and that it is supposed to be `u(t)` when there is delay. This difference doesn’t make much sense to me, and in my view it is better if it is `u(x,t)` in both cases or `u(t)` in both cases.
- The problem of keyword argument `x0` giving error message in `lsimplot`, possibly due to a plot recipe problem.
- Some uncertainty about what `x0` means when there is a delay. Most likely, it means the finite states (of system without delay). The interesting thing is what value is chosen for the “delay states” when `x0` is specified to be different from zero. If the delay is assumed to be on the input, the delay states should probably have the same values as the initial time inputs, or something.

---

<div class="post-metadata">

**Author:** ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)\
**Post date:** [March 27, 2021, 9:24pm UTC](https://discourse.julialang.org/t/controlsystems-transfer-functions-with-delay/58003/13 "2021-03-27T21:24:24Z")

</div>

Yeah, thanks for noting all this. Have linked this thread in the issue [here](https://github.com/JuliaControl/ControlSystems.jl/issues/460), feel free to add stuff there also.
