# Using symbolic variables in control systems

**URL:** <https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810>\
**Category:** Modelling & Simulations\
**Tags:** question, controlsystems\
**Created:** [February 6, 2024, 2:19pm UTC](https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810 "2024-02-06T14:19:15Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [February 6, 2024, 2:19pm UTC](https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810/1 "2024-02-06T14:19:15Z")

</div>

Is it possible to use symbolic variables when defining a discrete time control system?

The following code fails:

```julia
using ControlSystemsBase, ModelingToolkit

@parameters Ts

# Ts = 0.01
Ku = 200/5e6
K2 = 5e6
num = [Ku * Ts]
den = [1, -1]
P = tf(num, den, Ts) # plant

```

with the error message:

```julia
ERROR: LoadError: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
 [1] Discrete
   @ ~/.julia/packages/ControlSystemsBase/4kZY4/src/types/TimeEvolution.jl:9 [inlined]
 [2] Discrete
   @ ~/.julia/packages/ControlSystemsBase/4kZY4/src/types/TimeEvolution.jl:19 [inlined]
 [3] tf(num::Vector{Num}, den::Vector{Int64}, Ts::Num)
   @ ControlSystemsBase ~/.julia/packages/ControlSystemsBase/4kZY4/src/types/tf.jl:49
 [4] top-level scope
   @ ~/repos/WindSpeedEstimators/mwes/mwe_09.jl:10
 [5] include(fname::String)
   @ Base.MainInclude ./client.jl:489
 [6] top-level scope
   @ REPL[2]:1
in expression starting at /home/ufechner/repos/WindSpeedEstimators/mwes/mwe_09.jl:10

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [February 6, 2024, 2:24pm UTC](https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810/2 "2024-02-06T14:24:54Z")

</div>

Found the answer myself: Yes, it is possible using: [GitHub - JuliaControl/SymbolicControlSystems.jl: C-code generation and an interface between ControlSystems.jl and SymPy.jl](https://github.com/JuliaControl/SymbolicControlSystems.jl)

This works:

```julia
using ControlSystemsBase, ModelingToolkit, SymbolicControlSystems

@vars Ts Ku K2

num = [Ku * Ts]
den = [1, -1]
P = tf(num, den, Ts) # plant

```

and has as output:

```julia
TransferFunction{ControlSystemsBase.Discrete{SymPy.Sym}, ControlSystemsBase.SisoRational{SymPy.Sym}}
  (Ku*Ts)
-----------
(1)z + (-1)

Sample Time: Ts (seconds)
Discrete-time transfer function model

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [February 6, 2024, 2:41pm UTC](https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810/3 "2024-02-06T14:41:40Z")

</div>

But the following code fails:

```julia
using ControlSystemsBase, ModelingToolkit, SymbolicControlSystems

@vars Ts Ku K2

num = [Ku * Ts]
den = [1, -1]
P = tf(num, den, Ts) # plant
C = K2
sys = feedback(P, C)

```

with the error message:

```julia
[Info: Precompiling SymbolicControlSystems [886cb795-8fd3-4b11-92f6-8071e46f71c5]
[Info: Skipping precompilation since __precompile__ (false). Importing SymbolicControlSystems [886cb795-8fd3-4b11-92f6-8071e46f71c5].
ERROR: LoadError: PyError ($(Expr(:escape, :(ccall(#= /home/ufechner/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'sympy.polys.polyerrors.GeneratorsNeeded'>
GeneratorsNeeded("Cannot initialize from 'dict' without generators")
  File "/home/ufechner/.julia/conda/3/x86_64/lib/python3.10/site-packages/sympy/polys/polytools.py", line 182, in __new__
    return cls._from_expr(rep, opt)
  File "/home/ufechner/.julia/conda/3/x86_64/lib/python3.10/site-packages/sympy/polys/polytools.py", line 312, in _from_expr
    return cls._from_dict(rep, opt)
  File "/home/ufechner/.julia/conda/3/x86_64/lib/python3.10/site-packages/sympy/polys/polytools.py", line 249, in _from_dict
    raise GeneratorsNeeded(

Stacktrace:
  [1] pyerr_check
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/exception.jl:75 [inlined]
  [2] pyerr_check
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/exception.jl:79 [inlined]
  [3] _handle_error(msg::String)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/exception.jl:96
  [4] macro expansion
    @ ~/.julia/packages/PyCall/1gn3u/src/exception.jl:110 [inlined]
  [5] #107
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:43 [inlined]
  [6] disable_sigint
    @ ./c.jl:473 [inlined]
  [7] __pycall!
    @ ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:42 [inlined]
  [8] _pycall!(ret::PyCall.PyObject, o::PyCall.PyObject, args::Tuple{SymPy.Sym}, nargs::Int64, kw::Ptr{Nothing})
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:29
  [9] _pycall!
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:11 [inlined]
 [10] (::PyCall.PyObject)(args::SymPy.Sym)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/pyfncall.jl:86
 [11] tf(sys::SymPy.Sym, h::ControlSystemsBase.Discrete{SymPy.Sym})
    @ SymbolicControlSystems ~/.julia/packages/SymbolicControlSystems/wPScY/src/SymbolicControlSystems.jl:86
 [12] convert(::Type{TransferFunction{…}}, G::TransferFunction{ControlSystemsBase.Discrete{…}, ControlSystemsBase.SisoRational{…}})
    @ ControlSystemsBase ~/.julia/packages/ControlSystemsBase/4kZY4/src/types/conversion.jl:37 [inlined]
 [13] _promote
    @ ./promotion.jl:370 [inlined]
 [14] promote
    @ ./promotion.jl:393 [inlined]
 [15] feedback(sys1::TransferFunction{…}, sys2::SymPy.Sym; kwargs::@Kwargs{})
    @ ControlSystemsBase ~/.julia/packages/ControlSystemsBase/4kZY4/src/types/Lti.jl:33
 [16] top-level scope
    @ ~/repos/WindSpeedEstimators/mwes/mwe_09.jl:12
 [17] include(fname::String)
    @ Base.MainInclude ./client.jl:489
 [18] top-level scope
    @ REPL[1]:1
in expression starting at /home/ufechner/repos/WindSpeedEstimators/mwes/mwe_09.jl:12
Some type information was truncated. Use `show(err)` to see complete types.

```

Any idea?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [February 6, 2024, 3:11pm UTC](https://discourse.julialang.org/t/using-symbolic-variables-in-control-systems/109810/4 "2024-02-06T15:11:41Z")

</div>

Depending on what you want to do, you might not need SymbolicContorlSystems. You can pass `Ts = 1` here `tf(num, den, 1)` if you’re only interested in algebraic manipulations. The only time the `Ts` there is relevant is when you need to compute the response in frequency or time.
