From 92d9019373471b4328915a7a605c686bf5bd0daf Mon Sep 17 00:00:00 2001 From: jcarpent <jcarpent@laas.fr> Date: Mon, 27 Apr 2015 14:19:33 +0200 Subject: [PATCH] [Incremental][C++] Add planar joint useful for mobile robots --- CMakeLists.txt | 1 + src/multibody/joint/joint-planar.hpp | 253 ++++++++++++++++++++++++++ src/multibody/joint/joint-variant.hpp | 5 +- 3 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 src/multibody/joint/joint-planar.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 621f88fbe..2b506f68f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ SET(${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS multibody/joint/joint-spherical.hpp multibody/joint/joint-spherical-ZYX.hpp multibody/joint/joint-prismatic.hpp + multibody/joint/joint-planar.hpp multibody/joint/joint-free-flyer.hpp multibody/joint/joint-variant.hpp multibody/joint/joint-generic.hpp diff --git a/src/multibody/joint/joint-planar.hpp b/src/multibody/joint/joint-planar.hpp new file mode 100644 index 000000000..d5ae56eea --- /dev/null +++ b/src/multibody/joint/joint-planar.hpp @@ -0,0 +1,253 @@ +#ifndef __se3_joint_planar_hpp__ +#define __se3_joint_planar_hpp__ + +#include "pinocchio/multibody/joint/joint-base.hpp" +#include "pinocchio/multibody/constraint.hpp" +#include "pinocchio/math/sincos.hpp" +#include "pinocchio/spatial/motion.hpp" +#include "pinocchio/spatial/inertia.hpp" + +namespace se3 +{ + + struct JointDataPlanar; + struct JointModelPlanar; + + struct JointPlanar + { + struct BiasZero + { + operator Motion () const { return Motion::Zero(); } + }; // struct BiasZero + + friend const Motion & operator+ ( const Motion& v, const BiasZero&) { return v; } + friend const Motion & operator+ ( const BiasZero&,const Motion& v) { return v; } + + struct MotionPlanar + { + typedef double Scalar_t; + typedef MotionTpl<Scalar_t> Motion; + + Scalar_t x_dot_, y_dot_, theta_dot_; + + MotionPlanar () : x_dot_(NAN), y_dot_(NAN), theta_dot_(NAN) {} + MotionPlanar (Scalar_t x_dot, Scalar_t y_dot, Scalar_t theta_dot) : x_dot_(x_dot), y_dot_(y_dot), theta_dot_(theta_dot) {} + + operator Motion() const + { + return Motion (Motion::Vector3(x_dot_, y_dot_, 0.), Motion::Vector3(0., 0., theta_dot_)); + } + }; // struct MotionPlanar + + friend const MotionPlanar operator+ (const MotionPlanar & m, const BiasZero &) + { return m; } + + friend Motion operator+ (const MotionPlanar & m1, const Motion & m2) + { + Motion result (m2); + result.linear ()[0] += m1.x_dot_; + result.linear ()[1] += m1.y_dot_; + + result.angular ()[2] += m1.theta_dot_; + + return result; + } + + struct ConstraintPlanar + { + public: + typedef double Scalar_t; + typedef MotionTpl<Scalar_t> Motion; + typedef ForceTpl<Scalar_t> Force; + typedef Motion::Matrix3 Matrix3; + typedef Motion::Vector3 Vector3; + + public: + + Motion operator* (const MotionPlanar & vj) const + { return vj; } + + + struct ConstraintTranspose + { + const ConstraintPlanar & ref; + ConstraintTranspose(const ConstraintPlanar & ref) : ref(ref) {} + + Force::Vector3 operator* (const Force & phi) + { + return Force::Vector3 (phi.linear()[0], phi.linear()[1], phi.angular()[2]); + } + + /* [CRBA] MatrixBase operator* (Constraint::Transpose S, ForceSet::Block) */ + template<typename D> + friend typename Eigen::Matrix <typename Eigen::MatrixBase<D>::Scalar, 3, -1> + operator*( const ConstraintTranspose &, const Eigen::MatrixBase<D> & F ) + { + typedef Eigen::Matrix<typename Eigen::MatrixBase<D>::Scalar, 3, -1> MatrixReturnType; + assert(F.rows()==6); + + MatrixReturnType result (3, F.cols ()); + result.template topRows <2> () = F.template topRows <2> (); + result.template bottomRows <1> () = F.template bottomRows <1> (); + return result; + } + }; // struct ConstraintTranspose + + ConstraintTranspose transpose () const { return ConstraintTranspose(*this); } + + operator ConstraintXd () const + { + Eigen::Matrix<Scalar_t,6,3> S; + S.block <3,3> (Inertia::LINEAR, 0).setZero (); + S.block <3,3> (Inertia::ANGULAR, 0).setZero (); + S(Inertia::LINEAR + 0,0) = 1.; + S(Inertia::LINEAR + 1,1) = 1.; + S(Inertia::ANGULAR + 2,2) = 1.; + return ConstraintXd(S); + } + + Eigen::Matrix <Scalar_t,6,3> se3Action (const SE3 & m) const + { + Eigen::Matrix <double,6,3> X_subspace; + X_subspace.block <3,2> (Motion::LINEAR, 0) = skew (m.translation ()) * m.rotation ().leftCols <2> (); + X_subspace.block <3,1> (Motion::LINEAR, 2) = m.rotation ().rightCols <1> (); + + X_subspace.block <3,2> (Motion::ANGULAR, 0) = m.rotation ().leftCols <2> (); + X_subspace.block <3,1> (Motion::ANGULAR, 2).setZero (); + + return X_subspace; + } + + }; // struct ConstraintPlanar + + template<typename D> + friend Motion operator* (const ConstraintPlanar &, const Eigen::MatrixBase<D> & v) + { + EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(D,3); + Motion result (Motion::Zero ()); + result.linear ().template head<2> () = v.template topRows<2> (); + result.angular ().template tail<1> () = v.template bottomRows<1> (); + return result; + } + + }; // struct JointPlanar + + Motion operator^ (const Motion & m1, const JointPlanar::MotionPlanar & m2) + { + Motion result; + + const Motion::Vector3 & m1_t = m1.linear(); + const Motion::Vector3 & m1_w = m1.angular(); + + result.angular () << m1_w(1) * m2.theta_dot_, - m1_w(0) * m2.theta_dot_, 0.; + result.linear () << m1_t(1) * m2.theta_dot_ - m1_w(2) * m2.y_dot_, - m1_t(0) * m2.theta_dot_ + m1_w(2) * m2.x_dot_, m1_w(0) * m2.y_dot_ - m1_w(1) * m2.x_dot_; + + return result; + } + + /* [CRBA] ForceSet operator* (Inertia Y,Constraint S) */ + Eigen::Matrix <Inertia::Scalar, 6, 3> operator* (const Inertia & Y, const JointPlanar::ConstraintPlanar &) + { + Eigen::Matrix <Inertia::Scalar, 6, 3> M; + const double mass = Y.mass (); + const Inertia::Vector3 & com = Y.lever (); + const Symmetric3 & inertia = Y.inertia (); + + M.topLeftCorner <3,3> ().setZero (); + M.topLeftCorner <2,2> ().diagonal ().fill (mass); + + Inertia::Vector3 mc (mass * com); + M.rightCols <1> ().head <2> () << mc(1), - mc(0); + + M.bottomLeftCorner <3,2> () << 0., mc(2), - mc(1), 0., mc(1), -mc(0); + M.rightCols <1> ().tail <3> () = inertia.data ().tail <3> (); + M.rightCols <1> ().head <2> () = mc.head <2> () * com(2); + M.rightCols <1> ().tail <1> () = -mc.head <2> ().transpose () * com.head <2> (); + + return M; + } + + namespace internal + { + template<> + struct ActionReturn<JointPlanar::ConstraintPlanar > + { typedef Eigen::Matrix<double,6,3> Type; }; + } + + template<> + struct traits<JointPlanar> + { + typedef JointDataPlanar JointData; + typedef JointModelPlanar JointModel; + typedef JointPlanar::ConstraintPlanar Constraint_t; + typedef SE3 Transformation_t; + typedef JointPlanar::MotionPlanar Motion_t; + typedef JointPlanar::BiasZero Bias_t; + typedef Eigen::Matrix<double,6,3> F_t; + enum { + NQ = 3, + NV = 3 + }; + }; + template<> struct traits<JointDataPlanar> { typedef JointPlanar Joint; }; + template<> struct traits<JointModelPlanar> { typedef JointPlanar Joint; }; + + struct JointDataPlanar : public JointDataBase<JointDataPlanar> + { + typedef JointPlanar Joint; + SE3_JOINT_TYPEDEF; + + typedef Motion::Scalar Scalar; + + typedef Eigen::Matrix<Scalar,6,6> Matrix6; + typedef Eigen::Matrix<Scalar,3,3> Matrix3; + typedef Eigen::Matrix<Scalar,3,1> Vector3; + + Constraint_t S; + Transformation_t M; + Motion_t v; + Bias_t c; + + JointDataPlanar () : M(1) {} + }; + + struct JointModelPlanar : public JointModelBase<JointModelPlanar> + { + typedef JointPlanar Joint; + SE3_JOINT_TYPEDEF; + + JointData createData() const { return JointData(); } + + void calc (JointData & data, + const Eigen::VectorXd & qs) const + { + Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q = qs.segment<NQ>(idx_q ()); + + double c_theta,s_theta; SINCOS (q(2), &s_theta, &c_theta); + + data.M.rotation ().topLeftCorner <2,2> () << c_theta, -s_theta, s_theta, c_theta; + data.M.translation ().head <2> () = q.head<2> (); + + } + + void calc (JointData & data, + const Eigen::VectorXd & qs, + const Eigen::VectorXd & vs ) const + { + Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q = qs.segment<NQ> (idx_q ()); + Eigen::VectorXd::ConstFixedSegmentReturnType<NV>::Type & q_dot = vs.segment<NQ> (idx_v ()); + + double c_theta,s_theta; SINCOS (q(2), &s_theta, &c_theta); + + data.M.rotation ().topLeftCorner <2,2> () << c_theta, -s_theta, s_theta, c_theta; + data.M.translation ().head <2> () = q.head<2> (); + + data.v.x_dot_ = q_dot(0); + data.v.y_dot_ = q_dot(1); + data.v.theta_dot_ = q_dot(2); + } + }; + +} // namespace se3 + +#endif // ifndef __se3_joint_planar_hpp__ diff --git a/src/multibody/joint/joint-variant.hpp b/src/multibody/joint/joint-variant.hpp index ab1337ac4..50bfd28d9 100644 --- a/src/multibody/joint/joint-variant.hpp +++ b/src/multibody/joint/joint-variant.hpp @@ -6,12 +6,13 @@ #include "pinocchio/multibody/joint/joint-spherical.hpp" #include "pinocchio/multibody/joint/joint-spherical-ZYX.hpp" #include "pinocchio/multibody/joint/joint-prismatic.hpp" +#include "pinocchio/multibody/joint/joint-planar.hpp" #include "pinocchio/multibody/joint/joint-free-flyer.hpp" namespace se3 { - typedef boost::variant< JointModelRX,JointModelRY,JointModelRZ , JointModelRevoluteUnaligned, JointModelSpherical, JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ, JointModelFreeFlyer> JointModelVariant; - typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ , JointDataRevoluteUnaligned, JointDataSpherical, JointDataSphericalZYX, JointDataPX, JointDataPY, JointDataPZ, JointDataFreeFlyer > JointDataVariant; + typedef boost::variant< JointModelRX, JointModelRY, JointModelRZ, JointModelRevoluteUnaligned, JointModelSpherical, JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ, JointModelFreeFlyer, JointModelPlanar> JointModelVariant; + typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ, JointDataRevoluteUnaligned, JointDataSpherical, JointDataSphericalZYX, JointDataPX, JointDataPY, JointDataPZ, JointDataFreeFlyer, JointDataPlanar > JointDataVariant; typedef std::vector<JointModelVariant> JointModelVector; typedef std::vector<JointDataVariant> JointDataVector; -- GitLab