From be3c965c4efc7e50e13be975a8a85546de75b291 Mon Sep 17 00:00:00 2001
From: jcarpent <jcarpent@laas.fr>
Date: Mon, 27 Apr 2015 15:59:25 +0200
Subject: [PATCH] [Incremental][C++] Add complete translational joint

---
 CMakeLists.txt                            |   1 +
 src/multibody/joint/joint-translation.hpp | 199 +++++++++++++++++++++
 src/multibody/joint/joint-variant.hpp     |   5 +-
 unittest/joints.cpp                       | 200 ++++++++++++++++++++++
 4 files changed, 403 insertions(+), 2 deletions(-)
 create mode 100644 src/multibody/joint/joint-translation.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b506f68f..605620891 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,7 @@ SET(${PROJECT_NAME}_MULTIBODY_JOINT_HEADERS
   multibody/joint/joint-spherical-ZYX.hpp
   multibody/joint/joint-prismatic.hpp
   multibody/joint/joint-planar.hpp
+  multibody/joint/joint-translation.hpp
   multibody/joint/joint-free-flyer.hpp
   multibody/joint/joint-variant.hpp
   multibody/joint/joint-generic.hpp
diff --git a/src/multibody/joint/joint-translation.hpp b/src/multibody/joint/joint-translation.hpp
new file mode 100644
index 000000000..27dd44f2d
--- /dev/null
+++ b/src/multibody/joint/joint-translation.hpp
@@ -0,0 +1,199 @@
+#ifndef __se3_joint_translation_hpp__
+#define __se3_joint_translation_hpp__
+
+#include "pinocchio/multibody/joint/joint-base.hpp"
+#include "pinocchio/multibody/constraint.hpp"
+#include "pinocchio/spatial/inertia.hpp"
+#include "pinocchio/spatial/skew.hpp"
+
+namespace se3
+{
+
+  struct JointDataTranslation;
+  struct JointModelTranslation;
+
+  struct JointTranslation
+  {
+    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 MotionTranslation
+    {
+      MotionTranslation ()                   : v (Motion::Vector3 (NAN, NAN, NAN)) {}
+      MotionTranslation (const Motion::Vector3 & v) : v (v)  {}
+      MotionTranslation (const MotionTranslation & other) : v (other.v)  {}
+      Motion::Vector3 v;
+
+      Motion::Vector3 & operator() () { return v; }
+      const Motion::Vector3 & operator() () const { return v; }
+
+      operator Motion() const
+      {
+        return Motion (v, Motion::Vector3::Zero ());
+      }
+
+      MotionTranslation & operator= (const MotionTranslation & other)
+      {
+        v = other.v;
+        return *this;
+      }
+    }; // struct MotionTranslation
+
+    friend const MotionTranslation operator+ (const MotionTranslation & m, const BiasZero &)
+    { return m; }
+
+    friend Motion operator+ (const MotionTranslation & m1, const Motion & m2)
+    {
+      return Motion (m2.linear () + m1.v, m2.angular ());
+    }
+
+    struct ConstraintTranslationSubspace
+    {
+    public:
+
+      Motion operator* (const MotionTranslation & vj) const
+      { return Motion (vj (), Motion::Vector3::Zero ()); }
+
+      ConstraintTranslationSubspace () {}
+
+      struct ConstraintTranspose
+      {
+        const ConstraintTranslationSubspace & ref;
+        ConstraintTranspose(const ConstraintTranslationSubspace & ref) : ref(ref) {}
+
+        Force::Vector3 operator* (const Force & phi)
+        {
+          return phi.linear ();
+        }
+
+
+        /* [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 )
+        {
+          assert(F.rows()==6);
+          return  F.template middleRows <3> (Inertia::LINEAR);
+        }
+      }; // struct ConstraintTranspose
+
+      ConstraintTranspose transpose () const { return ConstraintTranspose(*this); }
+
+      operator ConstraintXd () const
+      {
+        Eigen::Matrix<double,6,3> S;
+        S.block <3,3> (Inertia::LINEAR, 0).setIdentity ();
+        S.block <3,3> (Inertia::ANGULAR, 0).setZero ();
+        return ConstraintXd(S);
+      }
+
+      Eigen::Matrix <double,6,3> se3Action (const SE3 & m) const
+      {
+        Eigen::Matrix <double,6,3> M;
+        M.block <3,3> (Motion::LINEAR, 0) = m.rotation ();
+        M.block <3,3> (Motion::ANGULAR, 0).setZero ();
+
+        return M;
+      }
+
+    }; // struct ConstraintTranslationSubspace
+
+    template<typename D>
+    friend Motion operator* (const ConstraintTranslationSubspace & S, const Eigen::MatrixBase<D> & v)
+    {
+      EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(D,3);
+      return Motion (v, Motion::Vector3::Zero ());
+    }
+
+  }; // struct JointTranslation
+
+  Motion operator^ (const Motion & m1, const JointTranslation::MotionTranslation & m2)
+  {
+    return Motion (m1.angular ().cross (m2.v), Motion::Vector3::Zero ());
+  }
+
+  /* [CRBA] ForceSet operator* (Inertia Y,Constraint S) */
+  Eigen::Matrix <double, 6, 3> operator* (const Inertia & Y, const JointTranslation::ConstraintTranslationSubspace & S)
+  {
+    Eigen::Matrix <double, 6, 3> M;
+    M.block <3,3> (Inertia::ANGULAR, 0) = alphaSkew(Y.mass (), Y.lever ());
+    //    M.block <3,3> (Inertia::LINEAR, 0) = Y.mass () * Inertia::Matrix3::Identity ();
+    M.block <3,3> (Inertia::LINEAR, 0).setZero ();
+    M.block <3,3> (Inertia::LINEAR, 0).diagonal ().fill (Y.mass ());
+
+    return M;
+  }
+
+  namespace internal
+  {
+    template<>
+    struct ActionReturn<JointTranslation::ConstraintTranslationSubspace >
+    { typedef Eigen::Matrix<double,6,3> Type; };
+  }
+
+
+  template<>
+  struct traits<JointTranslation>
+  {
+    typedef JointDataTranslation JointData;
+    typedef JointModelTranslation JointModel;
+    typedef JointTranslation::ConstraintTranslationSubspace Constraint_t;
+    typedef SE3 Transformation_t;
+    typedef JointTranslation::MotionTranslation Motion_t;
+    typedef JointTranslation::BiasZero Bias_t;
+    typedef Eigen::Matrix<double,6,3> F_t;
+    enum {
+      NQ = 3,
+      NV = 3
+    };
+  };
+  
+  template<> struct traits<JointDataTranslation> { typedef JointTranslation Joint; };
+  template<> struct traits<JointModelTranslation> { typedef JointTranslation Joint; };
+
+  struct JointDataTranslation : public JointDataBase<JointDataTranslation>
+  {
+    typedef JointTranslation Joint;
+    SE3_JOINT_TYPEDEF;
+
+    typedef Eigen::Matrix<double,6,6> Matrix6;
+    typedef Eigen::Matrix<double,3,3> Matrix3;
+    typedef Eigen::Matrix<double,3,1> Vector3;
+
+    Constraint_t S;
+    Transformation_t M;
+    Motion_t v;
+    Bias_t c;
+
+    JointDataTranslation () : M(1) {}
+  };
+
+  struct JointModelTranslation : public JointModelBase<JointModelTranslation>
+  {
+    typedef JointTranslation Joint;
+    SE3_JOINT_TYPEDEF;
+
+    JointData createData() const { return JointData(); }
+
+    void calc (JointData & data,
+               const Eigen::VectorXd & qs) const
+    {
+      data.M.translation (qs.segment<NQ>(idx_q ()));
+    }
+    void calc (JointData & data,
+               const Eigen::VectorXd & qs,
+               const Eigen::VectorXd & vs ) const
+    {
+      data.M.translation (qs.segment<NQ> (idx_q ()));
+      data.v () = vs.segment<NQ> (idx_v ());
+    }
+  };
+  
+} // namespace se3
+
+#endif // ifndef __se3_joint_translation_hpp__
diff --git a/src/multibody/joint/joint-variant.hpp b/src/multibody/joint/joint-variant.hpp
index 50bfd28d9..951bbd122 100644
--- a/src/multibody/joint/joint-variant.hpp
+++ b/src/multibody/joint/joint-variant.hpp
@@ -7,12 +7,13 @@
 #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-translation.hpp"
 #include "pinocchio/multibody/joint/joint-free-flyer.hpp"
 
 namespace se3
 {
-  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 boost::variant< JointModelRX, JointModelRY, JointModelRZ, JointModelRevoluteUnaligned, JointModelSpherical, JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ, JointModelFreeFlyer, JointModelPlanar, JointModelTranslation> JointModelVariant;
+  typedef boost::variant< JointDataRX, JointDataRY, JointDataRZ, JointDataRevoluteUnaligned, JointDataSpherical, JointDataSphericalZYX, JointDataPX, JointDataPY, JointDataPZ, JointDataFreeFlyer, JointDataPlanar, JointDataTranslation> JointDataVariant;
 
   typedef std::vector<JointModelVariant> JointModelVector;
   typedef std::vector<JointDataVariant> JointDataVector;
diff --git a/unittest/joints.cpp b/unittest/joints.cpp
index 25f84f77c..cae6b6e6e 100644
--- a/unittest/joints.cpp
+++ b/unittest/joints.cpp
@@ -9,6 +9,7 @@
 #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-translation.hpp"
 #include "pinocchio/multibody/model.hpp"
 #include "pinocchio/algorithm/rnea.hpp"
 #include "pinocchio/algorithm/crba.hpp"
@@ -406,6 +407,205 @@ BOOST_AUTO_TEST_CASE ( test_crba )
 
 BOOST_AUTO_TEST_SUITE_END ()
 
+BOOST_AUTO_TEST_SUITE ( JointTranslation )
+
+BOOST_AUTO_TEST_CASE ( test_kinematics )
+{
+  using namespace se3;
+
+  typedef Motion::Vector3 Vector3;
+  typedef Motion::Vector6 Vector6;
+
+  Motion expected_v_J (Motion::Zero ());
+  Motion expected_c_J (Motion::Zero ());
+
+  SE3 expected_configuration (SE3::Identity ());
+
+  JointDataTranslation joint_data;
+  JointModelTranslation joint_model;
+
+  joint_model.setIndexes (0, 0, 0);
+
+  Vector3 q (Vector3::Zero());
+  Vector3 q_dot (Vector3::Zero());
+
+  // -------
+  q = Vector3 (0., 0., 0.);
+  q_dot = Vector3 (0., 0., 0.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation());
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation ());
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector());
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector());
+
+  // -------
+  q = Vector3 (1., 0., 0.);
+  q_dot = Vector3 (1., 0., 0.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  expected_configuration.translation () << 1, 0, 0;
+
+  expected_v_J.linear () << 1., 0., 0.;
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation(), 1e-12);
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation (), 1e-12);
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector(), 1e-12);
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector(), 1e-12);
+
+  // -------
+  q = Vector3 (0., 1., 0.);
+  q_dot = Vector3 (0., 1., 0.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  expected_configuration.translation () << 0, 1., 0;
+
+  expected_v_J.linear () << 0., 1., 0.;
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation(), 1e-12);
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation (), 1e-12);
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector(), 1e-12);
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector(), 1e-12);
+
+  // -------
+  q = Vector3 (0., 0., 1.);
+  q_dot = Vector3 (0., 0., 1.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  expected_configuration.translation () << 0, 0, 1;
+
+  expected_v_J.linear () << 0., 0., 1.;
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation(), 1e-12);
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation (), 1e-12);
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector(), 1e-12);
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector(), 1e-12);
+
+  // -------
+  q = Vector3 (1., 1., 1.);
+  q_dot = Vector3 (1., 1., 1.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  expected_configuration.translation () << 1., 1., 1.;
+  expected_v_J.linear () << 1., 1., 1.;
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation(), 1e-10);
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation (), 1e-10);
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector(), 1e-10);
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector(), 1e-10);
+
+  // -------
+  q = Vector3 (1., 1.5, 1.9);
+  q_dot = Vector3 (2., 3., 1.);
+
+  joint_model.calc (joint_data, q, q_dot);
+
+  printOutJointData <JointDataTranslation> (q, q_dot, joint_data);
+
+  expected_configuration.translation () = q;
+  expected_v_J.linear () = q_dot;
+
+  is_matrix_absolutely_closed (expected_configuration.rotation (), joint_data.M.rotation(), 1e-10);
+  is_matrix_absolutely_closed (expected_configuration.translation (), joint_data.M.translation (), 1e-10);
+  is_matrix_absolutely_closed (expected_v_J.toVector (), ((Motion) joint_data.v).toVector(), 1e-10);
+  is_matrix_absolutely_closed (expected_c_J.toVector (), ((Motion) joint_data.c).toVector(), 1e-10);
+}
+
+BOOST_AUTO_TEST_CASE ( test_rnea )
+{
+  using namespace se3;
+  typedef Eigen::Matrix <double, 3, 1> Vector3;
+  typedef Eigen::Matrix <double, 3, 3> Matrix3;
+
+  Model model;
+  Inertia inertia (1., Vector3 (0.5, 0., 0.0), Matrix3::Identity ());
+
+  model.addBody (model.getBodyId("universe"), JointModelTranslation (), SE3::Identity (), inertia, "root");
+
+  Data data (model);
+
+  Eigen::VectorXd q (Eigen::VectorXd::Zero (model.nq));
+  Eigen::VectorXd v (Eigen::VectorXd::Zero (model.nv));
+  Eigen::VectorXd a (Eigen::VectorXd::Zero (model.nv));
+
+  rnea (model, data, q, v, a);
+  Vector3 tau_expected (Vector3::Zero ());
+
+  tau_expected  << 0,    0, 9.81;
+
+  is_matrix_absolutely_closed (tau_expected, data.tau, 1e-14);
+
+  q = Eigen::VectorXd::Ones (model.nq);
+  v = Eigen::VectorXd::Ones (model.nv);
+  a = Eigen::VectorXd::Ones (model.nv);
+
+  rnea (model, data, q, v, a);
+  tau_expected << 1,     1, 10.81;
+
+  is_matrix_absolutely_closed (tau_expected, data.tau, 1e-12);
+
+  q << 3, 2, 1;
+  v = Eigen::VectorXd::Ones (model.nv);
+  a = Eigen::VectorXd::Ones (model.nv);
+
+  rnea (model, data, q, v, a);
+  tau_expected << 1,     1, 10.81;
+
+  is_matrix_absolutely_closed (tau_expected, data.tau, 1e-12);
+}
+
+BOOST_AUTO_TEST_CASE ( test_crba )
+{
+  using namespace se3;
+  using namespace std;
+  typedef Eigen::Matrix <double, 3, 1> Vector3;
+  typedef Eigen::Matrix <double, 3, 3> Matrix3;
+
+  Model model;
+  Inertia inertia (1., Vector3 (0.5, 0., 0.0), Matrix3::Identity ());
+
+  model.addBody (model.getBodyId("universe"), JointModelTranslation (), SE3::Identity (), inertia, "root");
+
+  Data data (model);
+
+  Eigen::VectorXd q (Eigen::VectorXd::Zero (model.nq));
+  Eigen::MatrixXd M_expected (model.nv,model.nv);
+
+  crba (model, data, q);
+  M_expected = Matrix3::Identity ();
+
+  is_matrix_absolutely_closed (M_expected, data.M, 1e-14);
+
+  q = Eigen::VectorXd::Ones (model.nq);
+
+  crba (model, data, q);
+
+  is_matrix_absolutely_closed (M_expected, data.M, 1e-12);
+
+  q << 3, 2, 1;
+  
+  crba (model, data, q);
+  
+  is_matrix_absolutely_closed (M_expected, data.M, 1e-10);
+}
+
+BOOST_AUTO_TEST_SUITE_END ()
+
 
 BOOST_AUTO_TEST_SUITE ( JointSpherical )
 
-- 
GitLab