This example shows how to interpret and validate tuning results from systune.
You can tune the parameters of your control system with systune or looptune. The design specifications are captured using TuningGoal requirement objects. This example shows how to interpret the results from systune, graphically verify the design requirements, and perform additional open- and closed-loop analysis.
We use an autopilot tuning application as illustration, see the "Tuning of a Two-Loop Autopilot" example for details. The tuned compensator is the "MIMO Controller" block highlighted in orange in the model below.
The setup and tuning steps are repeated below for completeness.
ST0 = slTunable('rct_airframe2','MIMO Controller'); ST0.addControl('delta fin'); % Compensator parameterization C0 = ltiblock.ss('C',2,1,2); C0.d.Value(1) = 0; C0.d.Free(1) = false; ST0.setBlockParam('MIMO Controller',C0) % Requirements Req1 = TuningGoal.Tracking('az ref','az',1); % tracking Req2 = TuningGoal.Gain('delta fin','delta fin',tf(25,[1 0])); % roll-off Req3 = TuningGoal.Margins('delta fin',7,45); % margins MaxGain = frd([2 200 200],[0.02 2 200]); Req4 = TuningGoal.Gain('delta fin','az',MaxGain); % disturbance rejection % Tuning Opt = systuneOptions('RandomStart',3); rng('default') [ST1,fSoft,~,Info] = ST0.systune([Req1,Req2,Req3,Req4],Opt);
Final: Soft = 1.5, Hard = -Inf, Iterations = 60 Final: Soft = 1.15, Hard = -Inf, Iterations = 188 Final: Soft = 1.15, Hard = -Inf, Iterations = 64 Final: Soft = 1.15, Hard = -Inf, Iterations = 97
systune run three optimizations from three different starting points and returned the best overall result. The first output ST is an slTunable interface representing the tuned control system. The second output fSoft contains the final values of the four requirements for the best design.
fSoft = 1.1477 1.1477 0.5458 1.1477
Requirements are normalized so a requirement is satisfied if and only if its value is less than 1. Inspection of fSoft reveals that Requirements 1,2,4 are active and slightly violated while Requirement 3 (stability margins) is satisfied.
Use viewSpec to graphically inspect each requirement. This is useful to understand whether small violations are acceptable or what causes large violations. Make sure to provide the structure Info returned by systune to properly account for scalings and other parameters computed by the optimization algorithms. First verify the tracking requirement.
We observe a slight violation across frequency, suggesting that setpoint tracking will perform close to expectations. Similarly, verify the disturbance rejection requirement.
Most of the violation is at low frequency with a small bump near 35 rad/s, suggesting possible damped oscillations at this frequency. Finally, verify the stability margin requirement.
This requirement is satisfied at all frequencies, with the smallest margins achieved near the crossover frequency as expected. To see the actual margin values at a given frequency, click on the red curve and read the values from the data tip.
You can also use evalSpec to evaluate each requirement, that is, compute its contribution to the soft and hard constraints. For example
[H1,f1] = evalSpec(Req1,ST1,Info);
returns the value f1 of the requirement and the underlying frequency-weighted transfer function H1 used to computed it. You can verify that f1 matches the first entry of fSoft and coincides with the peak gain of H1.
[f1 fSoft(1) getPeakGain(H1,1e-6)]
ans = 1.1477 1.1477 1.1477
In addition to verifying requirements, you can perform basic open- and closed-loop analysis using getIOTransfer and getLoopTransfer. For example, verify tracking performance in the time domain by plotting the response az to a step command azref for the tuned system ST1.
T = ST1.getIOTransfer('az ref','az'); step(T)
Also plot the open-loop response measured at the plant input delta fin. You can use this plot to assess the classical gain and phase margins at the plant input.
L = ST1.getLoopTransfer('delta fin',-1); % negative-feedback loop transfer margin(L), grid
So far we have treated all four requirements equally in the objective function. Alternatively, you can use a mix of soft and hard constraints to differentiate between must-have and nice-to-have requirements. For example, you could treat Requirements 3,4 as hard constraints and optimize the first two requirements subject to these constraints. For best results, do this only after obtaining a reasonable design with all requirements treated equally.
[ST2,fSoft,gHard,Info] = ST1.systune([Req1 Req2],[Req3 Req4]);
Final: Soft = 1.31, Hard = 0.99998, Iterations = 137
fSoft = 1.2259 1.3068
gHard = 0.4762 1.0000
Here fSoft contains the final values of the first two requirements (soft constraints) and gHard contains the the final values of the last two requirements (hard constraints). The hard constraints are satisfied since all entries of gHard are less than 1. As expected, the best value of the first two requirements went up as the optimizer strived to strictly enforce the fourth requirement.