Using boost::numeric::odeint inside the class

2019-08-07 01:26发布

问题:

For a simulation, I'm using boost::numeric::odeint but I'm having a problem. I'm using the integrate function inside a method of one of my classes and I'm having the error of "no matching function for call to integrate". To be more clear, here is a compressed version of my code:

#include "MotionGeneration.h"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>

typedef boost::array< double , 10 > state_type;

MotionGeneration::MotionGeneration(some_data) {
     //My constructor.
     //some_data assignment.
}

MotionGeneration::~MotionGeneration() {

}

double MotionGeneration::getError(double time) {
   //error calculation.
}

void MotionGeneration::execute(){
    state_type init_conf = { 0, -1.5708, 0, 0, 0, -1.5708, 0, -1.5708, 0, 0.5};
    boost::numeric::odeint::integrate(motionScheme, init_conf, 0.0, 1.0, 0.05, plot);
}

void MotionGeneration::motionScheme(const state_type &q, state_type &q_dot, double t){
     //Some long code goes here. Also I have some calls to some methods of this class. for example:
     double err = getError(t);          
}

void MotionGeneration::plot(const state_type &q , const double t){
    //some data pfintf here.
}

Please note that none of my methods are static and as a matter of fact, I can not use static method. When I build the project, I have the following error:

error: no matching function for call to `integrate(<unknown type>, state_type&, double, double, double, <unknown type>)'

I think it's a problem of having the system function as a class method but I don't know how to handle this situation.

回答1:

odeint needs an operator()( const state_type &x , state_type &dxdt , double dt )

In your case, MotionGenerator does not have this operator, but you can bind the method motionScheme

#include <functional>
namespace pl = std::placeholders;

// ...

// not tested
void MotionGeneration::execute()
{
    state_type init_conf = { 0, -1.5708, 0, 0, 0, -1.5708, 0, -1.5708, 0, 0.5};
    boost::numeric::odeint::integrate(
        std::bind(&MotionGenerator::motionScheme, *this , pl::_1 , pl::_2 , pl::_3 ) , init_conf, 0.0, 1.0, 0.05, plot);
}

```

But,it would be easy to rename your method motionScheme to operator(), and simply pass *this to integrate.

Edit: You can also use std::ref to avoid copies of your instance of MotionGenerator:

void MotionGeneration::execute()
{
    state_type init_conf = { 0, -1.5708, 0, 0, 0, -1.5708, 0, -1.5708, 0, 0.5};
    boost::numeric::odeint::integrate(
        std::bind(&MotionGenerator::motionScheme, std::ref(*this) , pl::_1 , pl::_2 , pl::_3 ) , init_conf, 0.0, 1.0, 0.05, plot);
}


标签: c++ oop boost ode