1+ # this script tunes the controller parameters (well, seven of them)
2+ # TODO : make sure that calling autotune does not make the performance worse
3+ # DONE: add the mean square of the acceleration to the damage metric
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, NOMAD, 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; rms= true )
79+ end
80+
81+
82+ function simulate_sc (x:: Vector ; 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 eval_fct (x)
93+ bb_outputs = [simulate_sc (x)]
94+ success = true
95+ count_eval = true
96+ return (success, count_eval, bb_outputs)
97+ end
98+
99+ function simulate_lfc (x:: Vector{Cdouble} ; return_lg:: Bool = false )
100+ wcs = WCSettings (dt= 0.02 )
101+ update (wcs)
102+ wcs. test = true
103+ wcs. pf_low = x[1 ] # set the lower force controller gain
104+ wcs. if_low = x[2 ] # set the lower force controller integral gain
105+ simulate (wcs; return_lg)
106+ end
107+
108+ function simulate_ufc (x:: Vector{Cdouble} ; return_lg:: Bool = false )
109+ wcs = WCSettings (dt= 0.02 )
110+ update (wcs)
111+ wcs. test = true
112+ wcs. pf_high = x[1 ] # set the higher force controller gain
113+ wcs. if_high = x[2 ] # set the higher force controller integral gain
114+ simulate (wcs; return_lg)
115+ end
116+
117+ function autotune (controller:: WinchControllerState )
118+ global x, info, lg, TUNED, result
119+ if TUNED
120+ load_settings (" system_tuned.yaml" )
121+ else
122+ load_settings (" system.yaml" )
123+ end
124+ wcs = WCSettings (dt= 0.02 )
125+ update (wcs)
126+ wcs. test = true
127+ if controller == wcsSpeedControl
128+ println (" Autotuning speed controller..." )
129+ # # Define the parameters for the autotuning
130+ # x0 = [wcs.p_speed, wcs.i_speed, wcs.t_blend] # initial guess for the speed controller gain
131+ # x, info = bobyqa(simulate_sc, x0;
132+ # xl = 0.75 .* x0,
133+ # xu = 1.5 .* x0,
134+ # rhobeg = maximum([1e-4, minimum(x0)/4]),
135+ # npt=10,
136+ # maxfun = 500
137+ # )
138+ x0 = [wcs. p_speed, wcs. i_speed, wcs. t_blend] # initial guess for the speed controller gain
139+
140+ pb = NomadProblem (3 , # number of inputs of the blackbox
141+ 1 , # number of outputs of the blackbox
142+ [" OBJ" ], # type of outputs of the blackbox
143+ eval_fct;
144+ lower_bound = 0.75 .* x0,
145+ upper_bound = 1.5 .* x0)
146+ result = solve (pb, x0)
147+ x = result. x_best_feas
148+ elseif controller == wcsLowerForceLimit
149+ println (" Autotuning lower force limit controller..." )
150+ # Define the parameters for the autotuning
151+ x0 = [maximum ([1e-4 , wcs. pf_low]), wcs. if_low] # initial guess for the speed controller gain
152+
153+ x, info = bobyqa (simulate_lfc, x0;
154+ xl = 0.25 .* x0,
155+ xu = 2.0 .* x0,
156+ rhobeg = maximum ([1e-4 , minimum (x0)/ 4 ]),
157+ maxfun = 500
158+ )
159+ elseif controller == wcsUpperForceLimit
160+ println (" Autotuning upper force control..." )
161+ # Define the parameters for the autotuning
162+ x0 = [maximum ([2e-5 , wcs. pf_high]), wcs. if_high] # initial guess for the speed controller gain
163+ x, info = bobyqa (simulate_lfc, x0;
164+ xl = 0.25 .* x0,
165+ xu = 2.0 .* x0,
166+ rhobeg = maximum ([2e-5 , minimum (x0)/ 4 ]),
167+ maxfun = 500
168+ )
169+ else
170+ error (" Unknown controller state: $controller " )
171+ return
172+ end
173+
174+ println (" Autotuning results: $x " )
175+ # println("Iterations: $(info.nf)")
176+ # println(PRIMA.reason(info.status))
177+
178+ if true
179+ println (" Running simulation with tuned parameters..." )
180+ TUNED = true
181+ if controller == wcsSpeedControl
182+ wcs, lg = simulate_sc (x; return_lg= true )
183+ elseif controller == wcsLowerForceLimit
184+ wcs, lg = simulate_lfc (x; return_lg= true )
185+ elseif controller == wcsUpperForceLimit
186+ wcs, lg = simulate_ufc (x; return_lg= true )
187+ end
188+
189+ println (" \n Performance of force controllers: $(round (100 * (1 - f_err (lg)), digits= 2 )) %" )
190+ println (" Performance of speed controller: $(round (100 * (1 - v_err (lg)), digits= 2 )) %" )
191+ println (" Damage: $(round (100 * (damage (lg)), digits= 2 )) %" )
192+ println (" Damage with rms: $(round (100 * (damage (lg; rms= true )), digits= 2 )) %" )
193+ println (" Combined performance γ: $(round (- 100 * result. bbo_best_feas[1 ], digits= 2 )) %" )
194+ return wcs
195+ else
196+ println (" Autotuning failed: $(PRIMA. reason (info. status)) " )
197+ return nothing
198+ end
199+ end
200+
201+ function copy_settings ()
202+ cp (" data/wc_settings.yaml" , " data/wc_settings_tuned.yaml" ; force= true )
203+ end
204+ function change_value (lines, varname, value:: Union{Integer, Float64} )
205+ KiteUtils. change_value (lines, varname, repr (round (value, digits= 4 )))
206+ end
207+ function update_settings (wcs:: WCSettings )
208+ lines = KiteUtils. readfile (" data/wc_settings_tuned.yaml" )
209+ lines = change_value (lines, " i_speed:" , wcs. i_speed)
210+ lines = change_value (lines, " p_speed:" , wcs. p_speed)
211+ lines = change_value (lines, " t_blend:" , wcs. t_blend)
212+ lines = change_value (lines, " pf_low:" , wcs. pf_low)
213+ lines = change_value (lines, " if_low:" , wcs. if_low)
214+ lines = change_value (lines, " pf_high:" , wcs. pf_high)
215+ lines = change_value (lines, " if_high:" , wcs. if_high)
216+ KiteUtils. writefile (lines, " data/wc_settings_tuned.yaml" )
217+ end
218+
219+ function tune_all ()
220+ wcs = autotune (wcsSpeedControl)
221+ if ! isnothing (wcs)
222+ copy_settings ()
223+ update_settings (wcs)
224+ println ()
225+ wcs = autotune (wcsLowerForceLimit)
226+ if ! isnothing (wcs)
227+ update_settings (wcs)
228+ println ()
229+ wcs = autotune (wcsUpperForceLimit)
230+ if ! isnothing (wcs)
231+ update_settings (wcs)
232+ end
233+ end
234+ @info " Tuned settings saved to data/wc_settings_tuned.yaml"
235+ end
236+ end
237+
238+ tune_all ()
239+ tune_all ()
240+
241+
242+ # autotune(wcsUpperForceControl)
0 commit comments