Skip to content

Commit de1151f

Browse files
committed
add linear analysis documentation
1 parent ae1910a commit de1151f

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[deps]
2+
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
23
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
34
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
45
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"

docs/pages.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ pages = [
1111
"Magnetic Components" => "API/magnetic.md",
1212
"Mechanical Components" => "API/mechanical.md",
1313
"Thermal Components" => "API/thermal.md",
14+
"Linear Analysis" => "API/linear_analysis.md",
1415
],
1516
]

docs/src/API/linear_analysis.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Linear Analysis
2+
3+
Linear analysis refers to the process of linearizing a nonlinear model and analysing the resulting linear dynamical system. To facilitate linear analysis, ModelingToolkitStandardLibrary provides the concept of an [`AnalysisPoint`](@ref), which can be inserted inbetween two causal blocks (such as those from the Blocks sub module). Once a model containing analysis points is built, several operations are available:
4+
5+
- [`get_sensitivity`](@ref) get the [sensitivity function (wiki)](https://en.wikipedia.org/wiki/Sensitivity_(control_systems)), $S(s)$, as defined in the field of control theory.
6+
- [`get_comp_sensitivity`](@ref) get the complementary sensitivy function $T(s) : S(s)+T(s)=1$.
7+
- [`get_looptransfer`](@ref) get the (open) loop-transfer function where the loop starts and ends in the analysis point.
8+
- [`linearize`](@ref) can be called with two analysis points denoting the input and output of the linearied system. Parts of the model not appearing between the input and output will be removed.
9+
- [`open_loop`](@ref) return a new (nonlinear) system where the loop has been broken in the analysis point, i.e., the connection the analysis point usually implies has been removed.
10+
11+
An analysis point can be created explicitly using the constructor [`AnalysisPoint`](@ref), or automatically when connecting two causal components using `connect`:
12+
```julia
13+
connect(comp1.output, :analysis_point_name, comp2.input)
14+
```
15+
16+
Of the above mentioned functions, all except for [`open_loop`](@ref) return the output of [`ModelingToolkit.linearize`](@ref), which is
17+
```julia
18+
matrices, simplified_sys = linearize(...)
19+
# matrices = (; A, B, C, D)
20+
```
21+
i.e., `matrices` is a named tuple containing the matrices of a linear state-space system on the form
22+
```math
23+
\begin{aligned}
24+
\dot x &= Ax + Bu\\
25+
y &= Cx + Du
26+
\end{aligned}
27+
```
28+
29+
## Example
30+
The following example builds a simple closed-loop system with a plant $P$ and a controller $C$. Two analysis points are inserted, one before and one after $P$. We then derive a number of sensitivity functions and show the corresponding code using the package ControlSystemBase.jl
31+
32+
```@example LINEAR_ANALYSIS
33+
using ModelingToolkitStandardLibrary.Blocks, ModelingToolkit
34+
@named P = FirstOrder(k=1, T=1) # A first-order system with pole in -1
35+
@named C = Gain(-1) # A P controller
36+
t = ModelingToolkit.get_iv(P)
37+
eqs = [
38+
connect(P.output, :plant_output, C.input) # Connect with an automatically created analysis point called :plant_output
39+
connect(C.output, :plant_input, P.input) # Connect with an automatically created analysis point called :plant_input
40+
]
41+
sys = ODESystem(eqs, t, systems=[P,C], name=:feedback_system)
42+
43+
matrices_S = get_sensitivity(sys, :plant_input)[1] # Compute the matrices of a state-space representation of the (input)sensitivity funciton.
44+
matrices_T = get_comp_sensitivity(sys, :plant_input)[1]
45+
```
46+
Continued linear analysis and design can be performed using ControlSystemsBase.jl.
47+
We create `ControlSystemsBase.StateSpace` objects using
48+
```@example LINEAR_ANALYSIS
49+
using ControlSystemsBase, Plots
50+
S = ss(matrices_S...)
51+
T = ss(matrices_T...)
52+
bodeplot([S, T], lab=["S" "" "T" ""])
53+
```
54+
55+
The sensitivity functions obtained this way should be equivalent to the ones obtained with the code below
56+
57+
```@example LINEAR_ANALYSIS_CS
58+
using ControlSystemsBase
59+
P = tf(1.0, [1, 1]) |> ss
60+
C = 1 # Negative feedback assumed in ControlSystems
61+
S = sensitivity(P, C) # or feedback(1, P*C)
62+
T = comp_sensitivity(P, C) # or feedback(P*C)
63+
```
64+
65+
We may also derive the loop-transfer function $L(s) = P(s)C(s)$ using
66+
67+
```@example LINEAR_ANALYSIS
68+
matrices_L = get_looptransfer(sys, :plant_output)[1]
69+
L = ss(matrices_L...)
70+
```
71+
which is equivalent to the following with ControlSystems
72+
```@example LINEAR_ANALYSIS_CS
73+
L = P*(-C) # Add the minus sign to build the negative feedback into the controller
74+
```
75+
76+
77+
To obtain the transfer function between two analysis points, we call `linearize`
78+
```@example LINEAR_ANALYSIS
79+
matrices_P = linearize(sys, :plant_input, :plant_output)[1]
80+
```
81+
this particular transfer function should be equivalent to the linear system `P`, i.e., equivalent to this call
82+
```@example LINEAR_ANALYSIS
83+
@unpack input, output = P # To get the correct namespace
84+
linearize(P, [input.u], [output.u])[1]
85+
```
86+
87+
## Index
88+
```@index
89+
Pages = ["linear_analysis.md"]
90+
```
91+
92+
```@autodocs
93+
Modules = [ModelingToolkitStandardLibrary.Blocks]
94+
Pages = ["Blocks/analysis_points.jl"]
95+
Order = [:function, :type]
96+
Private = false
97+
```

0 commit comments

Comments
 (0)