summaryrefslogtreecommitdiffstats
path: root/templates/MPC_TUBE.m
blob: 9a630c153716f7bf4a44854a6d3fd6b77b599d98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2023, Amon Lahr, Simon Muntwiler, Antoine Leeman & Fabian Flürenbrock Institute for Dynamic Systems and Control, ETH Zurich.
%
% All rights reserved.
%
% Please see the LICENSE file that has been included as part of this package.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

classdef MPC_TUBE
    properties
        yalmip_optimizer
        K_tube
    end

    methods
        function obj = MPC_TUBE(Q,R,N,H_N,h_N,H_tube,h_tube,K_tube,params)
            obj.K_tube = K_tube;
    
            % YOUR CODE HERE
            nx = params.model.nx;
            nu = params.model.nu;

            A = params.model.A;
            B = params.model.B;

            [~,P,~] = dlqr(A,B,Q,R);

            V = sdpvar(repmat(nu,1,N),ones(1,N),'full');
            Z = sdpvar(repmat(nx,1,N+1),ones(1,N+1),'full');

            H_x = params.constraints.StateMatrix;
            h_x = params.constraints.StateRHS;
            H_u = params.constraints.InputMatrix;
            h_u = params.constraints.InputRHS;

            P_x_tightened = Polyhedron('A',H_x,'b',h_x).minus(Polyhedron('A',H_tube,'b',h_tube));
            H_z = P_x_tightened.A;
            h_z = P_x_tightened.b;

            P_u_tightened = Polyhedron('A',H_u,'b',h_u).minus(K_tube*Polyhedron('A',H_tube,'b',h_tube));
            H_v = P_u_tightened.A;
            h_v = P_u_tightened.b;

            X0 = sdpvar(nx,1,'full');
            constraints = [H_tube*(X0-Z{1}) <= h_tube];
            objective = 0;
            for k = 1:N
                constraints = [ ...
                    constraints, ...
                    Z{k+1} == A*Z{k} + B*V{k} , ...
%                     H_z * Z{k} <= h_z, ...
%                     H_v * V{k} <= h_v ...
                    H_x * Z{k} <= h_x, ...
                    H_u * V{k} <= h_u ...
                ];
                objective = objective + Z{k}'*Q*Z{k} + V{k}'*R*V{k};
            end
            constraints = [constraints, H_N * Z{end} <= h_N];
            objective = objective + Z{end}'*P*Z{end};

            opts = sdpsettings('verbose',1,'solver','quadprog');
            obj.yalmip_optimizer = optimizer(constraints,objective,opts,X0,{V{1} Z{1} objective});
        end

        function [u, ctrl_info] = eval(obj,x)
            %% evaluate control action by solving MPC problem, e.g.
            tic;
            [optimizer_out,errorcode] = obj.yalmip_optimizer(x);
            solvetime = toc;
            % YOUR CODE HERE
            [v0, z0, objective] = optimizer_out{:};
            u = obj.K_tube*(x-z0)+v0;


            feasible = true;
            if (errorcode ~= 0)
                feasible = false;
            end

            ctrl_info = struct('ctrl_feas',feasible,'objective',objective,'solvetime',solvetime);
        end
    end
end