Вызов fmincon из Симулинка
Я пытаюсь реализовать определенный тип модели прогнозирующего управления в рамках Simulink-Matlab. Для этого я планировал, чтобы динамическая модель в Simulink вызывала внешнюю S-функцию Matlab, которая в свою очередь запускает оптимизацию, которая вызывает другой файл Simulink. Следовательно, поток программы будет выглядеть следующим образом:
Simulink -> Matlab (fmincon
или же quadprog
) -> Симулинк.
Как видите, S-функция Matlab будет вызывать либо fmincon
или же quadprog
, но я хотел бы использовать fmincon для моего конкретного типа управления. Пожалуйста, пока игнорируйте любые проблемы, связанные с вычислительной эффективностью.
Я попробовал этот подход, но есть две очень четкие проблемы: во-первых, чтобы скомпилировать код без ошибок (в основном, получая файл.mex, мне пока не нужно программировать на C), я добавил команду
coder.extrinsic('fmincon');
Это было необходимо, потому что в противном случае Simulink не сможет скомпилировать mex-файл. Однако, если вы сделаете это, вы получите следующую ошибку:
Function handles cannot be passed to extrinsic functions.
Я попытался изменить свою функцию стоимости, вызывая Simulink, на другую, более простую функцию стоимости (x.^2
), но я все еще получаю ошибку.
Ища решение проблемы, я нашел такой же вопрос (т.е. как позвонить fmincon
из функции Matlab в Simulink) в блоге Mathworks, но без ответа ( https://uk.mathworks.com/matlabcentral/answers/65202-optimization-calling-fmincon-in-simulink-embedded-block).
Кто-нибудь может мне помочь? Заранее спасибо!
1 ответ
Вместо того, чтобы использовать coder.extrinsic
на fmincon
функции, я обычно пишу оболочку для задачи оптимизации, которую я должен решить как .m
Файловая функция для Matlab (а именно opt_problem
) и объявить coder.extrinsic('opt_problem')
в функции Matlab Simulink. Я приведу простой пример:
Рассмотрим эту модель Simulink, в которой на каждом шаге интеграции я хочу решить задачу линейной регрессии для некоторых сгенерированных данных. Задача оптимизации заключается в следующем:
minimize (y - m x - q)²
subject to 0 ≤ m ≤ 1
0 ≤ q ≤ 1
Схема действительно проста, ставим регрессор, звонки fmincon
:
Давайте посмотрим внутри регрессора:
function [m, q] = regressor(xs, ys, mic, qic)
coder.extrinsic('opt_problem'); % <- Informing the Coder
m = 0;
q = 0;
[m, q] = opt_problem(xs, ys, mic, qic); % <- Optimal problem wrapper call
end
эта функция только оболочка для внешней функции opt_problem
, Давайте посмотрим (у него две функции внутри):
function [m, q] = opt_problem(xs, ys, mic, qic)
fmincon_target = @(mq)(target(mq, xs, ys));
mq = fmincon(fmincon_target, [mic; qic], [], [], [], [], [0; 0], [1; 1]);
m = mq(1);
q = mq(2);
end
function r = target(mq, xs, ys)
r = norm(ys - xs.*mq(1) - mq(2));
end
и это все. Как вы можете видеть на рисунке, схема работает, и решение m, q
параметры (на двух дисплеях), которые минимизируют целевую функцию при соблюдении ограничений (m = 1.2 → m_opt = 1
).