Double pendulum solution using GSL

前端 未结 2 1472
攒了一身酷
攒了一身酷 2020-12-22 06:01

I am learning to use GSL to solve ODE. I wanted to solve double pendulum problem using GSL ODE functions. I decided to use this equations:

相关标签:
2条回答
  • 2020-12-22 06:26

    You could also use C++ with odeint library if you are interested. For the double pendulum system. For matrices I use Eigen and for solving ODEs I use odeint , therefore this is the code for your problem.

    #include <iostream>
    #include <cmath>
    #include <Eigen/Dense>
    #include <boost/math/constants/constants.hpp>
    #include <boost/numeric/odeint.hpp>
    #include <iomanip>
    
    using namespace std;
    using namespace boost::numeric::odeint;
    
    
    typedef std::vector< double > state_type;
    
    
    void equations(const state_type &y, state_type &dy, double x)
    {
        const double m1(0.5), m2(0.5),
                     L1(0.1), L2(0.1),
                     g(9.81);
    
        Eigen::MatrixXd M(2, 2), C(2, 1), B(2,1);
    
        /*
          Theta 1 =  y[0]
         dTheta 1 =  y[1] = dy[0]
        ddTheta 1 = dy[1]
    
          Theta 2 =  y[2]
         dTheta 2 =  y[3] = dy[2]
        ddTheta 2 = dy[3]
        */
        double delta(y[0] - y[2]);
    
        M <<      (m1 + m2)*L1, m2*L2*cos(delta),
              m2*L1*cos(delta),            m2*L2;
    
    
        C <<  m2*L1*L2*y[3]*y[3]*sin(delta) + g*(m1 + m2)*sin(y[0]),
             -m2*L1*y[1]*y[1]*sin(delta)    +        m2*g*sin(y[2]);
    
    
        //#####################( ODE Equations )################################
        dy[0] = y[1];
        dy[2] = y[3];
    
        B = M.inverse() * (-C);
    
    
        dy[1] = B(0,0);
        dy[3] = B(1,0);
    
    }
    
    
    int main(int argc, char **argv)
    {
        const double dt = 0.01;
        runge_kutta_dopri5 < state_type > stepper;
        double pi = boost::math::constants::pi<double>();
    
        state_type y(4); 
        // initial values
        y[0] = pi/3.0;  //  Theta 1 
        y[1] = 0.0;     // dTheta 1
        y[2] = pi/4.0; //   Theta 2
        y[3] = 0.0;    //  dTheta 2
    
        for (double t(0.0); t <= 5; t += dt){
    
            cout << fixed << setprecision(2);
            std::cout << "t: " << t << "  Theta 1: " << y[0] << "   dTheta 1: " << y[1]
                      << "  Theta 2: " << y[2] << "  dTheta 2: " << y[3] << std::endl;
    
    
            stepper.do_step(equations, y, t, dt);
        }
    
    }
    

    The results are

    enter image description here

    0 讨论(0)
  • 2020-12-22 06:38

    It really is the order of arguments in y. In the cited source it was in the "natural" order, the reason for your mix is not really clear. Giving names to some sub-expressions, the ODE function might also be written as

    int func(double t, const double y[], double f[], void *params) {
    
    
        double th1 = y[0], w1 = y[1];
        double th2 = y[2], w2 = y[3];
    
        f[0] = w1; // dot theta_1 = omega_1
        f[2] = w2; // dot theta_2 = omega_2
    
        double del = th2 - th1;
        double den = (M1 + M2) - M2 * cos(del) * cos(del);
        double Lwws1 = L1 * (w1*w1) * sin(del);
        double Lwws2 = L2 * (w2*w2) * sin(del);
        double Gs1 = G*sin(th1), Gs2 = G*sin(th2);
    
        f[1] = (M2 * (Lwws1 + Gs2) * cos(del) + M2 * Lwws2 - (M1 + M2) * Gs1) / (L1*den);
    
        f[3] = (-M2 * Lwws2 * cos(del) + (M1 + M2) * ( Gs1 * cos(del) - Lwws1 - Gs2) / (L2*den);
    
        return GSL_SUCCESS;
    }
    

    Of course, this assumes that the initial point vector is defined as

        double y[4] = {S1_ANGLE,V1_INIT,S2_ANGLE,V2_INIT};
    

    and that the interpretation of the results corresponds to that.

    0 讨论(0)
提交回复
热议问题