|
1 | 1 | # Copyright (c) 2025 Bart van de Lint |
2 | 2 | # SPDX-License-Identifier: MPL-2.0 |
3 | 3 |
|
4 | | -#= |
5 | | -This example demonstrates linearized model accuracy by comparing: |
6 | | -1. Nonlinear SymbolicAWEModel model simulation |
7 | | -2. Linearized state-space model simulation |
8 | | -
|
9 | | -Both models start from the same operating point and are subjected |
10 | | -to identical steering inputs. The resulting state trajectories are |
11 | | -plotted together to visualize how well the linearized model |
12 | | -approximates the nonlinear dynamics. |
13 | | -=# |
| 4 | +# This example demonstrates how to: |
| 5 | +# - Load a system configuration from a YAML file, |
| 6 | +# - Initialize a SymbolicAWEModel with specified winch torques, |
| 7 | +# - Stabilize the system at its operating point, |
| 8 | +# - Linearize the system at that point, |
| 9 | +# - And plot the Bode plots of the resulting linearized system. |
14 | 10 |
|
15 | 11 | using Timers |
16 | 12 | tic() |
17 | 13 | @info "Loading packages " |
18 | 14 |
|
19 | 15 | PLOT = true |
20 | | -if PLOT |
21 | | - using Pkg |
22 | | - if ! ("LaTeXStrings" ∈ keys(Pkg.project().dependencies)) |
23 | | - using TestEnv; TestEnv.activate() |
24 | | - end |
25 | | - using ControlPlots, LaTeXStrings, ControlSystemsBase |
| 16 | +using Pkg |
| 17 | +if ! ("LaTeXStrings" ∈ keys(Pkg.project().dependencies)) |
| 18 | + using TestEnv; TestEnv.activate() |
26 | 19 | end |
| 20 | +using ControlPlots, LaTeXStrings, ControlSystemsBase |
27 | 21 |
|
28 | | -using KiteModels, LinearAlgebra, Statistics, OrdinaryDiffEqCore |
29 | | -using ModelingToolkit |
30 | | -using ModelingToolkit: t_nounits |
| 22 | +using KiteModels, KiteUtils, LinearAlgebra, Statistics |
| 23 | +using KiteModels.SymbolicAWEModels: find_steady_state! |
| 24 | +using KiteModels.SymbolicAWEModels.ModelingToolkit |
| 25 | +using KiteModels.SymbolicAWEModels.ModelingToolkit: t_nounits |
31 | 26 | toc() |
32 | 27 |
|
33 | | -# TODO: use sparse autodiff |
34 | | - |
35 | | -# Simulation parameters |
36 | | -dt = 0.001 |
37 | | -total_time = 1.0 # Increased from 0.1s to 1.0s for better dynamics observation |
38 | | -vsm_interval = 3 |
39 | | -steps = Int(round(total_time / dt)) |
40 | | - |
41 | | -# Steering parameters |
42 | | -steering_freq = 1/2 # Hz - full left-right cycle frequency |
43 | | -steering_magnitude = 5.0 # Magnitude of steering input [Nm] |
44 | | - |
45 | 28 | # Initialize model |
46 | | -set = load_settings("system_ram.yaml") |
47 | | -set.segments = 3 |
| 29 | +set = Settings("system_ram.yaml") |
48 | 30 | set_values = [-50.0, 0.0, 0.0] # Set values of the torques of the three winches. [Nm] |
49 | | -set.quasi_static = false |
50 | | -set.physical_model = "simple_ram" |
51 | 31 |
|
52 | | -@info "Creating SymbolicAWEModel model..." |
| 32 | +@info "Creating SymbolicAWEModel..." |
53 | 33 | s = SymbolicAWEModel(set) |
54 | | -s.set.abs_tol = 1e-2 |
55 | | -s.set.rel_tol = 1e-2 |
56 | 34 | toc() |
57 | 35 |
|
58 | 36 | # Define outputs for linearization - heading |
59 | | -lin_outputs = @variables heading(t_nounits)[1] |
| 37 | +@variables begin |
| 38 | + heading(t_nounits)[1] |
| 39 | + angle_of_attack(t_nounits)[1] |
| 40 | + tether_len(t_nounits)[1:3] |
| 41 | + winch_force(t_nounits)[1:3] |
| 42 | +end |
| 43 | +lin_outputs = [heading[1], angle_of_attack[1], tether_len[1], winch_force[1]] |
| 44 | +@info "Linear outputs: $lin_outputs" |
60 | 45 |
|
61 | 46 | # Initialize at elevation with linearization outputs |
62 | | -s.sys_struct.winches[2].tether_length += 0.2 |
63 | | -s.sys_struct.winches[3].tether_length += 0.2 |
64 | | -KiteModels.init!(s; |
65 | | - remake=false, |
66 | | - reload=true, |
67 | | - lin_outputs # Specify which outputs to track in linear model |
68 | | -) |
| 47 | +init!(s; lin_outputs) |
69 | 48 | sys = s.sys |
70 | 49 |
|
71 | | -@show rad2deg(s.integrator[sys.elevation[1]]) |
72 | | - |
73 | | - |
74 | 50 | @info "System initialized at:" |
75 | 51 | toc() |
76 | 52 |
|
77 | 53 | # --- Stabilize system at operating point --- |
78 | 54 | @info "Stabilizing system at operating point..." |
79 | | -s.integrator.ps[sys.stabilize] = true |
80 | | -stabilization_steps = Int(10 ÷ dt) |
81 | | -for i in 1:stabilization_steps |
82 | | - next_step!(s; dt, vsm_interval=0.05÷dt) |
83 | | -end |
84 | | -s.integrator.ps[sys.stabilize] = false |
| 55 | +find_steady_state!(s) |
85 | 56 |
|
86 | 57 | # --- Linearize at operating point --- |
87 | 58 | @info "Linearizing system at operating point..." |
88 | | -@time (; A, B, C, D) = KiteModels.linearize(s) |
89 | | -@time (; A, B, C, D) = KiteModels.linearize(s) |
90 | | -@show norm(A) |
| 59 | +(; A, B, C, D) = linearize!(s) |
| 60 | +@time (; A, B, C, D) = linearize!(s) |
91 | 61 | @info "System linearized with matrix dimensions:" A=size(A) B=size(B) C=size(C) D=size(D) |
92 | 62 |
|
93 | 63 | sys = ss(A,B,C,D) |
|
0 commit comments