This example shows how to model a scalar gain *K* with a bilinear dependence on two scheduling variables,
and *V*, as follows:

For this example,
is an angle of incidence that ranges from 0 to 15 degrees, and *V* is a speed that ranges from 300 to 600 m/s. The coefficients
are the tunable parameters of this variable gain.

Create a grid of design points,
, that are linearly spaced in
and *V*. These design points are where you will tune the gain surface coefficients.

[alpha,V] = ndgrid(0:5:15,300:100:600);

These arrays, `alpha` and `V`, represent the independent variation of the two scheduling variables, each across its full range.

When you tune the gain surface coefficients with `systune`, you might obtain better solver performance by normalizing the scheduling variables to fall within the interval [-1,1]. Scale the
and *V* grid to fall within this range.

alphaN = alpha/15;
VN = (V-450)/150;

Create the tunable gain surface sampled at the grid of
values:

In this expansion, the basis functions are:

Specify the values of the basis functions over the
.

F1 = alphaN;
F2 = VN;
F3 = alphaN.*VN;
K = gainsurf('K',1,F1,F2,F3)

K =
4x4 array of generalized matrices with 1 rows, 1 columns, and the following blocks:
K_0: Scalar parameter, 1 occurrences.
K_1: Scalar parameter, 1 occurrences.
K_2: Scalar parameter, 1 occurrences.
K_3: Scalar parameter, 1 occurrences.
Type "double(K)" to see the current value, "get(K)" to see all properties, and "K.Blocks" to interact with the blocks.

`K` is an array of generalized matrices. Each element in `K` corresponds to
for a particular
pair, and depends on the tunable coefficients `K_0`,...,|K_3|.

Associate the independent variable values with the corresponding values of `K`.

K.SamplingGrid = struct('alpha',alpha,'V',V);

The `SamplingGrid` property keeps track of the scheduling variable values associated with each entry in `K`. This association is convenient for tracing results back to independent variable values. For instance, you can use `view(K)` to inspect the tuned values of the gain surface after tuning. When you do so, `view` takes the axis range and labels from the entries in `SamplingGrid`. For this example, instead of tuning, manually set the values of the tunable blocks to non-zero values. View the resulting gain surface as a function of the scheduling variables.

values = struct('K_0',1,'K_1',-1,'K_2',0.1,'K_3',-0.2);
Ktuned = setBlockValue(K,values);
view(Ktuned)

The variable names and values that you specified in the `SamplingGrid` property are used to scale and label the axes.

You can use `K` as a tunable gain to build a control system with gain-scheduled tunable components. For example, use `K` to create a gain-scheduled low-pass filter.

F = tf(K,[1 K]);

You can use gain surfaces as arguments to model creation commands like `tf` the same way you would use numeric arguments. The resulting filter is a generalized state-space (`genss`) model array that depends on the four coefficients of the gain surface.

Use model interconnection commands (such as `connect` and `feedback`) to combine `F` with an array of plant models sampled at the same values of
and *V*. You can then use `systune` to tune the gain-scheduled controller to meet your design requirements. Because you normalized the scheduling variables to model the tunable gain, you must adjust the coefficient values in the implementation of your tuned controller.