Skip to content

Commit 17bf058

Browse files
committed
Add autotune_dev.jl
1 parent 4941079 commit 17bf058

File tree

1 file changed

+224
-0
lines changed

1 file changed

+224
-0
lines changed

scripts/autotune_dev.jl

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# this script shall tune the controller parameters
2+
# TODO: save the results in wc_settings_tuned.yaml
3+
# TODO: optimize the lower force controller
4+
using Pkg
5+
if ! ("ControlPlots" keys(Pkg.project().dependencies))
6+
using TestEnv; TestEnv.activate()
7+
using Test
8+
end
9+
using WinchControllers, KiteUtils, PRIMA, ControlPlots
10+
11+
TUNED::Bool = false
12+
load_settings("system.yaml")
13+
14+
function calc_force(v_wind, v_ro)
15+
(v_wind - v_ro)^2 * 4000.0 / 16.0
16+
end
17+
18+
function plot(lg::WCLogger)
19+
p1=plotx(lg.time, lg.v_wind, [lg.v_ro, lg.v_set_in], lg.f_err*0.001, lg.v_err, lg.acc, lg.force*0.001, lg.state,
20+
title="Winch controller test, all controllers active",
21+
ylabels=["v_wind [m/s]", "v_reel_out [m/s]", "f_err [kN]", "v_error [m/s]", "acc [m/s²]", "force [kN]", "state"],
22+
ysize=10,
23+
labels=["v_wind", ["v_reel_out", "v_set_in"]],
24+
fig="test_winchcontroller",)
25+
display(p1)
26+
end
27+
28+
function simulate(wcs::WCSettings; return_lg::Bool = false)
29+
if TUNED
30+
set = load_settings("system_tuned.yaml")
31+
else
32+
set = load_settings("system.yaml")
33+
end
34+
35+
# define the simulation parameters
36+
DURATION = 10.0
37+
V_WIND_MAX = 9.0 # max wind speed of test wind
38+
V_WIND_MIN = 0.0 # min wind speed of test wind
39+
FREQ_WIND = 0.25 # frequency of the triangle wind speed signal
40+
41+
# create the logger
42+
lg::WCLogger = WCLogger(DURATION, wcs.dt, set.max_force, wcs.max_acc, wcs.damage_factor)
43+
44+
STARTUP = get_startup(wcs, length(lg))
45+
V_WIND = STARTUP .* get_triangle_wind(wcs, V_WIND_MIN, V_WIND_MAX, FREQ_WIND, length(lg))
46+
47+
# create and initialize winch controller
48+
wc = WinchController(wcs)
49+
winch = WinchControllers.Winch(wcs, set)
50+
f_low = wcs.f_low
51+
52+
for i in 1:length(lg)
53+
# model
54+
v_wind = V_WIND[i]
55+
v_act = get_speed(winch)
56+
force = calc_force(v_wind, v_act)
57+
set_force(winch, force)
58+
59+
# controller
60+
v_set_out = calc_v_set(wc, v_act, force, f_low)
61+
62+
# update model input
63+
set_v_set(winch, v_set_out)
64+
65+
# run integration step
66+
on_timer(winch)
67+
on_timer(wc)
68+
69+
# get values for logging and log them
70+
status = get_status(wc)
71+
log(lg; v_wind, v_ro=v_act, acc=get_acc(winch), state=get_state(wc), reset=status[1], active=status[2], force=status[3],
72+
f_set=status[4], f_err=get_f_err(wc), v_err=get_v_err(wc), v_set=get_v_set(wc), v_set_out, v_set_in=get_v_set_in(wc))
73+
end
74+
if return_lg
75+
return wcs, lg
76+
end
77+
# calculate the performance metrics
78+
-gamma(lg)
79+
end
80+
81+
82+
function simulate_sc(x::Vector{Cdouble}; return_lg::Bool = false)
83+
wcs = WCSettings(dt=0.02)
84+
update(wcs)
85+
wcs.test = true
86+
wcs.i_speed = x[1] # set the speed controller gain
87+
wcs.p_speed = x[2] # set the speed controller proportional gain
88+
wcs.t_blend = x[3] # set the blending time for switching between controllers
89+
simulate(wcs; return_lg)
90+
end
91+
92+
function simulate_lfc(x::Vector{Cdouble}; return_lg::Bool = false)
93+
wcs = WCSettings(dt=0.02)
94+
update(wcs)
95+
wcs.test = true
96+
wcs.pf_low = x[1] # set the lower force controller gain
97+
wcs.if_low = x[2] # set the lower force controller integral gain
98+
simulate(wcs; return_lg)
99+
end
100+
101+
function simulate_ufc(x::Vector{Cdouble}; return_lg::Bool = false)
102+
wcs = WCSettings(dt=0.02)
103+
update(wcs)
104+
wcs.test = true
105+
wcs.pf_high = x[1] # set the higher force controller gain
106+
wcs.if_high = x[2] # set the higher force controller integral gain
107+
simulate(wcs; return_lg)
108+
end
109+
110+
function autotune(controller::WinchControllerState)
111+
global x, info, lg, TUNED
112+
if TUNED
113+
load_settings("system_tuned.yaml")
114+
else
115+
load_settings("system.yaml")
116+
end
117+
wcs = WCSettings(dt=0.02)
118+
update(wcs)
119+
wcs.test = true
120+
if controller == wcsSpeedControl
121+
println("Autotuning speed controller...")
122+
# Define the parameters for the autotuning
123+
x0 = [wcs.p_speed, wcs.i_speed, wcs.t_blend] # initial guess for the speed controller gain
124+
x, info = bobyqa(simulate_sc, x0;
125+
xl = 0.75 .* x0,
126+
xu = 1.5 .* x0,
127+
rhobeg = maximum([1e-4, minimum(x0)/4]),
128+
npt=10,
129+
maxfun = 500
130+
)
131+
elseif controller == wcsLowerForceLimit
132+
println("Autotuning lower force limit controller...")
133+
# Define the parameters for the autotuning
134+
x0 = [maximum([1e-4, wcs.pf_low]), wcs.if_low] # initial guess for the speed controller gain
135+
136+
x, info = bobyqa(simulate_lfc, x0;
137+
xl = 0.25 .* x0,
138+
xu = 2.0 .* x0,
139+
rhobeg = maximum([1e-4, minimum(x0)/4]),
140+
maxfun = 500
141+
)
142+
elseif controller == wcsUpperForceLimit
143+
println("Autotuning upper force control...")
144+
# Define the parameters for the autotuning
145+
x0 = [maximum([2e-5, wcs.pf_high]), wcs.if_high] # initial guess for the speed controller gain
146+
x, info = bobyqa(simulate_lfc, x0;
147+
xl = 0.25 .* x0,
148+
xu = 2.0 .* x0,
149+
rhobeg = maximum([2e-5, minimum(x0)/4]),
150+
maxfun = 500
151+
)
152+
else
153+
error("Unknown controller state: $controller")
154+
return
155+
end
156+
157+
println("Autotuning results: $x")
158+
println("Iterations: $(info.nf)")
159+
println(PRIMA.reason(info.status))
160+
161+
if issuccess(info)
162+
println("Running simulation with tuned parameters...")
163+
TUNED = true
164+
if controller == wcsSpeedControl
165+
wcs, lg = simulate_sc(x; return_lg=true)
166+
elseif controller == wcsLowerForceLimit
167+
wcs, lg = simulate_lfc(x; return_lg=true)
168+
elseif controller == wcsUpperForceLimit
169+
wcs, lg = simulate_ufc(x; return_lg=true)
170+
end
171+
172+
println("\nPerformance of force controllers: $(round(100*(1-f_err(lg)), digits=2)) %")
173+
println("Performance of speed controller: $(round(100*(1-v_err(lg)), digits=2)) %")
174+
println("Damage: $(round(100*(damage(lg)), digits=2)) %")
175+
println("Combined performance γ: $(round(-100*info.fx, digits=2)) %")
176+
return wcs
177+
else
178+
println("Autotuning failed: $(PRIMA.reason(info.status))")
179+
return nothing
180+
end
181+
end
182+
183+
function copy_settings()
184+
cp("data/wc_settings.yaml", "data/wc_settings_tuned.yaml"; force=true)
185+
end
186+
function change_value(lines, varname, value::Union{Integer, Float64})
187+
KiteUtils.change_value(lines, varname, repr(round(value, digits=4)))
188+
end
189+
function update_settings(wcs::WCSettings)
190+
lines = KiteUtils.readfile("data/wc_settings_tuned.yaml")
191+
lines = change_value(lines, "i_speed:", wcs.i_speed)
192+
lines = change_value(lines, "p_speed:", wcs.p_speed)
193+
lines = change_value(lines, "t_blend:", wcs.t_blend)
194+
lines = change_value(lines, "pf_low:", wcs.pf_low)
195+
lines = change_value(lines, "if_low:", wcs.if_low)
196+
lines = change_value(lines, "pf_high:", wcs.pf_high)
197+
lines = change_value(lines, "if_high:", wcs.if_high)
198+
KiteUtils.writefile(lines, "data/wc_settings_tuned.yaml")
199+
end
200+
201+
function tune_all()
202+
wcs = autotune(wcsSpeedControl)
203+
if ! isnothing(wcs)
204+
copy_settings()
205+
update_settings(wcs)
206+
println()
207+
wcs = autotune(wcsLowerForceLimit)
208+
if ! isnothing(wcs)
209+
update_settings(wcs)
210+
println()
211+
wcs = autotune(wcsUpperForceLimit)
212+
if ! isnothing(wcs)
213+
update_settings(wcs)
214+
end
215+
end
216+
@info "Tuned settings saved to data/wc_settings_tuned.yaml"
217+
end
218+
end
219+
220+
tune_all()
221+
tune_all()
222+
223+
224+
# autotune(wcsUpperForceControl)

0 commit comments

Comments
 (0)