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 (" \n Performance 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