# ControlSystems -- root locus, etc.?

**URL:** <https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706>\
**Category:** Modelling & Simulations\
**Tags:** control\
**Created:** [September 8, 2018, 4:33pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706 "2018-09-08T16:33:53Z")\
**Posts on this page:** 15\
**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:** [September 8, 2018, 4:33pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/1 "2018-09-08T16:33:53Z")

</div>

I was just playing around with the ControlSystems package. One question and one observation…  
Q: is there a function for plotting root locus? Of course, it is easy to do this in a for loop, but if there is a function, my notebook would look nicer…  
O: I tested the tzero() function. It struck me that it was really slow… at least compared to the pole() function… I never experienced waiting for the answer in MATLAB… or is my memory failing me?

---

<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:** [September 8, 2018, 4:52pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/2 "2018-09-08T16:52:14Z")

</div>

rlocusplot  
Did you measure time with Benchmartools? If you ran it once only, you experienced the initial compilation time.

---

<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:** [September 8, 2018, 5:54pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/3 "2018-09-08T17:54:11Z")

</div>

Thanks for super fast response. I’ll check rlocusplot later in the weekend. [I assume that K can be both negative and positive…]

Didn’t benchmark tzero. I just observed that the pole command was super snappy, while tzero was slow in comparison. Will check again.

---

<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:** [September 8, 2018, 10:28pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/4 "2018-09-08T22:28:29Z")

</div>

A longer compilation time for finding transmission zeros is expected since it’s a much more complicated process. It involves several qr factorization and generalized eigenvalues decompositions whereas finding system poles is essentially only a single eigenvalue calculation. tzero should however be very fast after the very first call.

---

<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:** [September 9, 2018, 12:34pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/5 "2018-09-09T12:34:42Z")

</div>

`rlocusplot`– is the documentation clear?

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/c/cc10a4cc0739309e9b443b69a76ed05da7839a77.png)  
I was hoping that a state space description qualified as an `LTISystem` (…which I don’t know what is, since the documentation is not really indexed – one of the reasons why I prefer printed documents…)

Here is what I get:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/c/bcb25f0079d310d65f49362cbe8b3ec8140b8b1f.png)

What do I do wrong? Of course, coding a “root locus” function is straightforward and gives freedom, but is somewhat messy – so I’d prefer to use the built-in function. Here is the result of my “messy” code:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/4/042fa8bce2d4fc058a4737d11b47d2c4153e6efc.jpeg)

---

<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:** [September 9, 2018, 12:54pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/6 "2018-09-09T12:54:41Z")

</div>

That seems like a bug. Feel free to open an issue. In the meantime, you can use `tf(sys)` to convert your ss to a tf before calling rlocusplot.

---

<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:** [September 9, 2018, 2:18pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/7 "2018-09-09T14:18:30Z")

</div>

Hi, again: I’m not very computer/GitHub savvy… Do I need a GitHub account to “open an issue”? I have several issues…

- Yes, `rlocusplot` produces something if the system is given as transfer function (`tf(sys_org)`). It should, of course, produce the same result with a state space system. Function `rlocusplot` also fails if I use argument `zpg(sys_org)` … which is also a bug.
- The produced plot is very incorrect… In fact, I don’t know what the result is – doesn’t look anything like my plot (which is correct…). Contrast the plot from `rlocusplot` with my plot above…:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/0/0091f2abf61168678bc97986aef7081ac341f9f7.png)  
… or… zoomed in:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/1/617842e7da5f1374a167973c7c611b34715ad37b.jpeg)

---

<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:** [September 9, 2018, 2:33pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/8 "2018-09-09T14:33:16Z")

</div>

Well, I’m afraid I can’t really help you if you only post images, I would need to have the code (in text) to figure out what is going on.

I opened an issue.

PS. Don’t forget to [quote-code-with-backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530)

---

<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:** [September 9, 2018, 2:43pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/9 "2018-09-09T14:43:49Z")

</div>

Yes, I understand that you need numbers. Is this ok?

```julia
julia> sys_org
ControlSystems.StateSpace{Float64,Array{Float64,2}}
A = 
  4.37956 209.205
 -0.0357143 -2.0  
B = 
 2.09205
 0.0    
C = 
 1.0 0.0
D = 
 0.0

Continuous-time state-space model

julia> rlocusplot(tf(sys_org), linspace(-1,8,50))

```

Is this ok? This produces a plot similar to the one I included above…

[The matrices are generated by a Julia interface to a nonlinear reactor model in OpenModelica, which is run from Julia, and linearized from Julia – using linearization algorithms in OpenModelica. That’s why they are not “nice numbers”…]

---

<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:** [September 9, 2018, 2:45pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/10 "2018-09-09T14:45:37Z")

</div>

It would be far easier if the code was such that I could copy-paste it into the terminal and not have to type it all by hand.

---

<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:** [September 9, 2018, 3:14pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/11 "2018-09-09T15:14:52Z")

</div>

OK. Is this fine?

```julia
julia> using ControlSystems
julia> A = [4.38 209; -0.036 -2]; 
julia> B = [2.09; 0];
julia> C = [1 0];
julia> D = 0;
julia> sys = ss(A,B,C,D);
julia> rlocusplot(tf(sys), linspace(-1,8,50))

```

---

<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:** [September 13, 2018, 5:51am UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/12 "2018-09-13T05:51:17Z")

</div>

I can’t seem to figure out what is going wrong. Our old implementation works alright, but the new adaptive stepsize implementation seems to do the wrong thing in this case. I’ll open an issue about it, but do not have time to resolve it now 😟

---

<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:** [September 13, 2018, 6:56am UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/13 "2018-09-13T06:56:20Z")

</div>

No problem. I’ll try to write my own `rootlocusplot` (as opposed to `rlocusplot`) when I have time (probably not until early October during my fall “vacation” to Hungary and Vienna) - then if you like some of it, you can pick from it.

---

<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:** [September 15, 2018, 3:27pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/14 "2018-09-15T15:27:07Z")

</div>

I needed to do the root locus plot, and created my own function `rootlocusplot()`…

 ![image](https://global.discourse-cdn.com/julialang/original/3X/2/7/27afa031d29d6c4d6627383d8599201cf9ea7e87.jpeg)

---

<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:** [September 15, 2018, 3:36pm UTC](https://discourse.julialang.org/t/controlsystems-root-locus-etc/14706/15 "2018-09-15T15:36:53Z")

</div>

Here is my function, in case it is of use:

```julia
function rootlocusplot(P::LTISystem;k=linspace(0,1,20),G=I,CGrad=:plasma_r,MSC=:black)
    #
    # Code by Bernt Lie
    # University of South-Eastern Norway
    # v.0.1, September 15, 2018
    #
    # P: LTI plant
    # k: scalar gain range
    # G: gain matrix, u = k*G*(ref-y)
    # CGrad: color gradient for roots over k
    # MSC: marker stroke color for open loop roots
    %
    A = P.A
    B = P.B*G
    C = P.C
    D = P.D*G
    #
    e0 = eigvals(A)
    tz = tzero(ss(A,B,C,D))
    #
    Eig = zeros(Complex,(length(k),2))
    if length(D)==1
        for (i,ki) in enumerate(k)
            Ac = A - ki*B*((1 + ki*D)\C);
            Eig[i,:] = eigvals(Ac)
        end
    else
        for (i,ki) in enumerate(k)
            Ac = A - ki*B*((I + ki*D)\C);
            Eig[i,:] = eigvals(Ac)
        end
    end
    #
    scatter(real(tz),imag(tz),shape=:o,ms=6,msc=MSC,mc=:white,label="Transmission zeros")
    #
    scatter!(real(Eig)[:,1],imag(Eig)[:,1],shape=:x,ms=3,mc=CGrad,mz=k,label="")
    scatter!(real(Eig)[:,2],imag(Eig)[:,2],shape=:x,ms=3,mc=CGrad,mz=k,label="")
    #
    scatter!(real(e0),imag(e0),shape=:x,ms=6,mc=MSC,label="Open loop roots")
    #
    plot!(title="Root locus plot")
    plot!(xlabel="real(root)")
    plot!(ylabel="imag(root)")
end

```

The function works for MIMO systems and is based on u = k\cdot G\cdot (r-y) where r is some reference, G is a chosen/known gain matrix, and k is specified in some range.  
It would have been nice to put a k next to the color bar to indicate what the color bar is, but I don’t know how to do that.

I have assumed that the system does not have time delay. The function should work for the case D\neq 0, I think.
