Вызов 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).

Другие вопросы по тегам