About CVXGEN: how to call a custom C-mex from an MATLAB Function block in simulink?

15 views (last 30 days)
Longgang
Longgang on 4 Sep 2014
Answered: Denis Gurchenkov on 23 Sep 2014
Hello guys,
I have a problem in using cvxgen to solve the optimizations problem in simulink. I have already realized it in matlab, then I try to write it in Matlab function block to make the simulink work. But I have failed in vars.u and vars.x definition. These variables are cells. My code is below:
function u = fcn(x) params.A = [1.00150264109249 0.0100050085084119 0 0.000145333065818179; 0.300578720162791 1.00150264109249 0 0.0290254704477249; -2.55073534681720e-05 -8.50868824878273e-08 1 0.00995009260135654; -0.00509424975054432 -2.55073534681720e-05 0 0.990035028922393;];
params.B = [-0.000122691855579919;-0.0245036379592154;4.21324033334155e-05;0.00841254387244088];
params.Q = [6600 0 0 0;0 170 0 0;0 0 37000 0;0 0 0 1];
params.Q_final = [877537.740423744 146063.123790212 1069634.53891539 389175.297932726;146063.123790212 27890.7378140523 202115.846410881 74275.1870320343;1069634.53891539 202115.846410881 2064016.94592117 565257.860616142;389175.297932726 74275.1870320343 565257.860616142 203316.293504707];
params.R = 1;
params.u_max = 24;
params.x_max = [0.174532925199433;3.82500000000000;0.993500000000000;2.50500000000000];
params.x_0 = x;
eml.extrinsic('csolve_mex');
status.optval = 0;
status.gap = 0;
status.steps = 0;
status.converged = 0;
vars.u_0 = 0;
vars.u_1 = 0;
vars.u_2 = 0;
vars.u_3 = 0;
vars.x_1 = [0;0;0;0];
vars.x_2 = [0;0;0;0];
vars.x_3 = [0;0;0;0];
vars.x_4 = [0;0;0;0];
% vars.u{1,1} = 0;
% vars.u{2,1} = 0;
% vars.u{3,1} = 0;
% vars.x{1, 1} = [0;0;0;0];
% vars.x{2, 1} = [0;0;0;0];
% vars.x{3, 1} = [0;0;0;0];
% vars.x{4, 1} = [0;0;0;0];
[vars, status] = csolve_mex(params);
u = vars.u_0;
end
Thanks

Answers (1)

Denis Gurchenkov
Denis Gurchenkov on 23 Sep 2014
It looks to me that the problem you are hitting is that cell arrays are not supported inside MATLAB Function Block. I see two workarounds you can use:
(1) Wrap the csolve_mex call into a .m file that takes non-cell-arrays as parameters, and call that .m file via coder.extrinsic. That is, create foo.m that contains all the code that you posted, and then, in the MATLAB Function block, do
coder.extrinsic('foo'); u = 0; % pre-define u to be of correct type/size [u] = foo();
where foo is
foo.m
function [vars, status] = foo ... [vars, status] = csolve_mex(params); u = vars.u_0; end
If you need to pass some parameters to csolve_mex, pass them to foo, and inside, pass them to csolve_mex. The trick is to avoid using cell arrays outside of foo. Since foo is marked as "extrinsic" in the block, you can use cell arrays inside it, but not in its parameters.
(2) do not use csolve_mex(), and instead generate a C entry point for csolve, and use coder.ceval() to call it from MATLAB Function block. I think CVXGEN can generate a .lib file and a .h file for you, then you will need to add those files to the simulation target parameters on the MATLAB function block, and then you can call the csolve entry point, something like
coder.ceval('csolve', coder.rref(params), coder.wref(vars), coder.wref(status));
This way is more complicated and you'd probably need to spend some time reading doc about coder.ceval, and also how to generate C library from CVXGEN and how to link it to the MATLAB function block.
Cheers,
Denis.

Tags

No tags entered yet.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by