Сгенерируйте код, чтобы вычислить оптимальные перемещения MPC в MATLAB

Этот пример показывает, как использовать команду mpcmoveCodeGeneration, чтобы сгенерировать код С, чтобы вычислить оптимальные перемещения MPC управления для приложений реального времени.

Модель объекта управления

Объект является одно входом, одно выводом, стабильный, 2-й порядок линейный объект.

plant = tf(5,[1 0.8 3]);

Преобразуйте объект в дискретное время, форму пространства состояний, и задайте нулевой вектор начальных состояний.

Ts = 1;      
plant = ss(c2d(plant,Ts));
x0 = zeros(size(plant.B,1),1);

Разработайте контроллер MPC

Создайте контроллер MPC с горизонтами по умолчанию.

mpcobj = mpc(plant,Ts);
-->The "PredictionHorizon" property of "mpc" object is empty. Trying PredictionHorizon = 10.
-->The "ControlHorizon" property of the "mpc" object is empty. Assuming 2.
-->The "Weights.ManipulatedVariables" property of "mpc" object is empty. Assuming default 0.00000.
-->The "Weights.ManipulatedVariablesRate" property of "mpc" object is empty. Assuming default 0.10000.
-->The "Weights.OutputVariables" property of "mpc" object is empty. Assuming default 1.00000.

Задайте контроллер, настраивающий веса.

mpcobj.Weights.MV = 0;
mpcobj.Weights.MVrate = 0.5;
mpcobj.Weights.OV = 1;

Задайте начальные ограничения на переменную, которой управляют, и объект вывод. Эти ограничения будут обновлены во время выполнения.

mpcobj.MV.Min = -1;
mpcobj.MV.Max = 1;
mpcobj.OV.Min = -1;
mpcobj.OV.Max = 1;

Моделируйте онлайновые ограничительные изменения с командой mpcmove

В симуляции с обратной связью ограничения обновлены и поданы в команду mpcmove в каждом интервале управления.

yMPCMOVE = [];
uMPCMOVE = [];

Установите время симуляции.

Tsim = 20;

Инициализируйте онлайновые ограничительные данные.

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];

Инициализируйте состояния объекта.

x = x0;

Инициализируйте состояния MPC.

xmpc = mpcstate(mpcobj);
-->Assuming output disturbance added to measured output channel #1 is integrated white noise.
-->The "Model.Noise" property of the "mpc" object is empty. Assuming white noise on each measured output channel.

Запустите симуляцию с обратной связью путем вызова mpcmove в цикле.

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

Подтвердите результаты симуляции с командой mpcmoveCodeGeneration

Чтобы подготовиться к генерации кода, который вычисляет перемещения оптимального управления из MATLAB, рекомендуется воспроизвести те же результаты управления с командой mpcmoveCodeGeneration перед использованием команды codegen от продукта MATLAB Coder.

yCodeGen = [];
uCodeGen = [];

Инициализируйте состояния объекта.

x = x0;

Создайте структуры данных, чтобы использовать с mpcmoveCodeGeneration using getCodeGenerationData.

[coredata,statedata,onlinedata] = getCodeGenerationData(mpcobj);

Запустите симуляцию с обратной связью путем вызова mpcmoveCodeGeneration в цикле.

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

Результаты симуляции идентичны тем, которые используют 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')

Сгенерируйте MEX-функцию от команды mpcmoveCodeGeneration

Чтобы сгенерировать код С от команды mpcmoveCodeGeneration, используйте команду codegen от продукта MATLAB Coder. В этом примере сгенерируйте MEX-функцию mpcmoveMEX, чтобы воспроизвести результаты симуляции в MATLAB. Можно изменить цель генерации кода на C/C++ статическая библиотека, динамическая библиотека, исполняемый файл, и т.д. при помощи различного набора настроек coder.config.

При генерации кода С для команды mpcmoveCodeGeneration:

  • Поскольку никакие проверки целостности данных не выполняются на входных параметрах, необходимо убедиться, что все входные данные имеют правильные типы, размерности и значения.

  • Необходимо задать первый входной параметр, mpcmove_struct, как константа при использовании команды codegen.

  • Второй входной параметр, mpcmove_state, обновлен командой и возвращен как второй вывод. В большинстве случаев вы не должны изменять его содержимое и должны просто пасовать назад его к команде в следующем интервале управления. Единственное исключение - когда пользовательская оценка состояния включена, в этом случае необходимо обеспечить оценку текущего состояния с помощью этого аргумента.

if ~license ('test', 'MATLAB_Coder')
    disp('MATLAB Coder(TM) is required to run this example.')
    return
end

Сгенерируйте MEX-функцию.

fun = 'mpcmoveCodeGeneration';
funOutput = 'mpcmoveMEX';
Cfg = coder.config('mex');
Cfg.DynamicMemoryAllocation = 'off';
codegen('-config',Cfg,fun,'-o',funOutput,'-args',...
    {coder.Constant(coredata),statedata,onlinedata});

Инициализируйте хранение данных.

yMEX = [];
uMEX = [];

Инициализируйте состояния объекта.

x = x0;

Используйте getCodeGenerationData, чтобы создать структуры данных, чтобы использовать с mpcmoveCodeGeneration.

[coredata,statedata,onlinedata] = getCodeGenerationData(mpcobj);

Запустите симуляцию с обратной связью путем вызывания сгенерированных функций mpcmoveMEX в цикле.

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

Результаты симуляции идентичны тем, которые используют 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')

Смотрите также

|

Похожие темы