www.gusucode.com > mpc_featured 案例源码 matlab代码程序 > mpc_featured/CodeGenerationOfComputingOptimalMPCMovesInMATLABExample.m
%% Generate Code To Compute Optimal MPC Moves in MATLAB % This example shows how to use the <docid:mpc_ref.bu5k6ul> command to % generate C code to compute optimal MPC control moves for real-time % applications. %% Plant Model % The plant is a single-input, single-output, stable, 2nd order linear % plant. plant = tf(5,[1 0.8 3]); %% % Convert the plant to discrete-time, state-space form, and specify a zero % initial states vector. Ts = 1; plant = ss(c2d(plant,Ts)); x0 = zeros(size(plant.B,1),1); %% MPC Controller Design % Create an MPC controller with default horizons. mpcobj = mpc(plant,Ts); %% % Specify controller tuning weights. mpcobj.Weights.MV = 0; mpcobj.Weights.MVrate = 0.5; mpcobj.Weights.OV = 1; %% % Specify initial constraints on the manipualted variable and plant output. % These constraints will be updated at run-time. mpcobj.MV.Min = -1; mpcobj.MV.Max = 1; mpcobj.OV.Min = -1; mpcobj.OV.Max = 1; %% Simulating Online Constraint Changes with |mpcmove| Command % In the closed-loop simulation, constraints are updated and fed into the % |mpcmove| command at each control interval. yMPCMOVE = []; uMPCMOVE = []; %% % Set the simulation time. Tsim = 20; %% % Initialize the online constraint data. MVMinData = -0.2-[1 0.95 0.9 0.85 0.8 0.75 0.7 0.65 0.6 0.55 0.5 ... 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1]; MVMaxData = 0.2+[1 0.95 0.9 0.85 0.8 0.75 0.7 0.65 0.6 0.55 0.5 ... 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1]; OVMinData = -0.2-[1 0.95 0.9 0.85 0.8 0.75 0.7 0.65 0.6 0.55 0.5 ... 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1]; OVMaxData = 0.2+[1 0.95 0.9 0.85 0.8 0.75 0.7 0.65 0.6 0.55 0.5 ... 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1]; %% % Initialize plant states. x = x0; %% % Initialize MPC states. xmpc = mpcstate(mpcobj); %% % Run a closed-loop simulation by calling |mpcmove| in a loop. options = mpcmoveopt; for ct = 1:round(Tsim/Ts)+1 % Update and store plant output. y = plant.C*x; yMPCMOVE = [yMPCMOVE y]; % Update constraints. options.MVMin = MVMinData(ct); options.MVMax = MVMaxData(ct); options.OutputMin = OVMinData(ct); options.OutputMax = OVMaxData(ct); % Compute control actions. u = mpcmove(mpcobj,xmpc,y,1,[],options); % Update and store plant state. x = plant.A*x + plant.B*u; uMPCMOVE = [uMPCMOVE u]; end %% Validate Simulation Results with |mpcmoveCodeGeneration| Command % To prepare for generating code that computes optimal control moves from % MATLAB, it is recommended to reproduce the same control results with the % |mpcmoveCodeGeneration| command before using the |codegen| command from % the MATLAB Coder product. yCodeGen = []; uCodeGen = []; %% % Initialize plant states. x = x0; %% % Use <docid:mpc_ref.bu5k6vr> to create data structures to use with % |mpcmoveCodeGeneration|. [coredata, statedata, onlinedata] = getCodeGenerationData(mpcobj); %% % Run a closed-loop simulation by calling |mpcmoveCodeGeneration| in a % loop. for ct = 1:round(Tsim/Ts)+1 % Update and store plant output. y = plant.C*x; yCodeGen = [yCodeGen y]; % Update measured output in online data. onlinedata.signals.ym = y; % Update reference in online data. onlinedata.signals.ref = 1; % Update constraints in online data. onlinedata.limits.umin = MVMinData(ct); onlinedata.limits.umax = MVMaxData(ct); onlinedata.limits.ymin = OVMinData(ct); onlinedata.limits.ymax = OVMaxData(ct); % Compute control actions. [u, statedata] = mpcmoveCodeGeneration(coredata, statedata, onlinedata); % Update and store plant state. x = plant.A*x + plant.B*u; uCodeGen = [uCodeGen u]; end %% % The simulation results are identical to those using |mpcmove|. t = 0:Ts:Tsim; figure; subplot(1,2,1) plot(t,yMPCMOVE,'--*',t,yCodeGen,'o'); grid legend('mpcmove','codegen') title('Plant Output') subplot(1,2,2) plot(t,uMPCMOVE,'--*',t,uCodeGen,'o'); grid legend('mpcmove','codegen') title('Controller Moves') %% Genarating MEX Function From |mpcmoveCodeGeneration| Command % To generate C code from the |mpcmoveCodeGeneration| command, use the % |codegen| command from the MATLAB Coder product. In this example, % generate a MEX function |mpcmoveMEX| to reproduce the simulation results % in MATLAB. You can change the code generation target to C/C++ static % library, dynamic library, executable, etc. by using a different set of % |coder.config| settings. % % When generating C code for the |mpcmoveCodeGeneration| command: %% % * Since no data integrity checks are performed on the input arguments, % you must make sure that all the input data has the correct types, % dimensions, and values. % % * You must define the first input argument, |mpcmove_struct|, as a % constant when using |codegen| command. % % * The second input argument, |mpcmove_state|, is updated by the command % and returned as the second output. In most cases, you do not need to % modify its contents and should simply pass it back to the command in the % next control interval. The only exception is when custom state estimation % is enabled, in which case you must provide the current state estimation % with this argument. if ~license ('test', 'MATLAB_Coder') disp('MATLAB Coder(TM) is required to run this example.') return end %% % Generate MEX function. fun = 'mpcmoveCodeGeneration'; funOutput = 'mpcmoveMEX'; Cfg = coder.config('mex'); Cfg.DynamicMemoryAllocation = 'off'; codegen('-config',Cfg,fun,'-o',funOutput,'-args',... {coder.Constant(coredata),statedata,onlinedata}); %% % Initialize data storage. yMEX = []; uMEX = []; % Initialize plant states. x = x0; %% % Use |getCodeGenerationData| to create data structures to use with % |mpcmoveCodeGeneration|. [coredata, statedata, onlinedata] = getCodeGenerationData(mpcobj); %% % Run a closed-loop simulation by calling the generated |mpcmoveMEX| % functions in a loop. for ct = 1:round(Tsim/Ts)+1 % Update and store the plant output. y = plant.C*x; yMEX = [yMEX y]; % Update measured output in online data. onlinedata.signals.ym = y; % Update reference in online data. onlinedata.signals.ref = 1; % Update constraints in online data. onlinedata.limits.umin = MVMinData(ct); onlinedata.limits.umax = MVMaxData(ct); onlinedata.limits.ymin = OVMinData(ct); onlinedata.limits.ymax = OVMaxData(ct); % Compute control actions. [u, statedata] = mpcmoveMEX(coredata, statedata, onlinedata); % Update and store the plant state. x = plant.A*x + plant.B*u; uMEX = [uMEX u]; end %% % The simulation results are identical to the those using |mpcmove|. figure; subplot(1,2,1) plot(t,yMPCMOVE,'--*',t,yMEX,'o'); grid legend('mpcmove','mex') title('Plant Output') subplot(1,2,2) plot(t,uMPCMOVE,'--*',t,uMEX,'o'); grid legend('mpcmove','mex') title('Controller Moves')