I am trying out the package ControlSystemIdentification.

It looks very good, each step very well explained!

One question: In the example Temperature control · ControlSystemIdentification Documentation you are using a chirp signal for identifying the system.

Isn’t it more common to use a pseudo-random sequence? How could I do the same task using a pseudo-random sequence?

Thanks :slight_smile:

It depends on whom you’re asking. A PRBS signal works fine for the heating element in the example, but it would be a poor choice for anything mechanical. I usually prefer chirp signals for a lot of reasons.

  1. It’s easy to select the frequency content
  2. You can “see” the frequency response in the live data during the experiment, and abort early if you determine that the amplitude is too high or too low etc. This is particularly effective for mechanical systems.

The input is just an array, you can let the array represent any signal. A PRBS signal can be obtained by sign.(randn(1, 100)), possibly with some filtering applied before the sign to shape the frequency contents.

1 Like

Extra question regarding the given example: Why are you using an adjoint for u?

u = sign.(sin.((0:0.01:20) .^ 2))' # sample a control input for identification

Time is in the second dimension by the convention of the JuliaControl ecosystem.

julia> data.u
1×2001 adjoint(::Vector{Float64}) with eltype Float64:
 0.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  -1.0  -1.0  -1.0

julia> data.y
1×2001 Matrix{Float64}:
 0.188729  0.0570035  0.158437  0.118835  …  0.337283  0.171856  0.09693

u is an adjoint and y a Matrix… Why is not both a vector?

Where is this convention defined or explained?

Here you do not mention any adjoint: Identification data · ControlSystemIdentification Documentation . Is it important to use an adjoint for u?

In the docs for iddata

If the time-series are multivariate, time is in the last dimension.

No, in this case, you could have used transpose, reshape or permutedims as well.

It doesn’t matter for the internals of ControlSystemIdentification as long as the dimensions are correct.

In fact, this piece of information is available in a lot of places throughout the documentation

In the docs for lsim:

At the page Noteworthy Differences from other Languages:

1 Like

Well, I still do not understand why u has to be an adjoint… You say time has to be in the second dimension, but there is no time information in u …
u is a vector with only one dimension…

I am only electrical engineer and no mathematician. Some more explanation for simple engineers would be nice…


this is interpreted as an input array with one input signal of 3 time steps.

It does not have to be, it just has to have the size (num_input, num_timepoints)

But why do you make it an adjoint in the example if this is not required? That is confusing.

I give it the right shape, as described by the documentation. The fact that Julia wraps it in an Adjoint wrapper is completely irrelevant. If you don’t want to use an adjoint, don’t, if you do, that’s also fine. I don’t see what the problem is here, the example works and produces the intended result.

1 Like

So you would say that in a 2 dimensional matrix rows are the first dimension and columns the second dimension?
OK, you say it works, but I want to understand what you are doing and why.

I found this information online:
" You take the number of rows from the first matrix (2) to find the first dimension, and the number of columns from the second matrix (2) to find the second dimension."

OK, taking this into account the vector u where each element differs in time should be a row vector. A default vector in Julia is a column vector, therefore you make it an adjoint.

OK, I start understand why you are doing this. :slight_smile:
I still not understand the difference between and adjoint and a row vector, but that would be a different topic.

Created a pull request: Update types.jl by ufechner7 · Pull Request #120 · baggepinnen/ControlSystemIdentification.jl · GitHub