Skip to content

Commit fc6671e

Browse files
committed
Calc disk margin
1 parent 22874a2 commit fc6671e

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

mwes/mwe_07.jl

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Linearize the closed loop system consisting of the winch, kite and upper force controller.
2+
3+
using Pkg
4+
if ! ("ControlPlots" keys(Pkg.project().dependencies))
5+
using TestEnv; TestEnv.activate()
6+
using Test
7+
end
8+
using WinchControllers, WinchModels, KiteUtils, Plots, ControlSystemsBase, FiniteDiff, RobustAndOptimalControl
9+
import FiniteDiff: finite_difference_jacobian
10+
11+
if isfile("data/system_tuned.yaml")
12+
set = load_settings("system_tuned.yaml")
13+
else
14+
set = load_settings("system.yaml")
15+
end
16+
wcs = WCSettings(dt=0.02)
17+
update(wcs)
18+
wcs.test = true
19+
20+
winch = Winch(wcs, set)
21+
22+
# find equilibrium speed
23+
function find_equilibrium_speed(winch, set_speed, force, n=10000)
24+
last_v_act = 0.0
25+
for v_set in range(0.0, 2*set_speed, n)
26+
lim_speed = minimum([v_set, set_speed])
27+
set_force(winch, force)
28+
set_v_set(winch, lim_speed)
29+
v_act = get_speed(winch)
30+
on_timer(winch)
31+
if v_set > 0 && abs(v_act - last_v_act) < 1e-6
32+
return v_act
33+
end
34+
last_v_act = v_act
35+
end
36+
set_v_set(winch, set_speed)
37+
on_timer(winch)
38+
@error "Failed to find equilibrium speed"
39+
end
40+
41+
function motor_dynamics(x, u)
42+
# x: state vector, e.g., [v_act]
43+
# u: input vector, e.g., [v_set, force]
44+
v_act = x[1]
45+
v_set, force = u[1], u[2]
46+
acc = calc_acceleration(winch.wm, v_act, force; set_speed = v_set)
47+
return [acc]
48+
end
49+
50+
function calc_force(v_wind, v_ro)
51+
(v_wind - v_ro)^2 * 4000.0 / 16.0
52+
end
53+
54+
# create the upper force controller
55+
# Tf​ can typically be chosen as Ti/NT for a PI controller and Td/N for a PID controller, and N is commonly in the range 2 to 20.
56+
# Td = wcs.df_high / wcs.pf_high Kd/Kp
57+
function upper_force_controller(wcs)
58+
# wcs: WCSettings object
59+
Td = wcs.df_high / wcs.pf_high
60+
N = wcs.nf_high
61+
Tf = Td / N
62+
C = pid(wcs.pf_high, wcs.if_high, wcs.df_high; form=:parallel, filter_order=1, state_space=true, Tf)
63+
return C
64+
end
65+
66+
function system_dynamics(x, u)
67+
# x: state vector, e.g., [v_act]
68+
# u: input vector, e.g., [v_set, v_wind]
69+
v_act = x[1]
70+
v_set, v_wind = u[1], u[2]
71+
force = calc_force(v_wind, v_act)
72+
acc = calc_acceleration(winch.wm, v_act, force; set_speed = v_set)
73+
return [acc]
74+
end
75+
76+
function linearize(winch, v_set, v_wind)
77+
force = calc_force(v_wind, v_set)
78+
v_act = find_equilibrium_speed(winch, v_set, force)
79+
x0 = [v_act] # State at operating point
80+
u0 = [v_set, v_wind] # Input at operating point
81+
A = finite_difference_jacobian(x -> system_dynamics(x, u0), x0)
82+
B = finite_difference_jacobian(u -> system_dynamics(x0, u), u0)
83+
C = [1.0]
84+
D = [0.0 0.0]
85+
force = calc_force(v_wind, v_act)
86+
siso_sys = ss(A, B[:, 1], C, D[:, 1]) * force/v_act
87+
end
88+
89+
function open_loop_system(winch, v_set, v_wind)
90+
# Create the open loop system with the upper force controller
91+
C = upper_force_controller(winch.wcs)
92+
sys = linearize(winch, v_set, v_wind)
93+
# sys_open = feedback(C * sys, 1.0; sign=-1)
94+
return C * sys
95+
end
96+
97+
for v_wind in range(7.5, 9, length=2)
98+
global sys
99+
local v_set
100+
v_set = 0.57*v_wind
101+
# @info "Linearizing for v_wind: $v_wind m/s, v_ro: $(round(v_set, digits=2)) m/s"
102+
sys = open_loop_system(winch, v_set, v_wind)
103+
# gm, pm, wgm, wpm = margin(sys; adjust_phase_start=false)
104+
# @info "Gain margin: $gm, Phase margin: $pm, Gain crossover frequency: $wgm, Phase crossover frequency: $wpm"
105+
# bode_plot(sys; from=0.76, to=2.85, title="Linearized System, v_wind=8..9 m/s")
106+
end
107+
dm = diskmargin(sys)
108+
@info "$dm"
109+
plot(dm)

0 commit comments

Comments
 (0)