Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add controller function #512

Merged
merged 3 commits into from
May 28, 2021
Merged

add controller function #512

merged 3 commits into from
May 28, 2021

Conversation

baggepinnen
Copy link
Member

This is yet another small PR that aims to break up the quite large #467 into smaller chunks.
This PR adds a function controller that takes state feedback and observer gains and returns the controller

@JuliaControlBot
Copy link

Something failed when generating plots. See the log at https://github.com/JuliaControl/ControlExamplePlots.jl/runs/849897747?check_suite_focus=true for more details.

@codecov
Copy link

codecov bot commented May 17, 2021

Codecov Report

❗ No coverage uploaded for pull request base (dev@c44544a). Click here to learn what that means.
The diff coverage is n/a.

Impacted file tree graph

@@          Coverage Diff           @@
##             dev     #512   +/-   ##
======================================
  Coverage       ?   84.89%           
======================================
  Files          ?       31           
  Lines          ?     3190           
  Branches       ?        0           
======================================
  Hits           ?     2708           
  Misses         ?      482           
  Partials       ?        0           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c44544a...5343eab. Read the comment docs.

@olof3
Copy link
Contributor

olof3 commented May 17, 2021

This seems like something that could occasionally be convenient.

I'm a little bit skeptical to using such a generic name for a function like this, though.
Wouldn't it be good with a more descriptive name, both to have a slightly better idea of what the function is about, and also if the user would like to introduce a variable called controller for example.

I'd say that sscontroller is slightly better, but there are probably even better alternatives.

Hopefully the corresponding predictor method could be renamed accordingly as well.

@baggepinnen
Copy link
Member Author

The most descriptive name I can come up with is observer_statefeedback_controller, but perhaps this can be conveyed in a slighltly shorter form?
Some alternatives

  • sf_obsv_controller
  • innovation_form_controller

@olof3
Copy link
Contributor

olof3 commented May 18, 2021

Yes, I think something like that would be alright. Doesn't one sometimes say "observer-based state feedback", so obsv_sf_controller?

function controller(sys, L::AbstractMatrix, K::AbstractMatrix)
A,B,C,D = ssdata(sys)
ss(A - B*L - K*C + K*D*L, K, L, 0, sys.timeevol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this correspond to the output of the controller being -Lx?

Suggested change
ss(A - B*L - K*C + K*D*L, K, L, 0, sys.timeevol)
ss(A - B*L - K*C + K*D*L, K, -L, 0, sys.timeevol)

Copy link
Member

@albheim albheim May 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, you want the output to be Lx so that you can use negative feedback. Seems reasonable, but could maybe confuse more people than me. Maybe just state clearly that the output of the controller is Lx and not -Lx.

Or maybe that is not something that will commonly happen, since you give a tip on how to interconnect the systems it should be fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm, yeah I guess this is alright.

But what about the case when one wants the controller to treat the measurement and reference signals differently. I would say that this convention is still acceptable, although it would feel weird to add the measurement signal to the reference signal, instead of subtracting it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you introduce reference signals as well it can get very messy. In RobustAndOptimalControl.jl I'm experimenting with using a type ExtendedStateSpace which is similar to, and should probably be merged with PartitionedStateSpace, such that one can defined the controller with references as

function extended_controller(K)
    nx,nu,ny = K.nx, K.nu, K.ny
    A,B,C,D = ssdata(K)
    ss(A, B, -B, zeros(0,nx), C, D21=D, D22=-D)
end

i.e., it has two inputs, r and y. I haven't landed on how to represent everything yet though, I have also experimented with systems with named signals, ideally this should be used as well to not rely on indices everywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, not sure either what makes the most sense, so good that you are thinking about it. Yes, it seems more like a PartitionedStateSpace. We could change PartitionedStateSpace, I don't think we really need to explicitly use such a type for the delay systems.

Perhaps it won't even be needed here either with appropriate name of the signals.

Note: In this case one would have to use positive feedback?

@baggepinnen
Copy link
Member Author

I've tried to come up with a better name here. matlab has a simiar function that is named lqgreg
https://se.mathworks.com/help/control/ref/ss.lqgreg.html
They accept some kalman filter type into that which we don't do here. Also, a state feedback controller with observer does not have to be derived from an LQG problem.

There is really two aspects here, the controller has an internal observer with gain K, and a state feedback. Can we come up with a name that is not horribly long and captures both of those aspects? Perhaps obsever_controller is sufficient since an observer by definition observes the states and any controller using an observer would thus be a state feedback controller from observed states?

@olof3
Copy link
Contributor

olof3 commented May 27, 2021

I think what you said, but with a small reverse, i.e., obsv_sf_controller is fine. https://www.google.com/search?q="observer+based+state+feedback"

@baggepinnen
Copy link
Member Author

I changed both predictor and controller to

  • observer_predictor
  • observer_controller
    Looks nice and symmetric, and observer_controller kind of implies state feedback so the slight loss in descriptiveness should be fine, the docstring will clarify if any questions arise.

@baggepinnen baggepinnen merged commit b75faea into dev May 28, 2021
@baggepinnen baggepinnen deleted the controller branch May 28, 2021 05:32
@olof3
Copy link
Contributor

olof3 commented May 28, 2021

Good choices!

baggepinnen added a commit that referenced this pull request Nov 7, 2021
* Avoid unnecessarily large realization for feedback of TransferFunction (#485)

* Avoid unnecessarily large realization for feedback of TransferFunction

* Fix and added more tests.

* Change to numpoly, denpoly

* add dev brach to PR CI

* Switch u layout (#480)

* switch u layout for lsim

* Update src/timeresp.jl

Co-authored-by: Fredrik Bagge Carlson <[email protected]>

* More updates, one error in test_timeresp

* Fix tests

* Change to AbstractVecOrMat

* Catch CuArray in matrix conversion

* General zero vectors for x0 to support GPUs

* Update src/timeresp.jl

Co-authored-by: Mattias Fält <[email protected]>

* Update src/timeresp.jl

Co-authored-by: Mattias Fält <[email protected]>

* Move f outside lsim

* Remove GPU compatible x0, save for later

* Fix doctest

* add kwargs

* Remove variable and generalize type

Co-authored-by: Fredrik Bagge Carlson <[email protected]>
Co-authored-by: Mattias Fält <[email protected]>

* Gangof4 fixes (#486)

* QOL improvements for plotting

* remove spurious getindex

* update docstring

* multiple Ms in nyquist

* bugfixes

* make rings appear in all subplots

* Minor fixes to gang-of-four functionality.

* Fixes to Nyquist plots.

* Updated the nyquistplot docstring

Co-authored-by: Fredrik Bagge Carlson <[email protected]>

* add frequency in Hz to dampreport (#488)

* updates to nyquistplot (#493)

* updates to nyquistplot

* Update src/plotting.jl

Co-authored-by: olof3 <[email protected]>

* Update src/plotting.jl

Co-authored-by: olof3 <[email protected]>

Co-authored-by: olof3 <[email protected]>

* fix traces in rlocus (#491)

* fix traces in rlocus

* Update src/pid_design.jl

Co-authored-by: Albin Heimerson <[email protected]>

Co-authored-by: Albin Heimerson <[email protected]>

* let lsim handle arguments in lsimplot (#492)

* bugfix: avoid creating continuous system with Ts=0.0 (#496)

* Deactivate _preprocess_for_freqresp (#497)

until hessenberg is properly used

* allow balance when converting tf to ss (#495)

* allow balance when converting tf to ss

* use zeros(T) instead of fill(zero(T))

* Update src/types/StateSpace.jl

Co-authored-by: olof3 <[email protected]>

* Update src/types/conversion.jl

Co-authored-by: Albin Heimerson <[email protected]>

Co-authored-by: olof3 <[email protected]>
Co-authored-by: Albin Heimerson <[email protected]>

* Better handling of problematic cases for delay systems (#482)

* delay error should be correct now

* warn limit

* Add tustin c2d/d2c method (#487)

* add Tustin discretization

* no indexing after c2d

* implement f_prewarp in tustin and test vs. matlab

* fixe use wrong Ts

* f_prewarp -> w_prewarp

* w_prewarp in tests

* correct handling of x0 in lsimplot (#498)

* move eye def to framework.jl (#499)

* Fix UndefVarError: T not defined (#501)

* add axes for ss (#504)

* pi place and tests (#502)

* pi place and tests

* Fix test

* Add ending space in file

* Update numvec denvec

* Fixed error

* Update test/test_pid_design.jl

Co-authored-by: olof3 <[email protected]>

* Update test/test_pid_design.jl

Co-authored-by: olof3 <[email protected]>

* Update forms

* Fix test

* Fix test

* Update src/pid_design.jl

Co-authored-by: olof3 <[email protected]>

* Update src/pid_design.jl

Co-authored-by: olof3 <[email protected]>

* Update src/pid_design.jl

Co-authored-by: olof3 <[email protected]>

Co-authored-by: olof3 <[email protected]>

* Conver to tf in placepi (#507)

* Use nstates instead of nx in lsimplot (#508)

* Use nstates instead of nx in lsimplot

* Add predictor (#511)

* up innovation_form and add noise_model

* keep innovation_form, add predictor

* export predictor

* add hats

* updates to `obsv` (#517)

* updates to `obsv`

All computing an arbitrary number of rows in the observability matrix and accept `AbstractStateSpace`

* Update src/matrix_comps.jl

Co-authored-by: olof3 <[email protected]>

Co-authored-by: olof3 <[email protected]>

* `hz` keyword in `nyquistplot` similar to in `bodeplot` (#518)

* Fixes to place (#500)

* Add tests for place.

* Removed luenberger and exented place instead.

Co-authored-by: Fredrik Bagge Carlson <[email protected]>

* allow AbstractStateSpace in several places (#520)

* allow AbstractStateSpace in several places

* Maintain type for zpk in c2d (#522)

* maintain zpk type in c2d

* Fix type in typeconversion for c2d tf

* Fix type in c2d tf/zpk

* Remove assertion on tf/zpk SISO for c2d

* Test for c2d(zpk(..)..) unbroken

* Keep MIMO assertion c2d tf

* Add comment and fix test

* Fix test

* h to Ts

* Fix test

* remove assert

* split into methods

* Remove asserts (#523)

* Replace asserts

* add error types

* fix conversion for custom types (#514)

* fix conversion for custom types

* special numeric_type for AbstractSS

* fix conversion from ss to tf without type

* more abstract statespaces (#521)

* omre abstract statespaces

* even more ASS

* remove simple feedback in favor of mor egeneral version

* propagate timeevol

* add block diagram to feedback docstring

* Updates to docstring

* fix docstring formatting

* delete redundancy in feedback docstring

Co-authored-by: olof3 <[email protected]>

* add controller function (#512)

* add controller function

* rename controller and predictor

* Move plot globals to runtests (#531)

* Move plot globals to runtests

* Move plot globals to framework.jl

* return similarity transform from `balreal` (#530)

* display error when covar fails

* return similarity transform from balreal

* Update src/matrix_comps.jl

Co-authored-by: olof3 <[email protected]>

Co-authored-by: olof3 <[email protected]>

* remove incorrect warning in pzmap (#535)

* support hz keyword in sigmaplot similar to bodeplot (#537)

* change formatting in dampreport (#536)

* change formatting in dampreport

* update dampreport to use ±

* even better formatting

* up formatting for complex systems

* add additive identity element for statespace and TF (#538)

* add additive identity element for statespace and TF

* rm zero from type. Test MIMO zero

* Fix struct_ctrb_obsv (#540)

* Fix struct_ctrb_obsv, closes #409

* Update src/simplification.jl

Co-authored-by: Fredrik Bagge Carlson <[email protected]>

* add to docstring

Co-authored-by: olof3 <[email protected]>

* Yet another fix for  struct_ctrb_states. Closes #475 (#541)

* bugfix for negative real pole in damp (#539)

* Fix #546

* minor typographic changes

* optional epsilon in dcgain (#548)

* optional epsilon in dcgain

* Update analysis.jl

* bugfix: use correct type for saving dde solutions (#549)

Would be good to have a regression test for `BigFloat` data which was the reason I found this bug. That seems slightly involved to fix though.

I assume that this would also have failed for `ComplexF64`, so eventually a test for that too would be good.

* bugfix dcgain (#551)

* correct type of initial state in step (#553)

* remove version checks

* Fix spacing in type printing

* write `struct_ctrb_states` in terms of `iszero` instead of `== 0` (#557)

* write `struct_ctrb_states` in terms of `iszero` instead of `== 0`

The reason is that `iszero` always returns a bool, whereas `== 0` may return anything. The difference appears for symbolic variables where
```julia
julia> q0 == 0
q0(t) == 0

julia> iszero(q0)
false
```

* Update simplification.jl

* remove `issmooth` (#561)

* remove issmooth

* drop extra `]`

* Return a result structure from lsim (#529)

* Return a result structure from lsim

This is by design a non-breaking change to the lsim interface since the structure allows both getindex and destructuring to behave just like if lsim returned a tuple of arrays like before.  Indeed, the tests for lsim were not touched in this commit.

This commit also adds a plot recipe to the result structure. All plot recipes for lsimplot, stepplot, impulseplot have been replaced by the new recipe. This is a breaking change since the names of the previous plots no longer exist. A slight change is that the plots for a step response no longer show the text "step response", but I think that's an acceptable change, the user can supply any title they prefer themselves.

* remove automatic title

* introduce additional abstract result type

* do not destructure sys

* remove LQG (#564)

The functionality was very buggy and poorly tested. A much improved version with proper tests are available in https://github.com/JuliaControl/RobustAndOptimalControl.jl/blob/master/src/lqg.jl

* pole->poles tzero->tzeros (#562)

* update usage of plot for step simulation

* add doctest filters

* add release notes

* Update README.md

* Update README.md

Co-authored-by: olof3 <[email protected]>
Co-authored-by: Albin Heimerson <[email protected]>
Co-authored-by: Mattias Fält <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants