Model predictive control - Hybrid models

In the standard MPC example, we illustrated some alternative approaches to setup and solve MPC problems in YALMIP. We will now use approximately the same code to solve hybrid MPC problems, i.e., problems involving piecewise affine and hybrid models.

The model we start with is a PWA system where the input matrix B depends on the first state.

yalmip('clear')
clear all

% Model data
A = [2 -1;1 0];
B1 = [1;0]; % Small gain for  x(1) > 0
B2 = [2;0]; % Larger gain for x(1) < 0
nx = 2; % Number of states
nu = 1; % Number of inputs

% MPC data
Q = eye(2);
R = 1;
N = 4;

High-level model

Setting up the MPC problem for this PWA system is almost identical to the LTI case, except for the logic part. The perhaps most high-level and natural way to model this in YALMIP is by using the or operator. Note the additional constraint added on the last state prediction. This is done to ensure that all expressions that are involved in logic expressions are explicitly bounded in the big-M modeling phase.

u = sdpvar(repmat(nu,1,N),repmat(1,1,N));
x = sdpvar(repmat(nx,1,N+1),repmat(1,1,N+1));

constraints = [];
objective   = 0;
for k = 1:N
 objective = objective + norm(Q*x{k},1) + norm(R*u{k},1);

 Model1 = [x{k+1} == A*x{k} + B1*u{k}, x{k}(1) >= 0];
 Model2 = [x{k+1} == A*x{k} + B2*u{k}, x{k}(1) <= 0];

 constraints = [constraints, Model1 | Model2, -1 <= u{k}<= 1, -5<=x{k}<=5];
end

constraints = [constraints , -5<=x{k+1}<=5];
controller = optimizer(constraints, objective,sdpsettings('verbose',1),x{1},u{1});

All hybrid modelling will be done automatically by YALMIP, and the end result is a mixed integer linear program, compiled in the controller object, which can be used for simulation, as described in the standard MPC example.

Manual generation of logic constraints

The model generated by the or operator is essentially equivalent to the following model, which more clearly indicates where binary variables are introduced in the model. Note that we generate an exclusive-or model instead, in order to limit the binry search-space as much as we can from a-priori knowledge.

u = sdpvar(repmat(nu,1,N),repmat(1,1,N));
x = sdpvar(repmat(nx,1,N+1),repmat(1,1,N+1));
d = binvar(repmat(2,1,N),repmat(1,1,N));

constraints = [];
objective   = 0;
for k = 1:N
 objective = objective + norm(Q*x{k},1) + norm(R*u{k},1);

 Model1 = [x{k+1} == A*x{k} + B1*u{k}, x{k}(1) >= 0];
 Model2 = [x{k+1} == A*x{k} + B2*u{k}, x{k}(1) <= 0];

 constraints = [constraints, implies(d{k}(1), Model1), implies(d{k}(2), Model2)];

 constraints = [constraints, sum(d{k}) == 1, -1 <= u{k}<= 1, -5<=x{k}<=5];
end

constraints = [constraints, -5 <= x{k+1} <= 5];
controller = optimizer(constraints, objective,sdpsettings('verbose',1),x{1},u{1});

Once again, we have created a controller object which can be used easily for simulation.

Beyond PWA models

This is actually all that needs to be said about hybrid modeling in YALMIP. You can use any of the logic constraints and structures to model your hybrid behaviour. As an example, let us add the constraint that the input is quantized in 0.1 levels. All that is needed is one extra line of code, and YALMIP will try to derive an as efficient model as possible.

u = sdpvar(repmat(nu,1,N),repmat(1,1,N));
x = sdpvar(repmat(nx,1,N+1),repmat(1,1,N+1));
d = binvar(repmat(2,1,N),repmat(1,1,N));

constraints = [];
objective   = 0;
for k = 1:N
 objective = objective + norm(Q*x{k},1) + norm(R*u{k},1);

 Model1 = [x{k+1} == A*x{k} + B1*u{k}, x{k}(1) >= 0];
 Model2 = [x{k+1} == A*x{k} + B2*u{k}, x{k}(1) <= 0];

 constraints = [constraints, implies(d{k}(1), Model1), implies(d{k}(2), Model2)];

 constraints = [constraints, sum(d{k}) == 1, -1 <= u{k}<= 1, -5<=x{k}<=5];

 constraints = [constraints,ismember(u{k},[-1:0.1:1])];
end

constraints = [constraints, -5 <= x{k+1} <= 5];
controller = optimizer(constraints, objective,sdpsettings('verbose',1),x{1},u{1});

The following model incorporates an avoidance constraint \( \left\lvert x-r\right\rvert \geq 0.1\), i.e., a small region around some central point \(r\) is considered dangerous and may not be entered. This is a non-convex constraint, but YALMIP can model this using the nonlinear operator framework. Hence we create a controller setup that takes the current state and the dangerous position \(r\), and returns a safe input.

u = sdpvar(repmat(nu,1,N),repmat(1,1,N));
x = sdpvar(repmat(nx,1,N+1),repmat(1,1,N+1));
d = binvar(repmat(2,1,N),repmat(1,1,N));
r = sdpvar(2,1);

constraints = [];
objective   = 0;
for k = 1:N
 objective = objective + norm(Q*x{k},1) + norm(R*u{k},1);

 Model1 = [x{k+1} == A*x{k} + B1*u{k}, x{k}(1) >= 0];
 Model2 = [x{k+1} == A*x{k} + B2*u{k}, x{k}(1) <= 0];


 constraints = [constraints, implies(d{k}(1), Model1), implies(d{k}(2), Model2)];

 constraints = [constraints, sum(d{k}) >= 1, -1 <= u{k}<= 1, -5 <= x{k} <= 5];
 constraints = [constraints,norm(x{k} - r,1) >= 0.1];
end

constraints = [constraints, -5 <= x{k+1} <= 5];
constraints = [constraints, -5 <= r <= 5];
controller = optimizer(constraints, objective,sdpsettings('verbose',1),[x{1};r],u{1});