From 51bc53decc0201d7020e3bdc0fdb9e475180c424 Mon Sep 17 00:00:00 2001
From: Valenza Florian <fvalenza@laas.fr>
Date: Mon, 1 Feb 2016 17:21:52 +0100
Subject: [PATCH] [C++] Added algorithms to compute position and jacobian of
 extra_frames, and binded it in python

Conflicts:

	CMakeLists.txt
	src/python/algorithms.hpp
---
 CMakeLists.txt                 |   1 +
 src/algorithm/extra-frames.hpp | 130 +++++++++++++++++++++++++++++++++
 src/python/algorithms.hpp      |  49 +++++++++++++
 src/python/data.hpp            |   2 +
 4 files changed, 182 insertions(+)
 create mode 100644 src/algorithm/extra-frames.hpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 00917e200..4d1337eb5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -140,6 +140,7 @@ SET(${PROJECT_NAME}_ALGORITHM_HEADERS
   algorithm/non-linear-effects.hpp
   algorithm/joint-limits.hpp
   algorithm/energy.hpp
+  algorithm/extra-frames.hpp
   )
 
 SET(${PROJECT_NAME}_SIMULATION_HEADERS
diff --git a/src/algorithm/extra-frames.hpp b/src/algorithm/extra-frames.hpp
new file mode 100644
index 000000000..3b810f83b
--- /dev/null
+++ b/src/algorithm/extra-frames.hpp
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// 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_extra_frames_hpp__
+#define __se3_extra_frames_hpp__
+
+#include "pinocchio/multibody/visitor.hpp"
+#include "pinocchio/multibody/model.hpp"
+
+#include "pinocchio/algorithm/kinematics.hpp"
+
+namespace se3
+{
+
+
+
+  /**
+   * @brief      Update the position of each extra frame
+   *
+   * @param[in]  model  The kinematic model
+   * @param      data   Data associated to model
+   * @warning    One of the algorithms forwardKinematics should have been called first
+   */
+  inline void extraFramesForwardKinematic(const Model & model,
+                                          Data & data
+                                          );
+
+  /**
+   * @brief      Compute Kinematics of full model, then the position of each extra frame
+   *
+   * @param[in]  model                    The kinematic model
+   * @param      data                     Data associated to model
+   * @param[in]  q                        Configuration vector
+   */
+  inline void extraFramesForwardKinematic(const Model & model,
+                                          Data & data,
+                                          const Eigen::VectorXd & q
+                                          );
+
+  /**
+   * @brief      Return the jacobian of the extra frame in the world frame or
+     in the local frame depending on the template argument.
+   *
+   * @param[in]  model       The kinematic model
+   * @param[in]  data        Data associated to model
+   * @param[in]  frame_id    Id of the extra frame we want to compute the jacobian
+   * @param      J           The filled Jacobian Matrix
+   *
+   * @tparam     localFrame  Express the jacobian in the local or global frame
+   * 
+   * @warning    The function computeJacobians should have been called first
+   */
+  template<bool localFrame>
+  inline void getExtraFrameJacobian(const Model & model,
+                                    const Data& data,
+                                    Model::Index frame_id,
+                                    Eigen::MatrixXd & J
+                                    );
+ 
+} // namespace se3 
+
+/* --- Details -------------------------------------------------------------------- */
+namespace se3 
+{
+  
+  
+inline void  extraFramesForwardKinematic(const Model & model,
+                                         Data & data
+                                         )
+{
+  using namespace se3;
+
+  for (Model::Index i=0; i < (Model::Index) model.nExtraFrames; ++i)
+  {
+    const Model::Index & parent = model.extra_frames[i].parent_id;
+    data.oMef[i] = (data.oMi[parent] * model.extra_frames[i].frame_placement);
+  }
+}
+
+inline void  extraFramesForwardKinematic(const Model & model,
+                                         Data & data,
+                                         const Eigen::VectorXd & q
+                                         )
+{
+  using namespace se3;
+
+  forwardKinematics(model, data, q);
+
+  extraFramesForwardKinematic(model, data);
+}
+
+
+
+template<bool localFrame>
+inline void getExtraFrameJacobian(const Model & model, const Data& data,
+     Model::Index frame_id, Eigen::MatrixXd & J)
+{
+  assert( J.rows() == data.J.rows() );
+  assert( J.cols() == data.J.cols() );
+
+  const Model::Index & parent = model.extra_frames[frame_id].parent_id;
+  const SE3 & oMframe = data.oMef[frame_id];
+
+  int colRef = nv(model.joints[parent])+idx_v(model.joints[parent])-1;
+
+  for(int j=colRef;j>=0;j=data.parents_fromRow[(Model::Index)j])
+    {
+      if(! localFrame )   J.col(j) = data.J.col(j);
+      else                J.col(j) = oMframe.actInv(Motion(data.J.col(j))).toVector();
+    }
+}
+
+} // namespace se3
+
+#endif // ifndef __se3_extra_frames_hpp__
+
diff --git a/src/python/algorithms.hpp b/src/python/algorithms.hpp
index fdfb0fd9f..82bfd8566 100644
--- a/src/python/algorithms.hpp
+++ b/src/python/algorithms.hpp
@@ -29,6 +29,7 @@
 #include "pinocchio/algorithm/crba.hpp"
 #include "pinocchio/algorithm/kinematics.hpp"
 #include "pinocchio/algorithm/jacobian.hpp"
+#include "pinocchio/algorithm/extra-frames.hpp"
 #include "pinocchio/algorithm/center-of-mass.hpp"
 #include "pinocchio/algorithm/joint-limits.hpp"
 #include "pinocchio/algorithm/energy.hpp"
@@ -106,6 +107,25 @@ namespace se3
   return J;
       }
       
+      static Eigen::MatrixXd extra_frame_jacobian_proxy(const ModelHandler& model, 
+                                                        DataHandler & data,
+                                                        const VectorXd_fx & q,
+                                                        Model::Index frame_id,
+                                                        bool local,
+                                                        bool update_geometry
+                                                        )
+      {
+        Eigen::MatrixXd J( 6,model->nv ); J.setZero();
+
+        if (update_geometry)
+          computeJacobians( *model,*data,q );
+
+        if(local) getExtraFrameJacobian<true> (*model, *data, frame_id, J);
+        else getExtraFrameJacobian<false> (*model, *data, frame_id, J);
+        
+        return J;
+      }
+
       static void compute_jacobians_proxy(const ModelHandler& model, 
                DataHandler & data,
                const VectorXd_fx & q)
@@ -128,6 +148,15 @@ namespace se3
         forwardKinematics(*model,*data,q,qdot);
       }
 
+
+      static void kinematics_proxy(const ModelHandler& model, 
+                                   DataHandler & data,
+                                   const VectorXd_fx & q
+                                   )
+      {
+        extraFramesForwardKinematic( *model,*data,q );
+      }
+
       static void fk_2_proxy(const ModelHandler& model,
                            DataHandler & data,
                            const VectorXd_fx & q,
@@ -252,6 +281,14 @@ namespace se3
     "Compute the placements and spatial velocities of all the frames of the kinematic "
     "tree and put the results in data.");
 
+
+  bp::def("extraFramesKinematics",extra_frames_kinematics_proxy,
+    bp::args("Model","Data",
+       "Configuration q (size Model::nq)",
+       "Velocity v (size Model::nv)"),
+    "Compute the placements and spatial velocities of all the extra frames "
+    "and put the results in data.");
+
   bp::def("geometry",fk_0_proxy,
     bp::args("Model","Data",
         "Configuration q (size Model::nq)"),
@@ -284,6 +321,18 @@ namespace se3
     "the demanded one if update_geometry is set to false. It is therefore outrageously costly wrt a dedicated "
     "call. Function to be used only for prototyping.");
 
+  bp::def("extraFramejacobian",extra_frame_jacobian_proxy,
+    bp::args("Model","Data",
+       "Configuration q (size Model::nq)",
+       "Extra frame ID (int)",
+       "frame (true = local, false = world)",
+       "update_geometry (true = recompute the kinematics)"),
+    "Call computeJacobians if update_geometry is true. If not, user should call computeJacobians first."
+    "Then call getJacobian and return the resulted jacobian matrix. Attention: if update_geometry is true, the "
+    "function computes all the jacobians of the model, even if just outputing "
+    "the demanded one. It is therefore outrageously costly wrt a dedicated "
+    "call. Use only with update_geometry for prototyping.");
+
   bp::def("computeJacobians",compute_jacobians_proxy,
     bp::args("Model","Data",
        "Configuration q (size Model::nq)"),
diff --git a/src/python/data.hpp b/src/python/data.hpp
index 189579df4..239125520 100644
--- a/src/python/data.hpp
+++ b/src/python/data.hpp
@@ -74,6 +74,7 @@ namespace se3
 	  .ADD_DATA_PROPERTY(std::vector<Motion>,v,"Body velocity")
 	  .ADD_DATA_PROPERTY(std::vector<Force>,f,"Body force")
 	  .ADD_DATA_PROPERTY(std::vector<SE3>,oMi,"Body absolute placement (wrt world)")
+    .ADD_DATA_PROPERTY(std::vector<SE3>,oMef,"extra_frames absolute placement (wrt world)")
 	  .ADD_DATA_PROPERTY(std::vector<SE3>,liMi,"Body relative placement (wrt parent)")
 	  .ADD_DATA_PROPERTY_CONST(Eigen::VectorXd,tau,"Joint forces")
     .ADD_DATA_PROPERTY_CONST(Eigen::VectorXd,nle,"Non Linear Effects")
@@ -111,6 +112,7 @@ namespace se3
       IMPL_DATA_PROPERTY(std::vector<Motion>,v,"Body velocity")
       IMPL_DATA_PROPERTY(std::vector<Force>,f,"Body force")
       IMPL_DATA_PROPERTY(std::vector<SE3>,oMi,"Body absolute placement (wrt world)")
+      IMPL_DATA_PROPERTY(std::vector<SE3>,oMef,"extra_frames absolute placement (wrt world)")
       IMPL_DATA_PROPERTY(std::vector<SE3>,liMi,"Body relative placement (wrt parent)")
       IMPL_DATA_PROPERTY_CONST(Eigen::VectorXd,tau,"Joint forces")
       IMPL_DATA_PROPERTY_CONST(Eigen::VectorXd,nle,"Non Linear Effects")
-- 
GitLab