%% Using Parallel Computing to Accelerate Tuning
% This example shows how to leverage the Parallel Computing Toolbox(TM) to 
% accelerate multi-start strategies for tuning fixed-structure control 
% systems.

% Copyright 1986-2013 The MathWorks, Inc.

%% Background
% Both |systune| and |looptune| use local optimization methods for tuning
% the control architecture at hand. To mitigate the risk of ending up with
% a locally optimal but globally poor design, it is recommended to run 
% several optimizations starting from different randomly generated initial points. 
% If you have a multi-core machine or have access to distributed computing
% resources, you can significantly speed up this process using 
% the Parallel Computing Toolbox.
%
% This example shows how to parallelize the tuning of an airframe autopilot
% with |looptune|. See the example "Tuning of a Two-Loop Autopilot" for more
% details about this application of |looptune|.

%% Autopilot Tuning
% The airframe dynamics and autopilot are modeled in Simulink.

open_system('rct_airframe1')

%% 
% The autopilot consists of two cascaded loops whose tunable elements 
% include two PI controller gains ("az Control" block) and one gain in the
% pitch-rate loop ("q Gain" block). The vertical acceleration |az| should
% track the command |azref| with a 1 second response time. Use |slTuner|
% to configure this tuning task (see "Tuning of a Two-Loop Autopilot"
% example for details):

ST0 = slTuner('rct_airframe1',{'az Control','q Gain'});
addPoint(ST0,{'az ref','delta fin','az','q'})

% Design requirements
wc = [3,12];   % bandwidth
TrackReq = TuningGoal.Tracking('az ref','az',1);  % tracking

%% Parallel Tuning with LOOPTUNE
% We are ready to tune the autopilot gains with |looptune|. To minimize the
% risk of getting a poor-quality local minimum, run 30 
% optimizations starting from 30 randomly generated values of the three gains.
% Configure the |looptune| options to enable parallel processing of these 30 runs:

rng('default')
Options = looptuneOptions('RandomStart',30,'UseParallel',true);

%% 
% Next call |looptune| to launch the tuning algorithm. The 30 runs are 
% automatically distributed across available computing resources:

Controls = 'delta fin';
Measurements = {'az','q'};
[ST,gam,Info] = looptune(ST0,Controls,Measurements,wc,TrackReq,Options);

%%
% Most runs return 1.23 as optimal gain value, suggesting that this local
% minimum has a wide region of attraction and is likely to be the global optimum.
% Use |showBlockValue| to see the corresponding gain values:

showBlockValue(ST)

%% 
% Plot the closed-loop response for this set of gains:

T = getIOTransfer(ST,'az ref','az');
step(T,5)
