diff --git a/bindings/python/algorithm/expose-rnea.cpp b/bindings/python/algorithm/expose-rnea.cpp index ad64289f7df1e6316fad5b66c15c8ecfe203550f..576d4a38f13afdbbaa4fc00ea894f6c1a0750665 100644 --- a/bindings/python/algorithm/expose-rnea.cpp +++ b/bindings/python/algorithm/expose-rnea.cpp @@ -30,6 +30,16 @@ namespace se3 { return rnea(*model,*data,q,v,a); } + + static Eigen::VectorXd rnea_fext_proxy(const ModelHandler& model, + DataHandler & data, + const VectorXd_fx & q, + const VectorXd_fx & v, + const VectorXd_fx & a, + const std::vector<Force> & fext) + { + return rnea(*model,*data,q,v,a,fext); + } static Eigen::VectorXd nle_proxy(const ModelHandler& model, DataHandler & data, @@ -47,7 +57,16 @@ namespace se3 "Velocity v (size Model::nv)", "Acceleration a (size Model::nv)"), "Compute the RNEA, put the result in Data and return it."); + + bp::def("rnea",rnea_fext_proxy, + bp::args("Model","Data", + "Configuration q (size Model::nq)", + "Velocity v (size Model::nv)", + "Acceleration a (size Model::nv)", + "Vector of external forces expressed in the local frame of each joint (size Model::njoints)"), + "Compute the RNEA with external forces, put the result in Data and return it."); + bp::def("nle",nle_proxy, bp::args("Model","Data", "Configuration q (size Model::nq)", diff --git a/src/algorithm/rnea.hpp b/src/algorithm/rnea.hpp index c3bcbc36fd374f4035c989a53de5c34e26341908..9d2b9b5ac00a953566d54a33281cf3e6b30b49f7 100644 --- a/src/algorithm/rnea.hpp +++ b/src/algorithm/rnea.hpp @@ -39,6 +39,25 @@ namespace se3 const Eigen::VectorXd & v, const Eigen::VectorXd & a); + /// + /// \brief The Recursive Newton-Euler algorithm. It computes the inverse dynamics, aka the joint torques according to the current state of the system, the desired joint accelerations and the external forces. + /// + /// \param[in] model The model structure of the rigid body system. + /// \param[in] data The data structure of the rigid body system. + /// \param[in] q The joint configuration vector (dim model.nq). + /// \param[in] v The joint velocity vector (dim model.nv). + /// \param[in] a The joint acceleration vector (dim model.nv). + /// \param[in] fext Vector of external forces expressed in the local frame of the joints (dim model.njoints) + /// + /// \return The desired joint torques stored in data.tau. + /// + inline const Eigen::VectorXd & + rnea(const Model & model, Data & data, + const Eigen::VectorXd & q, + const Eigen::VectorXd & v, + const Eigen::VectorXd & a, + const std::vector<Force> & fext); + /// /// \brief Computes the non-linear effects (Corriolis, centrifual and gravitationnal effects), also called the biais terms \f$ b(q,\dot{q}) \f$ of the Lagrangian dynamics: /// <CENTER> \f$ \begin{eqnarray} M \ddot{q} + b(q, \dot{q}) = \tau \end{eqnarray} \f$ </CENTER> <BR> diff --git a/src/algorithm/rnea.hxx b/src/algorithm/rnea.hxx index f0eeaca52a6413b932737e31611c08596730a1a1..5d0524ad18a53009b1c4c8472357cc3c70401909 100644 --- a/src/algorithm/rnea.hxx +++ b/src/algorithm/rnea.hxx @@ -108,6 +108,34 @@ namespace se3 return data.tau; } + inline const Eigen::VectorXd & + rnea(const Model & model, Data & data, + const Eigen::VectorXd & q, + const Eigen::VectorXd & v, + const Eigen::VectorXd & a, + const std::vector<Force> & fext) + { + assert(fext.size() == model.joints.size()); + + data.v[0].setZero(); + data.a_gf[0] = -model.gravity; + + for( Model::JointIndex i=1;i<(Model::JointIndex)model.njoints;++i ) + { + RneaForwardStep::run(model.joints[i],data.joints[i], + RneaForwardStep::ArgsType(model,data,q,v,a)); + data.f[i] -= fext[i]; + } + + for( Model::JointIndex i=(Model::JointIndex)model.njoints-1;i>0;--i ) + { + RneaBackwardStep::run(model.joints[i],data.joints[i], + RneaBackwardStep::ArgsType(model,data)); + } + + return data.tau; + } + struct NLEForwardStep : public fusion::JointVisitor<NLEForwardStep> { typedef boost::fusion::vector< const se3::Model &, diff --git a/src/spatial/force.hpp b/src/spatial/force.hpp index d161b83b307f6427e21e2b16af942039a48da298..83d93d8746bd1263b9abdcc8d6ec3bd60d8eeeb1 100644 --- a/src/spatial/force.hpp +++ b/src/spatial/force.hpp @@ -127,10 +127,17 @@ namespace se3 */ Derived_t & operator= (const Derived_t & other) { return derived().__equl__(other); } - /** \brief replaces *this by *this + other. - * \return a reference to *this + /** + * \brief Replaces *this by *this + other. + * \return a reference to *this */ Derived_t & operator+= (const Derived_t & phi) { return derived().__pequ__(phi); } + + /** + * \brief Replaces *this by *this - other. + * \return a reference to *this + */ + Derived_t & operator-= (const Derived_t & phi) { return derived().__mequ__(phi); } /** \return an expression of the sum of *this and other */ @@ -307,6 +314,7 @@ namespace se3 ForceTpl & __equl__(const ForceTpl & other) { data = other.data; return *this; } ForceTpl & __pequ__ (const ForceTpl & phi) { data += phi.data; return *this; } + ForceTpl & __mequ__ (const ForceTpl & phi) { data -= phi.data; return *this; } ForceTpl __plus__(const ForceTpl & phi) const { return ForceTpl(data + phi.data); } ForceTpl __mult__(const double a) const { return ForceTpl(a*data); } ForceTpl __minus__() const { return ForceTpl(-data); } diff --git a/src/spatial/motion.hpp b/src/spatial/motion.hpp index a01f584cc42b3ecba874a59975e3041f764604a3..271f9d36019ea44d68079e66e6265508481bfcec 100644 --- a/src/spatial/motion.hpp +++ b/src/spatial/motion.hpp @@ -62,6 +62,7 @@ namespace se3 Derived_t operator+(const Derived_t & v2) const { return derived().__plus__(v2); } Derived_t operator-(const Derived_t & v2) const { return derived().__minus__(v2); } Derived_t & operator+=(const Derived_t & v2) { return derived().__pequ__(v2); } + Derived_t & operator-=(const Derived_t & v2) { return derived().__mequ__(v2); } bool isApprox (const Derived_t & other, const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const { return derived().isApprox_impl(other, prec);} @@ -192,6 +193,7 @@ namespace se3 MotionTpl __plus__(const MotionTpl & v2) const { return MotionTpl(data + v2.data); } MotionTpl __minus__(const MotionTpl & v2) const { return MotionTpl(data - v2.data); } MotionTpl& __pequ__(const MotionTpl & v2) { data += v2.data; return *this; } + MotionTpl& __mequ__(const MotionTpl & v2) { data -= v2.data; return *this; } Scalar dot(const Force & f) const { return data.dot(f.toVector()); } diff --git a/unittest/rnea.cpp b/unittest/rnea.cpp index 7d4990eb61541d9a6cf6d3b6e4ed92a778e24bb1..7398e97fba8f2caa7af0c288dd646c78560b06fa 100644 --- a/unittest/rnea.cpp +++ b/unittest/rnea.cpp @@ -131,4 +131,33 @@ BOOST_AUTO_TEST_CASE ( test_nle_vs_rnea ) BOOST_CHECK (tau_nle.isApprox(tau_rnea, 1e-12)); } + +BOOST_AUTO_TEST_CASE (test_rnea_with_fext) +{ + using namespace Eigen; + using namespace se3; + + Model model; + buildModels::humanoidSimple(model); + Data data_rnea_fext(model); + Data data_rnea(model); + + VectorXd q (VectorXd::Random(model.nq)); + q.segment<4>(3).normalize(); + + VectorXd v (VectorXd::Random(model.nv)); + VectorXd a (VectorXd::Random(model.nv)); + + std::vector<Force> fext(model.joints.size(), Force::Zero()); + + JointIndex rf = model.getJointId("rleg6_joint"); Force Frf = Force::Random(); + JointIndex lf = model.getJointId("lleg6_joint"); Force Flf = Force::Random(); + + rnea(model,data_rnea,q,v,a); + rnea(model,data_rnea_fext,q,v,a,fext); + + BOOST_CHECK(data_rnea.tau.isApprox(data_rnea_fext.tau)); + + +} BOOST_AUTO_TEST_SUITE_END ()