Skip to content

Commit 7a39951

Browse files
authored
Merge pull request #252 from JuliaControl/doc_correction
doc: details on proper systems in `LinModel` extended help
2 parents 1a38039 + 34cda47 commit 7a39951

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

docs/src/manual/nonlinmpc.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,8 @@ mpc_ms = LinMPC(skf; Hp, Hc, Mwt, Nwt, Cwt=Inf, transcription=MultipleShooting()
405405
mpc_ms = setconstraint!(mpc_ms, umin=[-1.5], umax=[+1.5])
406406
```
407407

408-
Superimposing the previous disturbance rejection plot shows almost identical results:
408+
Superimposing the previous disturbance rejection to the newer one gives almost identical
409+
results:
409410

410411
```@example man_nonlin
411412
res_ms = sim!(mpc_ms, N, [180.0]; plant, x_0=[π, 0], y_step=[10])

src/model/linmodel.jl

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,16 @@ The system `sys` can be continuous or discrete-time (`Ts` can be omitted for the
7474
For continuous dynamics, its state-space equations are (discrete case in Extended Help):
7575
```math
7676
\begin{aligned}
77-
\mathbf{ẋ}(t) &= \mathbf{A x}(t) + \mathbf{B z}(t) \\
78-
\mathbf{y}(t) &= \mathbf{C x}(t) + \mathbf{D z}(t)
77+
\mathbf{ẋ}(t) &= \mathbf{A x}(t) + \mathbf{B s}(t) \\
78+
\mathbf{y}(t) &= \mathbf{C x}(t) + \mathbf{D s}(t)
7979
\end{aligned}
8080
```
81-
with the state ``\mathbf{x}`` and output ``\mathbf{y}`` vectors. The ``\mathbf{z}`` vector
81+
with the state ``\mathbf{x}`` and output ``\mathbf{y}`` vectors. The ``\mathbf{s}`` vector
8282
comprises the manipulated inputs ``\mathbf{u}`` and measured disturbances ``\mathbf{d}``,
83-
in any order. `i_u` provides the indices of ``\mathbf{z}`` that are manipulated, and `i_d`,
83+
in any order. `i_u` provides the indices of ``\mathbf{s}`` that are manipulated, and `i_d`,
8484
the measured disturbances. The constructor automatically discretizes continuous systems,
8585
resamples discrete ones if `Ts ≠ sys.Ts`, computes a new balancing and minimal state-space
86-
realization, and separates the ``\mathbf{z}`` terms in two parts (details in Extended Help).
86+
realization, and separates the ``\mathbf{s}`` terms in two parts (details in Extended Help).
8787
The rest of the documentation assumes discrete models since all systems end up in this form.
8888
8989
See also [`ss`](@extref ControlSystemsBase.ss)
@@ -112,8 +112,8 @@ LinModel with a sample time Ts = 0.1 s:
112112
The state-space equations are similar if `sys` is discrete-time:
113113
```math
114114
\begin{aligned}
115-
\mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B z}(k) \\
116-
\mathbf{y}(k) &= \mathbf{C x}(k) + \mathbf{D z}(k)
115+
\mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B s}(k) \\
116+
\mathbf{y}(k) &= \mathbf{C x}(k) + \mathbf{D s}(k)
117117
\end{aligned}
118118
```
119119
Continuous dynamics are internally discretized using [`c2d`](@extref ControlSystemsBase.c2d)
@@ -124,16 +124,21 @@ LinModel with a sample time Ts = 0.1 s:
124124
Note that the constructor transforms the system to its minimal and balancing realization
125125
using [`minreal`](@extref ControlSystemsBase.minreal) for controllability/observability.
126126
As a consequence, the final state-space representation will be presumably different from
127-
the one provided in `sys`. It is also converted into a more practical form
128-
(``\mathbf{D_u=0}`` because of the zero-order hold):
127+
the one provided in `sys`. It is also converted into a more practical form:
129128
```math
130129
\begin{aligned}
131130
\mathbf{x}(k+1) &= \mathbf{A x}(k) + \mathbf{B_u u}(k) + \mathbf{B_d d}(k) \\
132131
\mathbf{y}(k) &= \mathbf{C x}(k) + \mathbf{D_d d}(k)
133132
\end{aligned}
134133
```
135134
Use the syntax [`LinModel{NT}(A, Bu, C, Bd, Dd, Ts)`](@ref) to force a specific
136-
state-space representation.
135+
state-space representation.
136+
137+
It is assumed that ``\mathbf{D_u=0}`` (or `sys` is strictly proper) since otherwise the
138+
resulting discrete controller is acausal by definition. Indeed, all discrete controllers
139+
(1) sample an output ``\mathbf{y}(k)`` from the plant, (2) computes an action
140+
``\mathbf{u}(k)`` and (3) apply the action on the plant. There is a causality paradox
141+
if ``\mathbf{u}(k)`` impacts ``\mathbf{y}(k)`` even before computing it.
137142
"""
138143
function LinModel(
139144
sys::StateSpace{E, NT},
@@ -194,8 +199,8 @@ end
194199
195200
Convert to minimal realization state-space when `sys` is a transfer function.
196201
197-
`sys` is equal to ``\frac{\mathbf{y}(s)}{\mathbf{z}(s)}`` for continuous-time, and
198-
``\frac{\mathbf{y}(z)}{\mathbf{z}(z)}``, for discrete-time.
202+
`sys` is equal to ``\frac{\mathbf{y}(s)}{\mathbf{s}(s)}`` for continuous-time, and
203+
``\frac{\mathbf{y}(z)}{\mathbf{s}(z)}``, for discrete-time.
199204
200205
See also [`tf`](@extref ControlSystemsBase.tf)
201206

src/model/nonlinmodel.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ functions are defined as:
107107
where ``\mathbf{x}``, ``\mathbf{y}``, ``\mathbf{u}``, ``\mathbf{d}`` and ``\mathbf{p}`` are
108108
respectively the state, output, manipulated input, measured disturbance and parameter
109109
vectors. As a matter of fact, the parameter argument `p` can be any Julia objects but use a
110-
mutable type if you want to change them later e.g.: a vector. If the dynamics is a function
111-
of the time, simply add a measured disturbance defined as ``d(t) = t``. The functions can be
112-
implemented in two possible ways:
110+
mutable type if you want to change them later e.g.: a vector.
111+
112+
See Extended Help if the dynamics are a function of ``t`` or ``\mathbf{u}`` appears in
113+
``\mathbf{h}``. The functions can be implemented in two possible ways:
113114
114115
1. **Non-mutating functions** (out-of-place): define them as `f(x, u, d, p) -> ẋ` and
115116
`h(x, d, p) -> y`. This syntax is simple and intuitive but it allocates more memory.
@@ -191,6 +192,10 @@ NonLinModel with a sample time Ts = 2.0 s:
191192
`h(x, d, p) -> y`.
192193
2. **Mutating functions**: define them as `f!(xnext, x, u, d, p) -> nothing` and
193194
`h!(y, x, d, p) -> nothing`.
195+
196+
If the dynamics are a function of the time, simply add a measured disturbance defined as
197+
``d(t) = t``. This package does not support the ``\mathbf{u}`` argument in ``\mathbf{h}``
198+
function, see the Extended Help of [`LinModel`](@ref) for the justification.
194199
"""
195200
function NonLinModel{NT}(
196201
f::Function, h::Function, Ts::Real, nu::Int, nx::Int, ny::Int, nd::Int=0;

0 commit comments

Comments
 (0)