简体   繁体   English

如何加快MATLAB集成?

[英]How to speed up MATLAB integration?

I have the following code: 我有以下代码:

function [] = Solver( t )

    %pre-declaration
    foo=[1,1,1];
    fooCell = num2cell(foo);
    [q, val(q), star]=fooCell{:};

    %functions used in prosomoiwsh
    syms q val(q) star;
    qd1=symfun(90*pi/180+30*pi/180*cos(q),q);
    qd2=symfun(90*pi/180+30*pi/180*sin(q),q);
    p1=symfun(79*pi/180*exp(-1.25*q)+pi/180,q);
    p2=symfun(79*pi/180*exp(-1.25*q)+pi/180,q);
    e1=symfun(val-qd1,q);
    e2=symfun(val-qd2,q);
    T1=symfun(log(-(1+star)/star),star);
    T2=symfun(log(star/(1-star)),star);

    %anonymous function handles
    lambda=[0.75;10.494441313222076];
    calcEVR_handles={@(t,x)[double(subs(diff(subs(T1,star,e1/p1),q)+subs(lambda(1)*T1,star,e1/p1),{diff(val,q);val;q},{x(2);x(1);t})),double(subs(diff(subs(T1,star,e1/p1),q)+subs(lambda(1)*T1,star,e1/p1),{diff(val,q);val;q},{0;x(1);t})),double(subs(double(subs(subs(diff(T1,star),star,e1/p1),{val;q},{x(1);t}))/p1,q,t))];@(t,x)[double(subs(diff(subs(T2,star,e2/p2),q)+subs(lambda(2)*T2,star,e2/p2),{diff(val,q);val;q},{x(4);x(3);t})),double(subs(diff(subs(T2,star,e2/p2),q)+subs(lambda(2)*T2,star,e2/p2),{diff(val,q);val;q},{0;x(3);t})),double(subs(double(subs(subs(diff(T2,star),star,e2/p2),{val;q},{x(3);t}))/p2,q,t))]};

    options = odeset('AbsTol',1e-1,'RelTol',1e-1);
    [T,x_r] = ode23(@prosomoiwsh,[0 t],[80*pi/180;0;130*pi/180;0;2.4943180186983711;11.216948999754299],options);

    save newresult T x_r

    function dx_th = prosomoiwsh(t,x_th)
        %declarations
        k=0.80773938740480955;
        nf=6.2860930902603602;
        hGa=0.16727117784664769;
        hGb=0.010886618389781832;
        dD=0.14062935253218495;
        s=0.64963817519705203;
        IwF={[4.5453398382686956 5.2541234145178066 -6.5853972592002235 7.695225990702979];[-4.4358339284697337 -8.1138542053372298 -8.2698210582548395 3.9739729629084071]};
        IwG={[5.7098975358444752 4.2470526600975802 -0.83412489434697168 0.53829395964565041] [1.8689492167233894 -0.0015017513794517434 8.8666804106266461 -1.0775021663921467];[6.9513235639494155 -0.8133752392893685 7.4032432556804162 3.1496138243338709] [5.8037182454981568 2.0933267947187457 4.852362963697928 -0.10745559204132382]};
        IbF={-1.2165533594615545;7.9215291787744917};
        IbG={2.8425752327892844 2.5931576770598168;9.4789237295474873 7.9378928037841252};
        p=2;
        m=2;
        signG=1;
        n_vals=[2;2];
        nFixedStates=4;
        gamma_nn=[0.31559428834175318;9.2037894041383641];
        th_star_guess=[2.4943180186983711;11.216948999754299];

        %solution
        x  = x_th(1:nFixedStates);
        th = x_th(nFixedStates+1:nFixedStates+p);

        f  = zeros(m,1);
        G  = zeros(m,m);
        ZF = zeros(p,m);
        ZG = zeros(p,m,m);

        for i=1:m
            [f(i), ZF(:,i)] = calculate_neural_output(x, IwF{i}, IbF{i}, th);
            for j=1:m
                [G(i,j), ZG(:,i,j)] = calculate_neural_output(x, IwG{i,j}, IbG{i,j}, th);
            end
        end

        detG = det(G);
        if m == 1
            adjG = 1;
        else
            adjG = detG*G^-1;
        end

        E = zeros(m,1);
        V = zeros(m,1);
        R = zeros(m,m);

        for i=1:m
            EVR=calcEVR_handles{i}(t,x);
            E(i)=EVR(1);
            V(i)=EVR(2);
            R(i,i)=EVR(3);
        end


        Rinv     = R^-1;
        prod_R_E = R*E;
        ub = f + Rinv * (V + k*E) + nf*prod_R_E;
        ua = - detG / (detG^2+dD) * (adjG * ub) ;
        u  = ua - signG * (hGa*(ua'*ua) + hGb*(ub'*ub)) * prod_R_E;

        dx_th = zeros(nFixedStates+p, 1); %preallocation

        %System in form (1) of the IEEE paper
        [vec_sys_f, vec_sys_G] = sys_f_G(x);
        dx_nm  = vec_sys_f + vec_sys_G*u;

        %Calculation of dx
        index_start = 1;
        index_end   = -1;
        for i=1:m
            index_end   = index_end + n_vals(i);
            for j=index_start:index_end
                dx_th(j) = x(j+1);
            end
            dx_th(index_end+1) = dx_nm(i);
            index_start = index_end + 2;
        end

        %Calculation of dth

        AFvalueT = zeros(p,m);
        for i=1:m
            AFvalueT(:,i) = 0;
            for j=1:m
                AFvalueT(:,i) = AFvalueT(:,i)+ZG(:,i,j)*ua(j);
            end
        end

        dx_th(nFixedStates+1:nFixedStates+p) = diag(gamma_nn)*( (ZF+AFvalueT)*prod_R_E -s*(th-th_star_guess) );
        display(t)
    end

    function [y, Z] = calculate_neural_output(input, Iw, Ib, state)
        Z = [tanh(Iw*input+Ib);1];
        y = state' * Z;
    end

    function [ f,g ] = sys_f_G( x )
        Iz1=0.96;
        Iz2=0.81;
        m1=3.2;
        m2=2.0;
        l1=0.5;
        l2=0.4;
        g=9.81;
        q1=x(1);
        q2=x(3);
        q1dot=x(2);
        q2dot=x(4);
        M=[Iz1+Iz2+m1*l1^2/4+m2*(l1^2+l2^2/4+l1*l2*cos(q2)),Iz2+m2*(l2^2/4+l1*l2*cos(q2)/2);Iz2+m2*(l2^2/4+l1*l2*cos(q2)/2),Iz2+m2*l2^2/4];
        c=0.5*m2*l1*l2*sin(q2);
        C=[-c*q2dot,-c*(q1dot+q2dot);c*q1dot,0];
        G=[0.5*m1*g*l1*cos(q1)+m2*g*(l1*cos(q1)+0.5*l2*cos(q1+q2));0.5*m2*g*l2*cos(q1+q2)];
        f=-M\(C*[q1dot;q2dot]+G);
        g=inv(M);
    end


end

Its target is to simulate the control of a 2-DOF robotic arm using a certain control law. 其目标是使用特定控制律来模拟2自由度机械臂的控制。 The results I get after running the simulation are correct(I have a graph of the output I should expect), but it takes ages to finish! 运行模拟后得到的结果是正确的(我有一个我应该期望的输出图),但是要花一些时间才能完成!

Is there anything I could do to speed up the process? 有什么我可以做以加快这一过程的吗?

In order to improve the computational speed of any integration in Matlab, a few options are available to you: 为了提高Matlab中任何集成的计算速度,可以使用一些选项:

  1. Reduce the required accuracy (which you already have done) 降低所需的精度(您已经完成了)
  2. Use an adapted integrator. 使用适合的积分器。 As mentioned by @sanchises, sometimes ode23 can be longer than another ode solver in Matlab (if your equation is stiff for instance). 正如@sanchises所提到的,有时ode23可以比Matlab中的另一个ode求解器更长(例如,如果您的方程式很僵硬)。 You could try to determine which solver is most adapted from the documentation... Or simply try them all! 您可以尝试从文档中确定最适合的求解器...或者直接尝试所有解决方案!
  3. The best solution, but by far the most time consuming, would be to use a compiled language, such as C or Fortran. 最好的解决方案是使用编译语言,例如C或Fortran,但目前为止最耗时。 If the integration is but a part of your Matlab program, you could use Mex files , and translate only the integration to a compiled language. 如果集成只是Matlab程序的一部分,则可以使用Mex文件 ,仅将集成翻译为已编译的语言。 You could also create dynamic libraries in your compiled language and load them in Matlab using loadlibrary . 您还可以使用编译语言创建动态库,然后使用loadlibrary将其加载到Matlab中。 I use loadlibrary and an integration routine written in Fortran for the integration of orbits and trajectories, and I get over 100 times speedup with Fortran vs. Matlab! 我使用负载库和用Fortran编写的集成例程来进行轨道和轨迹的集成,并且与Fortran和Matlab相比,我获得了超过100倍的加速! Of course, technically, the integration is not in Matlab anymore... But the library or Mex files trick allows you to only convert the integration part of your program to a different language! 当然,从技术上讲,集成不再存在于Matlab中。但是使用库或Mex文件的技巧,您只能将程序的集成部分转换为另一种语言! A number of open source integrators are available, such as ODEPACK or RKSUITE in Fortran. 有许多开源集成器可用,例如Fortran中的ODEPACKRKSUITE Then, you only need to create a wrapper and your dynamics function in the correct language. 然后,您只需要创建一个包装器即可使用正确的语言来创建动态功能。

So to put it in a nutshell, if you're going to use this integration a lot, I would advise using a compiled language. 简而言之,如果您打算大量使用此集成,我建议您使用编译语言。 If not, you should make do with Matlab, and be patient! 如果没有,您应该使用Matlab,并且要耐心!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM