## Documentation |

This example uses `systune` to generate smooth gain schedules for a three-loop autopilot.

On this page… |
---|

**Airframe Model and Three-Loop Autopilot**

This example uses a three-degree-of-freedom model of the pitch axis dynamics of an airframe. The states are the Earth coordinates , the body coordinates , the pitch angle , and the pitch rate . Figure 1 summarizes the relationship between the inertial and body frames, the flight path angle , the incidence angle , and the pitch angle .

**Figure 1: Airframe dynamics.**

We use a classic three-loop autopilot structure to control the flight path angle . This autopilot adjusts the flight path by delivering adequate bursts of normal acceleration (acceleration along ). In turn, normal acceleration is produced by adjusting the elevator deflection to cause pitching and vary the amount of lift. The autopilot uses Proportional-Integral (PI) control in the pitch rate loop and proportional control in the and loops. The closed-loop system (airframe and autopilot) are modeled in Simulink.

```
open_system('rct_airframeGS')
```

The airframe dynamics are nonlinear and the aerodynamic forces and moments depend on speed and incidence . To obtain suitable performance throughout the flight envelope, the autopilot gains must be adjusted as a function of and to compensate for changes in plant dynamics. This adjustment process is called "gain scheduling" and are called the scheduling variables.

Gain scheduling is a linear technique for controlling nonlinear or time-varying plants. The idea is to compute linear approximations of the plant at various operating conditions, tune the controller gains at each operating condition, and swap gains as a function of operating condition during operation. Conventional gain scheduling involves three major steps:

Trim and linearize the plant at each operating condition

Tune the controller gains for the linearized dynamics at each operating condition

Reconcile the gain values to provide smooth transition between operating conditions.

In this example, we combine Steps 2. and 3. by parameterizing the autopilot gains as first-order polynomials in
and directly tuning the polynomial coefficients for the entire flight envelope. This approach eliminates Step 3. and guarantees smooth gain variations as a function of
and
. Moreover, the gain schedule coefficients can be automatically tuned with `systune`.

Assume that the incidence varies between -20 and 20 degrees and that the speed varies between 700 and 1400 m/s. When neglecting gravity, the airframe dynamics are symmetric in so consider only positive values of . Use a 5-by-9 grid of linearly spaced pairs to cover the flight envelope:

nA = 5; % number of alpha values nV = 9; % number of V values [alpha,V] = ndgrid(linspace(0,20,nA)*pi/180,linspace(700,1400,nV));

For each flight condition , linearize the airframe dynamics at trim (zero normal acceleration and pitching moment). This requires computing the elevator deflection and pitch rate that result in steady and . To do this, first isolate the airframe model in a separate Simulink model.

```
open_system('rct_airframeTRIM')
```

Use `operspec` to specify the trim condition, use `findop` to compute the trim values of
and
, and linearize the airframe dynamics for the resulting operating point. See the "Trimming and Linearizing an Airframe" example in Simulink Control Design for details. Repeat these steps for the 45 flight conditions
.

% Compute trim condition for each (alpha,V) pair clear op for ct=1:nA*nV alpha_ini = alpha(ct); % Incidence [rad] v_ini = V(ct); % Speed [m/s] % Specify trim condition opspec = operspec('rct_airframeTRIM'); % Xe,Ze: known, not steady opspec.States(1).Known = [1;1]; opspec.States(1).SteadyState = [0;0]; % u,w: known, w steady opspec.States(3).Known = [1 1]; opspec.States(3).SteadyState = [0 1]; % theta: known, not steady opspec.States(2).Known = 1; opspec.States(2).SteadyState = 0; % q: unknown, steady opspec.States(4).Known = 0; opspec.States(4).SteadyState = 1; % TRIM Options = findopOptions('DisplayReport','off'); op(ct) = findop('rct_airframeTRIM',opspec,Options); end % Linearization I/Os io = [linio('rct_airframeTRIM/delta',1,'in');... % delta linio('rct_airframeTRIM/Airframe Model',3,'out');... % q linio('rct_airframeTRIM/Airframe Model',4,'out');... % az linio('rct_airframeTRIM/Airframe Model',5,'out')]; % gamma % Linearize at trim conditions G = linearize('rct_airframeTRIM',op,io); G = reshape(G,[nA nV]); G.u = 'delta'; G.y = {'q' 'az' 'gamma'};

This produces a 5-by-9 array of linearized plant models at the 45 flight conditions . The plant dynamics vary substantially across the flight envelope.

```
sigma(G), title('Variations in airframe dynamics')
```

The autopilot consists of four gains that must be "scheduled" (adjusted) as a function of and . Each "gain" is therefore a two-dimensional gain surface. As a first cut, seek gain surfaces with a simple multi-linear dependence on and :

.

These gain surfaces are modeled in Simulink as follows:

**Figure 2: Simulink model for the gain surface
.**

Use `gainsurf` to parameterize these gain surfaces in terms of the tunable coefficients
. To improve convergence of the tuning algorithm, it is recommended to replace
by normalized values ranging in [-1,1]:

% Subtract the mean value of alpha and divide by its half range Mean = 10*pi/180; % mean = 10 degrees HalfRange = Mean; % half range = 10 degrees alpha_n = (alpha - Mean)/HalfRange; % varies in [-1,1] % Subtract the mean value of V and divide by its half range Mean = (700+1400)/2; HalfRange = (1400-700)/2; V_n = (V - Mean)/HalfRange; % varies in [-1,1] % Create gain surfaces Kp = gainsurf('Kp', 0.1, alpha_n, V_n, alpha_n.*V_n); Ki = gainsurf('Ki', 2, alpha_n, V_n, alpha_n.*V_n); Ka = gainsurf('Ka', 0.001, alpha_n, V_n, alpha_n.*V_n); Kg = gainsurf('Kg', -1000, alpha_n, V_n, alpha_n.*V_n);

The initial values for the constant coefficient
are based on tuning results for
= 10 deg and
= 1000 m/s (mid-range design). Note that `Kp`, `Ki`,... are arrays of matrices (one per flight condition) parameterized by the tunable coefficients
. To facilitate visualization, use the `SamplingGrid` property to keep track of the dependence on
:

% Grid of alpha,V values SG = struct('alpha',alpha,'V',V); Kp.SamplingGrid = SG; Ki.SamplingGrid = SG; Ka.SamplingGrid = SG; Kg.SamplingGrid = SG;

Next construct a closed-loop model `T0` by connecting the linearized airframe model `G`, the second-order actuator model, and the autopilot gains `Kp`, `Ki`, `Ka`, `Kg` according to the block diagram `rct_airframeGS`. The software lets you manipulate the model arrays `G`, `Kp`, `Ki`,... as single entities (one block in the block diagram).

% Actuator model Act = tf(150^2,[1 2*0.7*150 150^2]); Act.u = 'u'; Act.y = 'delta_d'; % Controller elements Cq = pid(Kp,Ki); Cq.u = 'eq'; Cq.y = 'u'; Ca = ss(Ka); Ca.u = 'eaz'; Ca.y = 'q_ref'; Cg = ss(Kg); Cg.u = 'eg'; Cg.y = 'az_ref'; % Summing junctions S1 = sumblk('delta = delta_d + d'); S2 = sumblk('eq = q_ref + q'); S3 = sumblk('eaz = az_ref - az'); S4 = sumblk('eg = gamma_ref - gamma'); % Connect the blocks together T0 = connect(G,Cq,Ca,Cg,S1,S2,S3,S4,Act,... {'gamma_ref','az_ref','d'},{'gamma','az'})

T0 = 5x9 array of generalized continuous-time state-space models. Each model has 2 outputs, 3 inputs, 7 states, and between 4 and 16 blocks. Type "ss(T0)" to see the current value, "get(T0)" to see all properties, and "T0.Blocks" to interact with the blocks.

This creates a 5-by-9 array of closed-loop models parameterized by the tunable coefficients of the four gain surfaces.

`systune` can automatically tune the gain surface coefficients for the entire flight envelope. Use `TuningGoal` objects to specify the performance objectives:

loop: Track the setpoint with a 1 second response time, less than 2% steady-state error, and less than 30% peak error.

Req1 = TuningGoal.Tracking('gamma_ref','gamma',1,0.02,1.3); viewSpec(Req1)

loop: Ensure good disturbance rejection at low frequency (to track acceleration demands) and past 10 rad/s (to be insensitive to measurement noise).

% Note: The disturbance is injected at the az_ref location RejectionProfile = frd([0.02 0.02 1.2 1.2 0.1],[0 0.02 2 15 150]); Req2 = TuningGoal.Gain('az_ref','az',RejectionProfile); viewSpec(Req2)

loop: Ensure good disturbance rejection up to 10 rad/s

% Note: The disturbance d enters at the plant input Req3 = TuningGoal.Gain('d','az',600*tf([0.25 0],[0.25 1])); viewSpec(Req3)

Transients: Ensure a minimum damping ratio of 0.35 for oscillation-free transients

MinDamping = 0.35; Req4 = TuningGoal.Poles(0,MinDamping);

Using `systune`, tune the 16 gain surface coefficients to best meet these performance requirements at all 45 flight conditions.

T = systune(T0,[Req1 Req2 Req3 Req4]);

Final: Soft = 1.13, Hard = -Inf, Iterations = 78

The final value of the combined objective is close to 1, indicating that all requirements are nearly met. Visualize the resulting gain surfaces.

% Use the tuned values of the gain surface coefficients Kp = setBlockValue(Kp,T); Ki = setBlockValue(Ki,T); Ka = setBlockValue(Ka,T); Kg = setBlockValue(Kg,T); % Plot gain surfaces clf subplot(221), view(Kp), title('Kp') subplot(222), view(Ki), title('Ki') subplot(223), view(Ka), title('Ka') subplot(224), view(Kg), title('Kg')

First validate the tuned autopilot at the 45 flight conditions considered above. Plot the response to a step change in flight path angle and the response to a step disturbance in elevator deflection.

clf subplot(211), step(T('gamma','gamma_ref'),5), grid title('Tracking of step change in flight path angle') subplot(212), step(T('az','d'),3), grid title('Rejection of step disturbance at plant input')

The responses are satisfactory at all flight conditions. Next validate the autopilot against the nonlinear airframe model. First push the tuned gain surface coefficients to the Simulink model. The coefficients for the "Kp Gain" block are named "Kp_0", "Kp_1", "Kp_2", "Kp_3", and similarly for the other gain blocks.

[Kp_0,Kp_1,Kp_2,Kp_3] = gainsurfdata(Kp); [Ki_0,Ki_1,Ki_2,Ki_3] = gainsurfdata(Ki); [Ka_0,Ka_1,Ka_2,Ka_3] = gainsurfdata(Ka); [Kg_0,Kg_1,Kg_2,Kg_3] = gainsurfdata(Kg);

Now simulate the autopilot performance for a maneuver that takes the airframe through a large portion of its flight envelope.

% Initial conditions h_ini = 1000; alpha_ini = 0; v_ini = 700; % Simulate SimOut = sim('rct_airframeGS', 'ReturnWorkspaceOutputs', 'on'); % Extract simulation data SimData = get(SimOut,'sigsOut'); Sim_gamma = getElement(SimData,'gamma'); Sim_alpha = getElement(SimData,'alpha'); Sim_V = getElement(SimData,'V'); Sim_delta = getElement(SimData,'delta'); Sim_h = getElement(SimData,'h'); Sim_az = getElement(SimData,'az'); t = Sim_gamma.Values.Time; % Plot the main flight variables clf subplot(211) plot(t,Sim_gamma.Values.Data(:,1),'r--',t,Sim_gamma.Values.Data(:,2),'b'), grid legend('Commanded','Actual','location','SouthEast') title('Flight path angle \gamma in degrees') subplot(212) plot(t,Sim_delta.Values.Data), grid title('Elevator deflection \delta in degrees')

subplot(211) plot(t,Sim_alpha.Values.Data), grid title('Incidence \alpha in degrees') subplot(212) plot(t,Sim_V.Values.Data), grid title('Speed V in m/s')

subplot(211) plot(t,Sim_h.Values.Data), grid title('Altitude h in meters') subplot(212) plot(t,Sim_az.Values.Data), grid title('Normal acceleration a_z in g''s')

Tracking of the flight path angle profile remains good throughout the maneuver. Note that the variations in incidence and speed cover most of the flight envelope considered here ([-20,20] degrees for and [700,1400] for ). And while the autopilot was tuned for a nominal altitude of 3000 m, it fares well despite altitude changing from 1,000 to 10,000 m.

The nonlinear simulation results confirm that the gain-scheduled autopilot delivers consistently high performance throughout the flight envelope. The simple explicit formulas for the gain dependence on the scheduling variables is amenable to efficient hardware implementation. Alternatively, these formulas can be readily converted into 2D lookup tables for further adjustment.

Was this topic helpful?