簡體   English   中英

如何加快MATLAB集成?

[英]How to speed up MATLAB integration?

我有以下代碼:

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

其目標是使用特定控制律來模擬2自由度機械臂的控制。 運行模擬后得到的結果是正確的(我有一個我應該期望的輸出圖),但是要花一些時間才能完成!

有什么我可以做以加快這一過程的嗎?

為了提高Matlab中任何集成的計算速度,可以使用一些選項:

  1. 降低所需的精度(您已經完成了)
  2. 使用適合的積分器。 正如@sanchises所提到的,有時ode23可以比Matlab中的另一個ode求解器更長(例如,如果您的方程式很僵硬)。 您可以嘗試從文檔中確定最適合的求解器...或者直接嘗試所有解決方案!
  3. 最好的解決方案是使用編譯語言,例如C或Fortran,但目前為止最耗時。 如果集成只是Matlab程序的一部分,則可以使用Mex文件 ,僅將集成翻譯為已編譯的語言。 您還可以使用編譯語言創建動態庫,然后使用loadlibrary將其加載到Matlab中。 我使用負載庫和用Fortran編寫的集成例程來進行軌道和軌跡的集成,並且與Fortran和Matlab相比,我獲得了超過100倍的加速! 當然,從技術上講,集成不再存在於Matlab中。但是使用庫或Mex文件的技巧,您只能將程序的集成部分轉換為另一種語言! 有許多開源集成器可用,例如Fortran中的ODEPACKRKSUITE 然后,您只需要創建一個包裝器即可使用正確的語言來創建動態功能。

簡而言之,如果您打算大量使用此集成,我建議您使用編譯語言。 如果沒有,您應該使用Matlab,並且要耐心!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM