Skip to content

Commit 43aba66

Browse files
committed
Add stability_lfc.jl, not yet working
1 parent bce183a commit 43aba66

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

examples/stability_lfc.jl

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Linearize the open loop system consisting of the winch, kite and lower force controller.
2+
# Use the function "diskmargin" to check the stability of the system.
3+
4+
using Pkg
5+
if ! ("ControlPlots" keys(Pkg.project().dependencies))
6+
using TestEnv; TestEnv.activate()
7+
using Test
8+
end
9+
using WinchControllers, WinchModels, KiteUtils, ControlPlots, ControlSystemsBase, FiniteDiff, RobustAndOptimalControl
10+
import FiniteDiff: finite_difference_jacobian
11+
12+
if isfile("data/system_tuned.yaml")
13+
set = load_settings("system_tuned.yaml")
14+
else
15+
set = load_settings("system.yaml")
16+
end
17+
wcs = WCSettings(dt=0.02)
18+
update(wcs)
19+
wcs.test = true
20+
21+
winch = Winch(wcs, set)
22+
23+
@info "Testing stability of the lower force controller (UFC) with the winch and kite system."
24+
25+
# find equilibrium speed
26+
function find_equilibrium_speed(winch, set_speed, force, n=10000)
27+
last_v_act = 0.0
28+
for v_set in range(-2.0, 2*set_speed, n)
29+
lim_speed = minimum([v_set, set_speed])
30+
set_force(winch, force)
31+
set_v_set(winch, lim_speed)
32+
v_act = get_speed(winch)
33+
on_timer(winch)
34+
if v_set > 0 && abs(v_act - last_v_act) < 1e-6
35+
return v_act
36+
end
37+
last_v_act = v_act
38+
end
39+
set_v_set(winch, set_speed)
40+
on_timer(winch)
41+
@error "Failed to find equilibrium speed"
42+
end
43+
44+
function motor_dynamics(x, u)
45+
# x: state vector, e.g., [v_act]
46+
# u: input vector, e.g., [v_set, force]
47+
v_act = x[1]
48+
v_set, force = u[1], u[2]
49+
acc = calc_acceleration(winch.wm, v_act, force; set_speed = v_set)
50+
return [acc]
51+
end
52+
53+
function calc_force(v_wind, v_ro)
54+
(v_wind - v_ro)^2 * 4000.0 / 16.0
55+
end
56+
57+
# create the lower force controller
58+
# 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.
59+
# Td = wcs.df_high / wcs.pf_high Kd/Kp
60+
function upper_force_controller(wcs)
61+
# wcs: WCSettings object
62+
C = pid(wcs.pf_low, wcs.if_low; form=:parallel, filter_order=1, state_space=true)
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 lower force controller
91+
C = upper_force_controller(winch.wcs)
92+
sys = linearize(winch, v_set, v_wind)
93+
return C * sys
94+
end
95+
96+
function margins()
97+
global sys
98+
margins = Float64[]
99+
for v_wind in range(-1, 1, length=3)
100+
local v_set, dm
101+
v_set = 0.57*v_wind
102+
sys = open_loop_system(winch, v_set, v_wind)
103+
try
104+
dm = diskmargin(sys)
105+
push!(margins, dm.margin)
106+
catch e
107+
push!(margins, 0)
108+
end
109+
end
110+
min_margin = minimum(margins)
111+
if min_margin < 0.3
112+
@error "System is unstable with a minimum margin of: $min_margin"
113+
elseif min_margin < 0.5
114+
@warn "System is marginally stable with a minimum margin of: $min_margin"
115+
else
116+
@info "System is stable with a minimum margin of: $(round(min_margin, digits=2)). A value ≥ 0.5 is considered robust."
117+
end
118+
return margins
119+
end
120+
margins()
121+
122+
for v_wind in range(-1, 1, length=3)
123+
global sys
124+
local v_set
125+
v_set = 0.57*v_wind
126+
sys = open_loop_system(winch, v_set, v_wind)
127+
bode_plot(sys; from=0.76, to=2.85, title="System with LFC, v_wind=-1..1 m/s")
128+
end
129+
nothing

0 commit comments

Comments
 (0)