diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e97b6c7ac8a8e15bc33a7b3257cb57b68589cd1..80ad03e7d096455a750c88cf33354447f1eaac0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ SET(${PROJECT_NAME}_HEADERS multibody/constraint.hpp multibody/joint.hpp multibody/model.hpp + multibody/visitor.hpp tools/timer.hpp ) diff --git a/src/multibody/visitor.hpp b/src/multibody/visitor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e5812b14e8c0113a9ca3f1b2dc628d8212358d41 --- /dev/null +++ b/src/multibody/visitor.hpp @@ -0,0 +1,60 @@ +#ifndef __se3_visitor_hpp__ +#define __se3_visitor_hpp__ + +#define BOOST_FUSION_INVOKE_MAX_ARITY 10 +#include <boost/fusion/include/invoke.hpp> +#include <boost/fusion/include/algorithm.hpp> + + +namespace boost { + namespace fusion { + template<typename T,typename V> + typename result_of::push_front<V const, T>::type + append(T const& t,V const& v) { return push_front(v,t); } + + template<typename T1,typename T2,typename V> + typename result_of::push_front<typename result_of::push_front<V const, T2>::type const, T1>::type + append2(T1 const& t1,T2 const& t2,V const& v) { return push_front(push_front(v,t2),t1); } + } +} + + +namespace se3 +{ + namespace fusion + { + namespace bf = boost::fusion; + + template<typename Visitor> + struct JointVisitor : public boost::static_visitor<> + { + template<typename D> + void operator() (const JointModelBase<D> & jmodel) const + { + JointDataVariant& jdataSpec = static_cast<const Visitor*>(this)->jdata; + + bf::invoke(&Visitor::template algo<D>, + bf::append2(jmodel, + boost::ref(boost::get<typename D::JointData&>(jdataSpec)), + static_cast<const Visitor*>(this)->args)); + } + + template<typename ArgsTmp> + static void run(const JointModelVariant & jmodel, + JointDataVariant & jdata, + ArgsTmp args) + { + return boost::apply_visitor( Visitor(jdata,args),jmodel ); + } + }; + + } // namespace fusion +} // namespace se3 + +#define JOINT_VISITOR_INIT(VISITOR) \ + VISITOR( JointDataVariant & jdata,ArgsType args ) : jdata(jdata),args(args) {} \ + using JointVisitor<VISITOR>::run; \ + JointDataVariant & jdata; \ + ArgsType args + +#endif // ifndef __se3_visitor_hpp__ diff --git a/unittest/rnea.cpp b/unittest/rnea.cpp index 4c5c0781f9212d79993d29d1cb7993a4956408e7..94eaccc59d00856ab86cf287ce6daa50ff223b80 100644 --- a/unittest/rnea.cpp +++ b/unittest/rnea.cpp @@ -1,80 +1,39 @@ #include "pinocchio/spatial/fwd.hpp" #include "pinocchio/spatial/se3.hpp" #include "pinocchio/multibody/joint.hpp" +#include "pinocchio/multibody/visitor.hpp" #include "pinocchio/multibody/model.hpp" #include <iostream> #include "pinocchio/tools/timer.hpp" -#define BOOST_FUSION_INVOKE_MAX_ARITY 10 -#include <boost/fusion/include/sequence.hpp> -#include <boost/fusion/include/make_vector.hpp> -#include <boost/fusion/include/next.hpp> -#include <boost/fusion/include/invoke.hpp> -#include <boost/fusion/view/joint_view.hpp> -#include <boost/fusion/include/joint_view.hpp> -#include <boost/fusion/algorithm.hpp> -#include <boost/fusion/container.hpp> - - -namespace boost { - namespace fusion { - template<typename T,typename V> - typename result_of::push_front<V const, T>::type - append(T const& t,V const& v) { return push_front(v,t); } - - template<typename T1,typename T2,typename V> - typename result_of::push_front<typename result_of::push_front<V const, T2>::type const, T1>::type - append2(T1 const& t1,T2 const& t2,V const& v) { return push_front(push_front(v,t2),t1); } - } -} namespace se3 { - namespace bf = boost::fusion; - - - struct RneaForwardStep : public boost::static_visitor<> + struct RneaForwardStep : public fusion::JointVisitor<RneaForwardStep> { + typedef boost::fusion::vector< const se3::Model&, + se3::Data&, + const int&, + const Eigen::VectorXd &, + const Eigen::VectorXd &, + const Eigen::VectorXd & + > ArgsType; - typedef bf::vector< const se3::Model& , - se3::Data& , - int, - const Eigen::VectorXd &, - const Eigen::VectorXd &, - const Eigen::VectorXd & - > Args; - Args args; - JointDataVariant & jdata; - - RneaForwardStep( JointDataVariant & jdata,Args args ) : args(args),jdata(jdata) {} - - template<typename D> - void operator() (const JointModelBase<D> & jmodel) const - { - bf::invoke(&RneaForwardStep::algo<D>, - bf::append2(jmodel,boost::ref(boost::get<typename D::JointData&>(jdata)),args)); - } + JOINT_VISITOR_INIT(RneaForwardStep); - static void run(const JointModelVariant & jmodel, - JointDataVariant & jdata, - Args args) - { - return boost::apply_visitor( RneaForwardStep(jdata,args),jmodel ); - } - template<typename JointModel> - static void algo(const se3::JointModelBase<JointModel> & jmodel, - se3::JointDataBase<typename JointModel::JointData> & jdata, - const se3::Model& model, - se3::Data& data, - const int &i, - const Eigen::VectorXd & q, - const Eigen::VectorXd & v, - const Eigen::VectorXd & a) + static int algo(const se3::JointModelBase<JointModel> & jmodel, + se3::JointDataBase<typename JointModel::JointData> & jdata, + const se3::Model& model, + se3::Data& data, + const int &i, + const Eigen::VectorXd & q, + const Eigen::VectorXd & v, + const Eigen::VectorXd & a) { using namespace Eigen; using namespace se3; @@ -95,48 +54,32 @@ namespace se3 if(parent>0) data.a[i] += data.liMi[i].actInv(data.a[parent]); data.f[i] = model.inertias[i]*data.a[i] + model.inertias[i].vxiv(data.v[i]); // -f_ext + return 0; } }; - - -struct RneaBackwardStep : public boost::static_visitor<> -{ - typedef bf::vector<const Model& , - Data& , - const int &> Args; - JointDataVariant& jdata; - Args args; - - RneaBackwardStep( JointDataVariant& jdata, Args args) - : jdata(jdata),args(args) {} - - template <typename D> - void operator()(const JointModelBase<D> & jmodel) const - { - bf::invoke(&RneaBackwardStep::algo<D>, - bf::append2(jmodel,boost::ref(boost::get<typename D::JointData&>(jdata)),args)); - } - - static void run( const JointModelVariant & jmodel, - JointDataVariant & jdata, - Args args) - { boost::apply_visitor( RneaBackwardStep(jdata,args),jmodel ); } - - template<typename JointModel> - static void algo(const JointModelBase<JointModel> & jmodel, - JointDataBase<typename JointModel::JointData> & jdata, - const Model& model, - Data& data, - int i) + struct RneaBackwardStep : public fusion::JointVisitor<RneaBackwardStep> { - const Model::Index & parent = model.parents[i]; - jmodel.jointForce(data.tau) = jdata.S().transpose()*data.f[i]; - if(parent>0) data.f[parent] += data.liMi[i].act(data.f[i]); - } -}; + typedef boost::fusion::vector<const Model&, + Data&, + const int &> ArgsType; + + JOINT_VISITOR_INIT(RneaBackwardStep); + + template<typename JointModel> + static void algo(const JointModelBase<JointModel> & jmodel, + JointDataBase<typename JointModel::JointData> & jdata, + const Model& model, + Data& data, + int i) + { + const Model::Index & parent = model.parents[i]; + jmodel.jointForce(data.tau) = jdata.S().transpose()*data.f[i]; + if(parent>0) data.f[parent] += data.liMi[i].act(data.f[i]); + } + }; } // namespace se3 @@ -149,7 +92,7 @@ struct RneaBackwardStep : public boost::static_visitor<> int main() { #ifdef __SSE3__ -_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); #endif @@ -209,17 +152,17 @@ _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); StackTicToc timer(StackTicToc::US); timer.tic(); SMOOTH(1000) { - for( int i=1;i<model.nbody;++i ) - { - RneaForwardStep::run(model.joints[i],data.joints[i], - RneaForwardStep::Args(model,data,i,q,v,a)); - } - - for( int i=model.nbody-1;i>0;--i ) - { - RneaBackwardStep::run(model.joints[i],data.joints[i], - RneaBackwardStep::Args(model,data,i)); - } + for( int i=1;i<model.nbody;++i ) + { + RneaForwardStep::run(model.joints[i],data.joints[i], + RneaForwardStep::ArgsType(model,data,i,q,v,a)); + } + + for( int i=model.nbody-1;i>0;--i ) + { + RneaBackwardStep::run(model.joints[i],data.joints[i], + RneaBackwardStep::ArgsType(model,data,i)); + } } timer.toc(std::cout,1000);