Closed B-LIE closed 1 year ago
Yes, there are a few different ways the systems are stored. TransferFunctions constsis of a matrix of either SisoTf types storing two polynomials or SisoZpk storing a gain and a vector each for pole/zero locations. Then there is StateSpace storing four matrices, and some other versions of special state spaces as well.
The extra ;;
is (I think) from normal matrix plotting since maybe version 1.8?
julia> (rand(1, 1), rand(2, 1), rand(1, 2))
([0.1785620036939919;;], [0.6089651884889287; 0.7791505974417174;;], [0.494261101514058 0.47886582862763305])
It denotes that there is a second dimension when it is not otherwise clear from the data, i.e. for a 2x1 size matrix to distinguish it from a 2-length vector.
Why was this puzzling? Transfer functions and statespace models have quite different properties when it comes to computation and it makes sense to be able to represent both. For one, transfer functions can represent non-proper systems, whereas statespace models (without mass matrix) can not. The computations involved in computing, e.g., frequency responses are also vastly different for the two different representations.
I also encourage you to actually look at the source code, it would trivially answer this kind of question, a big benefit of using open-source software ;)
Why was this puzzling?
"Puzzling" for one with background in MATLAB's ControlToolbox - where ssdata
responds with A,B,C,D matrices irrespective of which constructor was used. Also, my impression is that numerically speaking, it is better with storing models in State Space form, so I thought that was done. The documentation of ssdata
uses generic sys
as argument.
But you are right - I shouldn't assume that ControlSystems.jl has exactly the same use as MATLAB's toolbox.
As you say, storing the system as a transfer function has some advantages in that transfer functions can handle infinite dimensional systems (such as with the delay
) function. The delay is, of course, a representation of the simple advection equation $\frac{\partial x}{\partial t} = -v\frac{\partial x}{\partial z}$ with $z \in [0,L]$ leading to Laplace transform $\exp{(-\tau s)}$ with $\tau = L/v$. Many other fancy transfer functions can be found which are not fractions of polynomials, such as in various heat exchangers. It would be cool if ControlSystems could allow for such types by multiplying a transfer function with other functions (such as those given by linear PDEs), but there is perhaps not a big "market" for this :-o.
Anyways, my confusion was due to MATLAB experience.
I also encourage you to actually look at the source code
I tried to open the ControlSystems.jl source code in GitHub, but didn't really find ssdata
.
However, utility function Base.functionloc
found it. [I've had experience in the past where Base.functionloc
gives an error message, though.]
I can recommend the function dump
to inspect the structure of any composed object
julia> H = tf(1, [1,1]);
julia> dump(H)
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Int64}}
matrix: Array{ControlSystemsBase.SisoRational{Int64}}((1, 1))
1: ControlSystemsBase.SisoRational{Int64}
num: Polynomials.Polynomial{Int64, :x}
coeffs: Array{Int64}((1,)) [1]
den: Polynomials.Polynomial{Int64, :x}
coeffs: Array{Int64}((2,)) [1, 1]
timeevol: Continuous Continuous()
The macro @edit
is also useful in locating the source of the code that is being called
julia> @edit ssdata(H)
As a side, we represent time-delay systems as an LFT of a statespace system with a time-delay block:
julia> tf(1, [1,1]) * delay(2.0)
DelayLtiSystem{Float64, Float64}
P: StateSpace{Continuous, Float64}
A =
-1.0
B =
0.0 1.0
C =
1.0
0.0
D =
0.0 0.0
1.0 0.0
Continuous-time state-space model
Delays: [2.0]
you can read more about this in the paper https://github.com/JuliaControl/CDC2021/blob/master/CDC2021.pdf
Also, my impression is that numerically speaking, it is better with storing models in State Space form, so I thought that was done.
For many things yes, but not for everything, we thus allow the user to choose the representation. We also store zpk
models as separate arrays of zeros poles and gain, which is preferable in some situations.
We have a whole page in the documentation dedicated to these choices https://juliacontrol.github.io/ControlSystems.jl/stable/man/numerical/
I'm puzzled by the following:
This indicates that the system is stored in the format it was created in, and not in state space form?
Another observation...
ssdata
creates two extra, blank lines for the outputs,;;
for the C matrix and the D matrix. Why? (I've seen similar things in other Julia code, too, and it puzzles me :-o )