使用MATLAB Coder Generation将m语言转化为C++过程遇到的问题及解决

目录

一、MATLAB Coder的使用步骤:

 二、遇到的问题

三、Matlab版本问题


一、MATLAB Coder的使用步骤:

在命令行窗口输入

>>coder

建议: 在定义 (一维) 变量数组的数据类型及大小时,建议定义为 double(1 × :inf),避免在数组运算过程中由于引入新的定义的中间变量数组,导致数组计算的等式左右两端数组大小不对等

下一步,

 

②:         在点击“Generate”后也存在许多报错,需要按照提示修改函数.m代码

         下面列出一些我遇到是问题及解决方案:

 二、遇到的问题

        1.以我的部分代码(自定义的MPC函数中调用quadprog函数求解)为例:

  ......

     %新的A,B,C矩阵
    A_cell = cell(2,2);
    B_cell = cell(2,1);
    A_cell{1,1} = a;
    A_cell{1,2} = b;
    A_cell{2,1} = zeros(Nu,Nx);
    A_cell{2,2} = eye(Nu);
    B_cell{1,1} = b;
    B_cell{2,1} = eye(Nu);
    A = cell2mat(A_cell);
    B = cell2mat(B_cell);
    C = [eye(Nx), zeros(Nx,Nu)];
    
    %PHI矩阵及THETA矩阵
    PHI_cell = cell(Np,1);
    THETA_cell = cell(Np,Nc);
    for j = 1:1:Np
        PHI_cell{j,1} = C*A^j;%cell的引用必须用大括号{},否则被看做double类型
        for k = 1:1:Nc
            if k<=j
                THETA_cell{j,k} = C*A^(j-k)*B;%左下角矩阵填充
            else
                THETA_cell{j,k} = zeros(Nx,Nu);%矩阵左上角均为0
            end
        end
    end
    PHI = cell2mat(PHI_cell);%size(PHI) = [Nx*Np Nx+Nu]
    THETA = cell2mat(THETA_cell);%size(THETA) = [Nx*Np Nu*(Nc+1)]
    
    %%二次型目标函数的相关矩阵
    H_cell = cell(2,2);
    H_cell{1,1} = THETA'*Q*THETA + R;
    H_cell{1,2} = zeros(Nu*Nc,1);
    H_cell{2,1} = zeros(1,Nu*Nc);
    H_cell{2,2} = row;%row松弛因子,为了能够得到最优解,防止出现无解的情况
    H = cell2mat(H_cell);
    
    %误差E矩阵
    E = PHI*kesi;%预测时域内的跟踪误差
    
    %g矩阵
    g_cell = cell(1,2);
    g_cell{1,1} = 2*E'*Q*THETA;
    g_cell{1,2} = 0;
    g = cell2mat(g_cell);
    
    %%约束条件的相关矩阵
    
    %A_I矩阵
    A_t = zeros(Nc,Nc);   %下三角矩阵
    for p = 1:1:Nc
        for q = 1:1:Nc
            if q <= p
                A_t(p,q) = 1;
            else
                A_t(p,q) = 0;
            end
        end
    end
    A_I = kron(A_t,eye(Nu));
    
    %Ut矩阵
    Ut = kron(ones(Nc,1),U);
    
    %控制量和控制量变化量的约束
    Umin = kron(ones(Nc,1),u_min);
    Umax = kron(ones(Nc,1),u_max);
    delta_Umin = kron(ones(Nc,1),delta_min);
    delta_Umax = kron(ones(Nc,1),delta_max);
    
    %用于quadprog函数不等式约束Ax<=b的矩阵A和向量b
    A_cons_cell = {A_I  zeros(Nu*Nc,1);-A_I  zeros(Nu*Nc,1)}; %为了和H的列数匹配,新添加一列0
    b_cons_cell = {Umax - Ut;-Umin+Ut};
    A_cons = cell2mat(A_cons_cell);
    b_cons = cell2mat(b_cons_cell);
    
    
    %△U的上下边界
    lb = [delta_Umin;0];%;(求解方程)状态量下界,包含控制时域内控制增量和松弛因子
    ub = [delta_Umax;10];%;(求解方程)状态量上界,包含控制时域内控制增量和松弛因子  

    %开始求解过程
    options = optimset('Algorithm','interior-point-convex');

    %↑内点法求解二次规划问题
     delta_U = quadprog(H,g,A_cons,b_cons,[],[],lb,ub,[],options);

       编译代码时 遇到“‘cell2mat’及'quadprog' ‘optimset’is not supported for code generation”的问题,这是因为MATLAB自己封装的函数是不支持C++代码生成的,需要将其定义为外部函数,即使用coder.extrinsic声明一下。并且:

参考Generate Code for quadprog- MATLAB & Simulink- MathWorks 中国

 将函数optimset 改为 optimoptions:

        2.编译代码时 遇到“Expected either a logical, char, int, fi, single, or double. Found an mxArray. MxArrays are returnedfrom calls to the MATLAB interpreter and are not supported inside expressions. They may only beused on the right-hand side of assignments and as arguments to extrinsic functions.”

 

         这是因为在编译过程中,编译器将函数的求解值(这里是delta_U)定义为mxArray类型,mxArray类型的变量只能放在等式的右边,不能被赋值(赋值都是double类型的数值,不等同)。因此,初始化被赋为mxArray的变量,初始化之后系统将其划定为double类型,就可以进行运算了:

 

         3.“cell2mat”和“quadprog”不能被生成C++

 在网上看到了关于quadprog的解释:

因此,将所有的cell转化为固定大小的mat类型 ;另外,将quadprog函数注释掉了,目前没有解决quadprog的C++表示问题。(目前还在学习阶段,希望能够得到大神的解答!!)

修改后的代码为:

A = zeros(5);
    B = zeros(5,2);%在编译生成代码时,cell类型不适用,只能用已知大小的数值矩阵
    
    %新的A,B,C矩阵
    A(1:3,1:3) = a;
    A(1:3,4:5) = b;
    A(4:5,4:5) = eye(Nu);
    B(1:3,:)= b;
    B(4:5,:) = eye(Nu);

    C = [eye(Nx), zeros(Nx,Nu)];

    
    %PHI矩阵及THETA矩阵
%     PHI_cell = cell(Np,1);
%     THETA_cell = cell(Np,Nc);
    PHI = zeros(Np*Nx,5);
    THETA = zeros(Np*Nx,Nc*Nu);
    for j = 1:1:Np
        PHI((j*Nx-(Nx-1)):j*Nx,1:5) = C*A^j;%cell的引用必须用大括号{},否则被看做double类型
        for k = 1:1:Nc
            if k<=j
                THETA((j*Nx-(Nx-1)):j*Nx,(k*Nu-(Nu-1)):k*Nu) = C*A^(j-k)*B;%左下角矩阵填充
            else
                THETA((j*Nx-(Nx-1)):j*Nx,(k*Nu-(Nu-1)):k*Nu) = zeros(Nx,Nu);%矩阵左上角均为0
            end
        end
    end

    
    %%二次型目标函数的相关矩阵
    H = zeros(61);
    H(1:60,1:60)= THETA'*Q*THETA + R;
    H(1:60,61) = zeros(Nu*Nc,1);
    H(61,1:60) = zeros(1,Nu*Nc);
    H(61,61) = row;%row松弛因子,为了能够得到最优解,防止出现无解的情况
    
    %误差E矩阵
    E = PHI*kesi;%预测时域内的跟踪误差
    
    %g矩阵
    g = zeros(1,61);
    g(1:60) = 2*E'*Q*THETA;
    g(61) = 0;
    
    %%约束条件的相关矩阵
    
    %A_I矩阵
    A_t = zeros(Nc,Nc);   %下三角矩阵
    for p = 1:1:Nc
        for q = 1:1:Nc
            if q <= p
                A_t(p,q) = 1;
            else
                A_t(p,q) = 0;
            end
        end
    end
    A_I = kron(A_t,eye(Nu));
    
    %Ut矩阵
    Ut = kron(ones(Nc,1),U);
    
    %控制量和控制量变化量的约束
    Umin = kron(ones(Nc,1),u_min);
    Umax = kron(ones(Nc,1),u_max);
    delta_Umin = kron(ones(Nc,1),delta_min);
    delta_Umax = kron(ones(Nc,1),delta_max);
    
    %用于quadprog函数不等式约束Ax<=b的矩阵A和向量b
    A_cons = zeros(Nu*Nc*2,Nu*Nc+1);
    A_cons(1:Nu*Nc,1:Nu*Nc) = A_I;
    A_cons((Nu*Nc+1):(2*Nu*Nc), (Nu*Nc+1):(2*Nu*Nc)) = -A_I;
    b_cons = zeros(Nu*Nc*2,1);
    b_cons(1:Nu*Nc,1) = Umax - Ut;
    b_cons((Nu*Nc+1):(2*Nu*Nc),1) = -Umin+Ut;
    
    
    %△U的上下边界
    lb = [delta_Umin;0];%;(求解方程)状态量下界,包含控制时域内控制增量和松弛因子
    ub = [delta_Umax;10];%;(求解方程)状态量上界,包含控制时域内控制增量和松弛因子
    
     coder.extrinsic('optimoptions');
     coder.extrinsic('quadprog');
    %开始求解过程
%     options = optimoptions('quadprog','Algorithm','interior-point-convex' );
%     %options = optimoptions('quadprog','MaxIterations',100);%有效集法求解二次规划问题目前已经没有
%     %↑内点法求解二次规划问题
%     delta_U = quadprog(H,g,A_cons,b_cons,[],[],lb,ub,[],options);

三、Matlab版本问题

        建议:Matlab的版本要高一点(至少要比Visual Studio的版本高),我在之前Matlab 和VS都是2019版本,可是按照【详细记录】Visual Studio 2019+matlab2017b mex无法正常使用,找不到已安装的编译器_老子姓李!的博客-CSDN博客_matlab visual文章进行MATLAB和Visual Studio的环境配置及验证,在命令行窗口输入

>>mex -setup C++

显示

“找到已安装的编译器 'Microsoft Visual C++ 2019 (C)'。 
MEX 配置为使用 'Microsoft Visual C++ 2019 (C)' 以进行 C 语言编译。”

但是在MATLAB Coder生成代码时不能成功,显示“??? The extrinsic function 'ce112mat' is not available for standalone code generation.”:

     但是由上面我们已知:有些函数虽然是不支持内部代码生成的,但将其定义为外部函数,使用coder.extrinsic声明一下即可通过编译,为什么会在生成代码的时候报错呢?

     后来下载了MATLAB 2022a版本,在生成代码时没有报错,看到很多文章说Matlab的版本要高一些,感觉大概是这个原因。

 

  • 14
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
要将MATLAB代码换为C语言,可以使用MATLAB中的附加app,MATLAB Coder。该工具可以将MATLAB代码换为C语言C++代码。它可以帮助开发人员更快地将MATLAB代码换为可在其他平台上运行的C语言代码。 在MATLAB中,如果要将MATLAB代码换为C语言代码,需要在换之前先定义相应的数据类型。例如,对于一个数组a,可以在MATLAB使用a(i)而不需要事先声明,但在换时,需要手动定义a的数据类型。例如,可以使用以下代码将MATLAB中的代码换为C语言代码: a = [0.0, 0.0, 0.0, 0.0]; for i = 1:m a(i) = u(i) * h; end 这段MATLAB代码首先声明了一个数组a,并将其初始化为全零。然后,通过for循环将u(i)乘以h的结果赋值给a(i)。可以通过MATLAB Coder将这段代码换为C语言代码。 MATLAB代码为C语言的具体步骤如下: 1. 打开MATLAB Coder附加app; 2. 在MATLAB代码框中输入要换的代码,注意要将整个代码作为一个函数; 3. 选择换选项和目标语言C语言; 4. 点击“生成代码”按钮,即可生成C语言代码。 通过这些步骤,您可以将MATLAB代码换为C语言代码,以便在其他平台上使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [如何使用MATLAB coder将MATLAB代码换成C/C++语言(详细图文教程)](https://blog.csdn.net/suxiao6666/article/details/125228471)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Matlab 代码 成 C/C++ 代码](https://blog.csdn.net/weixin_47156401/article/details/120718020)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锅小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值