Skip to content
Snippets Groups Projects
visitor.hpp 3.4 KiB
Newer Older
//
// Copyright (c) 2015 CNRS
// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
//
// This file is part of Pinocchio
// Pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// Pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.

#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>
#include "pinocchio/multibody/joint/joint-variant.hpp"

    // Append the element T at the front of boost fusion vector V.
    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); }

    // Append the elements T1 and T2 at the front of boost fusion vector V.
    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>,
			       boost::ref(boost::get<typename D::JointDataDerived>(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 );
      }
    };


    template<typename Visitor>
    struct JointModelVisitor : public boost::static_visitor<>
    {
      template<typename D>
      void operator() (const JointModelBase<D> & jmodel) const
      {
        bf::invoke(&Visitor::template algo<D>,
                   bf::append(boost::ref(jmodel),
                              static_cast<const Visitor*>(this)->args));
      }

      template<typename ArgsTmp>
      static void run(const JointModelVariant & jmodel,
          ArgsTmp args)
      {
  return boost::apply_visitor( Visitor(args),jmodel );
      }
    };
  
  } // namespace fusion
} // namespace se3

#define JOINT_VISITOR_INIT(VISITOR)					\
  VISITOR( JointDataVariant & jdata,ArgsType args ) : jdata(jdata),args(args) {} \
  using se3::fusion::JointVisitor< VISITOR >::run;			\

#define JOINT_MODEL_VISITOR_INIT(VISITOR)         \
  VISITOR(ArgsType args ) : args(args) {} \
  using se3::fusion::JointModelVisitor< VISITOR >::run;      \
  ArgsType args