В этом примере показано, как сгенерировать код CUDA и использовать графический процессор для вычисления оптимальных перемещений MPC в MATLAB™, используя mpcmoveCodeGeneration
функция.
Исправьте начальное значение генератора для повторяемости.
rng(0);
Создайте строго соответствующий объект в дискретном времени с 10 состояниями, 3 входами и 3 выходами.
plant = drss(10,3,3); plant.D = 0;
Создайте случайное начальное состояние для объекта управления, которое будет использоваться позже в симуляции.
x0 = rand(10,1);
Создайте контроллер MPC со временем дискретизации 0,1 секунды и предсказаниями и управления по умолчанию.
mpcobj = mpc(plant,0.1);
-->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.
Задайте случайные ограничения для управляемых и измеренных переменных.
for ct=1:3 mpcobj.MV(ct).Min = -1*rand; mpcobj.MV(ct).Max = 1*rand; end for ct=1:3 mpcobj.OV(ct).Min = -10*rand; mpcobj.OV(ct).Max = 10*rand; end
Получите указатель на mpcobj
внутреннее состояние.
xmpc=mpcstate(mpcobj);
-->No sample time provided for plant model. Assuming sample time = controller's sample time = 0.1. -->Assuming output disturbance added to measured output channel #1 is integrated white noise. -->Assuming output disturbance added to measured output channel #2 is integrated white noise. -->Assuming output disturbance added to measured output channel #3 is integrated white noise. -->The "Model.Noise" property of the "mpc" object is empty. Assuming white noise on each measured output channel.
mpcmove
Перед генерацией кода симулируйте объект в замкнутом цикле с помощью mpcmove
чтобы убедиться, что поведение приемлемо. В данном примере результат симуляции с mpcmove
сохранен, поэтому его можно позже сравнить с симуляцией с помощью сгенерированного кода.
Инициализируйте массивы, которые будут хранить перемещения и выходы для последующей графического изображения.
yMV = []; uMV = [];
Инициализируйте состояния объекта управления и контроллера.
x = x0; xmpc.Plant=x0;
Запустите симуляцию с обратной связью путем вызова mpcmove
в цикле на 5 шагов.
for ct = 1:5 % Update and store the plant output. y = plant.C*x; yMV = [yMV y]; % Compute control actions with ref = ones(1,3) u = mpcmove(mpcobj,xmpc,y,ones(1,3)); % Update and store the plant state. x = plant.A*x + plant.B*u; uMV = [uMV u]; end
Сбросьте начальные условия контроллера.
xmpc.Plant=x0; xmpc.Disturbance=zeros(1,3); xmpc.LastMove=zeros(1,3);
Использование getCodeGenerationData
создать три структуры, необходимые для генерации кода и симуляции от объекта MPC и его начального состояния. The coredata
структура содержит основные параметры конфигурации контроллера MPC, которые являются постоянными во время исполнения. The statedata
структура содержит состояния контроллера MPC, такие как, например, состояние модели объекта управления, предполагаемое нарушение порядка, ковариационная матрица и последний ход управления. The onlinedata
структура содержит данные, которые вы должны обновлять на каждом контрольном интервале, такие как измерения и опорные сигналы, ограничения и веса модели.
[coredata,statedata,onlinedata] = getCodeGenerationData(mpcobj,'InitialState',xmpc);
Сохраните начальную структуру данных о состоянии для последующей повторной инициализации.
statedata0=statedata;
mpcmoveCodeGeneration
The mpcmoveCodeGeneration
функция позволяет моделировать контроллер MPC в замкнутом цикле способом, подобным mpcmove
. Это занимает три структуры данных контроллера, где statedata
и onlinedata
представление текущих значений состояний контроллера и входных сигналов, соответственно, и вычисление оптимального хода управления и нового значения состояний контроллера. Затем можно сгенерировать код из mpcmoveCodeGeneration
(в этом примере также код CUDA) и скомпилировать его в исполняемый файл (в этом примере один работает на графическом процессоре), который имеет те же входы и выходы и, следовательно, может быть вызван из MATLAB точно так же.
Инициализируйте массивы для хранения перемещений и выходов для последующей графического изображения.
yCDG = []; uCDG = [];
Инициализируйте состояния объекта управления и контроллера.
x = x0; statedata=statedata0;
Запустите симуляцию с обратной связью путем вызова mpcmoveCodeGeneration
в цикле на 5 шагов.
for ct = 1:5 % Update and store the plant output. y = plant.C*x; yCDG = [yCDG y]; % Update measured output and reference in online data. onlinedata.signals.ym = y; onlinedata.signals.ref = ones(1,3); % Compute control actions. [u,statedata] = mpcmoveCodeGeneration(coredata,statedata,onlinedata); % Update and store the plant state. x = plant.A*x + plant.B*u; uCDG = [uCDG u]; end
Создайте объект опции строения кодера GPU с помощью coder.gpuConfig
и сконфигурируйте опции генерации кода.
CfgGPU = coder.gpuConfig('mex'); CfgGPU.TargetLang = 'C++'; CfgGPU.EnableVariableSizing = false; CfgCPU.ConstantInputs = 'IgnoreValues';
Сгенерируйте MEX-функцию mympcmoveGPU
от mpcmoveCodeGeneration
Функция MATLAB, использование codegen
команда. Эта команда генерирует код CUDA и компилирует его, чтобы получить исполняемый файл MEX mympcmoveGPU
который работает на графическом процессоре.
codegen('-config',CfgGPU,'mpcmoveCodeGeneration','-o','mympcmoveGPU','-args',{coder.Constant(coredata),statedata,onlinedata});
Code generation successful.
mympcmoveGPU
Инициализируйте массивы, которые будут хранить перемещения и выходы для последующей графического изображения.
yGPU = []; uGPU = [];
Инициализируйте состояния объекта управления и контроллера.
x = x0; statedata=statedata0;
Запустите симуляцию с обратной связью, позвонив в мой mpcmoveGPU
в цикле на 5 шагов.
for ct = 1:5 % Update and store the plant output. y = plant.C*x; yGPU = [yGPU y]; % Update measured output and reference in online data. onlinedata.signals.ym = y; onlinedata.signals.ref = ones(1,3); % Compute control actions. [u,statedata] = mympcmoveGPU(coredata,statedata,onlinedata); % Update and store the plant state. x = plant.A*x + plant.B*u; uGPU = [uGPU u]; end
Создайте объект опции строения кодера с помощью coder.Config
и сконфигурируйте опции генерации кода.
CfgCPU = coder.config('mex'); CfgCPU.DynamicMemoryAllocation='off'; CfgCPU.EnableVariableSizing = false; CfgCPU.ConstantInputs = 'IgnoreValues';
Сгенерируйте MEX-функцию mympcmoveCPU
от mpcmoveCodeGeneration
Функция MATLAB, использование codegen
команда. Эта команда генерирует код С и компилирует его, чтобы получить исполняемый файл MEX mympcmoveCPU
который работает на центральном процессоре.
codegen('-config',CfgCPU,'mpcmoveCodeGeneration','-o','mympcmoveCPU','-args',{coder.Constant(coredata),statedata,onlinedata});
Code generation successful.
mympcmoveCPU
Инициализируйте массивы, которые будут хранить перемещения и выходы для последующей графического изображения.
yCPU = []; uCPU = [];
Инициализируйте состояния объекта управления и контроллера.
x = x0; statedata=statedata0;
Запустите симуляцию с обратной связью, позвонив в мой mpcmoveCPU
в цикле на 5 шагов.
for ct = 1:5 % Update and store the plant output. y = plant.C*x; yCPU = [yCPU y]; % Update measured output and reference in online data. onlinedata.signals.ym = y; onlinedata.signals.ref = ones(1,3); % Compute control actions. [u,statedata] = mympcmoveCPU(coredata,statedata,onlinedata); % Update and store the plant state. x = plant.A*x + plant.B*u; uCPU = [uCPU u]; end
Во-первых, сравните входы и выходы объекта, полученные из mpcmove, и те, которые получены с помощью графический процессор.
uGPU-uMV
ans = 3×5
10-15 ×
0.3886 0.1110 0.3886 -0.2220 -0.7772
-0.2776 -0.0555 -0.3886 -0.7494 0.0694
-0.0035 0.0555 0.2359 0.0278 -0.0833
yGPU-yMV
ans = 3×5
10-14 ×
0 -0.1110 -0.0333 -0.1332 -0.0333
0 -0.1776 -0.0444 -0.4219 -0.2665
0 -0.0222 0.0222 -0.0666 0.1332
Результаты симуляции идентичны, за исключением незначительных числовых ошибок, тем, кто использует mpcmove
.
uCPU-uMV
ans = 3×5
10-14 ×
0.0278 0.0389 -0.0167 -0.0389 -0.0167
0.0611 -0.0056 -0.0749 -0.1013 0.0291
0 0.0333 0.0833 -0.0111 -0.0611
yCPU-yMV
ans = 3×5
10-14 ×
0 0.0111 -0.0777 0.1554 -0.0444
0 0.2331 0 -0.2887 -0.1998
0 -0.1332 -0.0444 -0.1332 0.0666
Точно так же различие между результатами, полученными при запуске mpcmoveCodeGeneration
в MATLAB и выполнение сгенерированного кода на центральный процессор незначительно.
uCPU-uCDG
ans = 3×5
10-14 ×
0 -0.1554 -0.1887 -0.1055 -0.0500
-0.0444 0 -0.0111 -0.0985 -0.0180
0 0.0278 -0.0111 -0.0444 -0.1027
yCPU-yCDG
ans = 3×5
10-14 ×
0 -0.0555 0.4663 0.3997 0.3553
0 -0.1443 0.1332 0.0444 -0.2220
0 0.0666 0.0888 0.0666 0.3331