在命令行窗口输入
>>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的版本要高一点(至少要比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的版本要高一些,感觉大概是这个原因。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删