pinocchio  1.2.6-7-g6de3e-dirty
joint-free-flyer.hpp
1 //
2 // Copyright (c) 2015-2017 CNRS
3 // Copyright (c) 2015-2016 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5 // This file is part of Pinocchio
6 // Pinocchio is free software: you can redistribute it
7 // and/or modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation, either version
9 // 3 of the License, or (at your option) any later version.
10 //
11 // Pinocchio is distributed in the hope that it will be
12 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Lesser Public License for more details. You should have
15 // received a copy of the GNU Lesser General Public License along with
16 // Pinocchio If not, see
17 // <http://www.gnu.org/licenses/>.
18 
19 #ifndef __se3_joint_free_flyer_hpp__
20 #define __se3_joint_free_flyer_hpp__
21 
22 #include "pinocchio/macros.hpp"
23 #include "pinocchio/spatial/inertia.hpp"
24 #include "pinocchio/multibody/joint/joint-base.hpp"
25 #include "pinocchio/multibody/constraint.hpp"
26 #include "pinocchio/spatial/explog.hpp"
27 #include "pinocchio/math/fwd.hpp"
28 #include "pinocchio/math/quaternion.hpp"
29 
30 #include <stdexcept>
31 
32 namespace se3
33 {
34 
35  struct ConstraintIdentity;
36 
37  template <>
39  {
40  typedef double Scalar;
41  typedef Eigen::Matrix<double,3,1,0> Vector3;
42  typedef Eigen::Matrix<double,4,1,0> Vector4;
43  typedef Eigen::Matrix<double,6,1,0> Vector6;
44  typedef Eigen::Matrix<double,3,3,0> Matrix3;
45  typedef Eigen::Matrix<double,4,4,0> Matrix4;
46  typedef Eigen::Matrix<double,6,6,0> Matrix6;
47  typedef Matrix3 Angular_t;
48  typedef Vector3 Linear_t;
49  typedef const Matrix3 ConstAngular_t;
50  typedef const Vector3 ConstLinear_t;
51  typedef Matrix6 ActionMatrix_t;
52  typedef Eigen::Quaternion<double,0> Quaternion_t;
53  typedef SE3Tpl<double,0> SE3;
54  typedef ForceTpl<double,0> Force;
57  enum {
58  LINEAR = 0,
59  ANGULAR = 3
60  };
61  typedef Eigen::Matrix<Scalar,6,1,0> JointMotion;
62  typedef Eigen::Matrix<Scalar,6,1,0> JointForce;
63  typedef Eigen::Matrix<Scalar,6,6> DenseBase;
64  }; // traits ConstraintRevolute
65 
66 
67  struct ConstraintIdentity : ConstraintBase < ConstraintIdentity >
68  {
69  SPATIAL_TYPEDEF_NO_TEMPLATE(ConstraintIdentity);
70  enum { NV = 6, Options = 0 };
71  typedef traits<ConstraintIdentity>::JointMotion JointMotion;
72  typedef traits<ConstraintIdentity>::JointForce JointForce;
73  typedef traits<ConstraintIdentity>::DenseBase DenseBase;
74 
75  SE3::Matrix6 se3Action(const SE3 & m) const { return m.toActionMatrix(); }
76 
77  int nv_impl() const { return NV; }
78 
80  {
81  Force::Vector6 operator* (const Force & phi)
82  { return phi.toVector(); }
83  };
84 
85  TransposeConst transpose() const { return TransposeConst(); }
86  operator ConstraintXd () const { return ConstraintXd(SE3::Matrix6::Identity()); }
87 
88  DenseBase variation(const Motion & m) const { return m.toActionMatrix(); }
89  }; // struct ConstraintIdentity
90 
91  template<typename D>
92  Motion operator* (const ConstraintIdentity&, const Eigen::MatrixBase<D>& v)
93  {
94  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(D,6);
95  return Motion(v);
96  }
97 
98 
99  /* [CRBA] ForceSet operator* (Inertia Y,Constraint S) */
100  inline Inertia::Matrix6 operator* (const Inertia & Y, const ConstraintIdentity &)
101  {
102  return Y.matrix();
103  }
104 
105  /* [ABA] Y*S operator*/
106  inline const Inertia::Matrix6 & operator* (const Inertia::Matrix6 & Y, const ConstraintIdentity &)
107  {
108  return Y;
109  }
110 
111  inline Inertia::Matrix6 & operator* (Inertia::Matrix6 & Y, const ConstraintIdentity &)
112  {
113  return Y;
114  }
115 
116  inline Inertia::Matrix6 operator* (const ConstraintIdentity::TransposeConst &, const Inertia & Y)
117  {
118  return Y.matrix();
119  }
120 
121  /* [CRBA] MatrixBase operator* (Constraint::Transpose S, ForceSet::Block) */
122  template<typename D>
123  const Eigen::MatrixBase<D> &
124  operator*( const ConstraintIdentity::TransposeConst &, const Eigen::MatrixBase<D> & F )
125  {
126  return F;
127  }
128 
129  namespace internal
130  {
131  template<>
132  struct ActionReturn<ConstraintIdentity >
133  { typedef SE3::Matrix6 Type; };
134  }
135 
136  struct JointFreeFlyer;
137 
138  template<>
139  struct traits<JointFreeFlyer>
140  {
141  enum {
142  NQ = 7,
143  NV = 6
144  };
145  typedef double Scalar;
149  typedef SE3 Transformation_t;
150  typedef Motion Motion_t;
151  typedef BiasZero Bias_t;
152  typedef Eigen::Matrix<double,6,NV> F_t;
153 
154  // [ABA]
155  typedef Eigen::Matrix<double,6,NV> U_t;
156  typedef Eigen::Matrix<double,NV,NV> D_t;
157  typedef Eigen::Matrix<double,6,NV> UD_t;
158 
159  typedef Eigen::Matrix<double,NQ,1> ConfigVector_t;
160  typedef Eigen::Matrix<double,NV,1> TangentVector_t;
161  };
162  template<> struct traits<JointDataFreeFlyer> { typedef JointFreeFlyer JointDerived; };
163  template<> struct traits<JointModelFreeFlyer> { typedef JointFreeFlyer JointDerived; };
164 
165  struct JointDataFreeFlyer : public JointDataBase<JointDataFreeFlyer>
166  {
167  typedef JointFreeFlyer JointDerived;
168  SE3_JOINT_TYPEDEF;
169 
170  typedef Eigen::Matrix<double,6,6> Matrix6;
171  typedef Eigen::Quaternion<double> Quaternion;
172  typedef Eigen::Matrix<double,3,1> Vector3;
173 
174  Constraint_t S;
175  Transformation_t M;
176  Motion_t v;
177  Bias_t c;
178 
179  F_t F; // TODO if not used anymore, clean F_t
180 
181  // [ABA] specific data
182  U_t U;
183  D_t Dinv;
184  UD_t UDinv;
185 
186  JointDataFreeFlyer() : M(1), U(), Dinv(), UDinv(UD_t::Identity()) {}
187 
188  }; // struct JointDataFreeFlyer
189 
190  struct JointModelFreeFlyer : public JointModelBase<JointModelFreeFlyer>
191  {
192  typedef JointFreeFlyer JointDerived;
193  SE3_JOINT_TYPEDEF;
194 
199  typedef Motion::Vector3 Vector3;
200 
201  JointDataDerived createData() const { return JointDataDerived(); }
202 
203  template<typename V>
204  inline void forwardKinematics(Transformation_t & M, const Eigen::MatrixBase<V> & q_joint) const
205  {
206  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,V);
207  //using std::sqrt;
208  typedef Eigen::Map<const Motion_t::Quaternion_t> ConstQuaternionMap_t;
209 
210  ConstQuaternionMap_t quat(q_joint.template tail<4>().data());
211  //assert(std::fabs(quat.coeffs().squaredNorm()-1.) <= sqrt(Eigen::NumTraits<typename V::Scalar>::epsilon())); TODO: check validity of the rhs precision
212  assert(std::fabs(quat.coeffs().squaredNorm()-1.) <= 1e-4);
213 
214  M.rotation(quat.matrix());
215  M.translation(q_joint.template head<3>());
216  }
217 
218  void calc(JointDataDerived & data,
219  const Eigen::VectorXd & qs) const
220  {
221  typedef Eigen::Map<const Motion_t::Quaternion_t> ConstQuaternionMap_t;
222 
223  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type q = qs.segment<NQ>(idx_q());
224  ConstQuaternionMap_t quat(q.tail<4> ().data());
225 
226  data.M.rotation (quat.matrix());
227  data.M.translation (q.head<3>());
228  }
229 
230  void calc(JointDataDerived & data,
231  const Eigen::VectorXd & qs,
232  const Eigen::VectorXd & vs ) const
233  {
234  typedef Eigen::Map<const Motion_t::Quaternion_t> ConstQuaternionMap_t;
235 
236  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type q = qs.segment<NQ>(idx_q());
237  data.v = vs.segment<NV>(idx_v());
238 
239  ConstQuaternionMap_t quat(q.tail<4> ().data());
240 
241  data.M.rotation (quat.matrix());
242  data.M.translation (q.head<3>());
243  }
244 
245  void calc_aba(JointDataDerived & data, Inertia::Matrix6 & I, const bool update_I) const
246  {
247  data.U = I;
248  data.Dinv = I.inverse();
249 
250  if (update_I)
251  I.setZero();
252  }
253 
254  Scalar finiteDifferenceIncrement() const
255  {
256  using std::sqrt;
257  return 2.*sqrt(sqrt(Eigen::NumTraits<Scalar>::epsilon()));
258  }
259 
260  ConfigVector_t integrate_impl(const Eigen::VectorXd & qs, const Eigen::VectorXd & vs) const
261  {
262  typedef Eigen::Map<Motion_t::Quaternion_t> QuaternionMap_t;
263 
264  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q = qs.segment<NQ> (idx_q ());
265  Eigen::VectorXd::ConstFixedSegmentReturnType<NV>::Type & q_dot = vs.segment<NV> (idx_v ());
266 
267  ConfigVector_t res;
268  Transformation_t M0; forwardKinematics(M0,q);
269  Transformation_t M1(M0*exp6(Motion_t(q_dot)));
270 
271  res.head<3>() = M1.translation();
272  QuaternionMap_t res_quat(res.tail<4>().data());
273  res_quat = M1.rotation();
274  // Norm of qs might be epsilon-different to 1, so M1.rotation might be epsilon-different to a rotation matrix.
275  // It is then safer to re-normalized after converting M1.rotation to quaternion.
276  firstOrderNormalize(res_quat);
277 
278  return res;
279  }
280 
281  ConfigVector_t interpolate_impl(const Eigen::VectorXd & q0, const Eigen::VectorXd & q1, const double u) const
282  {
283  typedef Eigen::Map<Motion_t::Quaternion_t> QuaternionMap_t;
284 
285  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_0 = q0.segment<NQ> (idx_q ());
286  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_1 = q1.segment<NQ> (idx_q ());
287 
288  if (u == 0.) return q_0;
289  else if( u == 1.) return q_1;
290  else
291  {
292  // TODO: If integrate takes an arguments (ConfigVector_t, TangentVector_t), then we can merely do:
293  // TangentVector_t nu(u*difference(q0, q1));
294  // return integrate(q0, nu);
295 
296  TangentVector_t nu(u*difference(q0, q1));
297  Transformation_t M0; forwardKinematics(M0,q_0);
298  Transformation_t M1(M0*exp6(Motion_t(nu)));
299 
300  ConfigVector_t res;
301  res.head<3>() = M1.translation();
302  QuaternionMap_t res_quat(res.tail<4>().data());
303  res_quat = M1.rotation();
304  firstOrderNormalize(res_quat);
305 
306  return res;
307  }
308  }
309 
310  ConfigVector_t random_impl() const
311  {
312  ConfigVector_t q(ConfigVector_t::Random());
313 
314  typedef Eigen::Map<Motion_t::Quaternion_t> QuaternionMap_t;
315  uniformRandom(QuaternionMap_t(q.segment<4>(3).data()));
316 
317  return q;
318  }
319 
320  ConfigVector_t randomConfiguration_impl(const ConfigVector_t & lower_pos_limit, const ConfigVector_t & upper_pos_limit ) const throw (std::runtime_error)
321  {
322  ConfigVector_t result;
323  // Translational part
324  for (Index i = 0; i < 3; ++i)
325  {
326  if(lower_pos_limit[i] == -std::numeric_limits<double>::infinity() ||
327  upper_pos_limit[i] == std::numeric_limits<double>::infinity() )
328  {
329  std::ostringstream error;
330  error << "non bounded limit. Cannot uniformly sample joint nb " << id();
331  throw std::runtime_error(error.str());
332  }
333 
334  result[i] = lower_pos_limit[i] + (upper_pos_limit[i] - lower_pos_limit[i]) * (Scalar)(rand())/RAND_MAX;
335  }
336 
337  typedef Eigen::Map<Motion_t::Quaternion_t> QuaternionMap_t;
338  uniformRandom(QuaternionMap_t(result.segment<4>(3).data()));
339 
340  return result;
341  }
342 
343  TangentVector_t difference_impl(const Eigen::VectorXd & q0, const Eigen::VectorXd & q1) const
344  {
345  Transformation_t M0(Transformation_t::Identity()); forwardKinematics(M0, q0.segment<NQ> (idx_q ()));
346  Transformation_t M1(Transformation_t::Identity()); forwardKinematics(M1, q1.segment<NQ> (idx_q ()));
347 
348  return se3::log6(M0.inverse()*M1);
349  }
350 
351  double distance_impl(const Eigen::VectorXd & q0,const Eigen::VectorXd & q1) const
352  {
353  return difference_impl(q0,q1).norm();
354  }
355 
356  ConfigVector_t neutralConfiguration_impl() const
357  {
358  ConfigVector_t q;
359  q << 0, 0, 0, // translation part
360  0, 0, 0, 1; // quaternion part
361  return q;
362  }
363 
364  void normalize_impl(Eigen::VectorXd& q) const
365  {
366  q.segment<4>(idx_q()+3).normalize();
367  }
368 
369  bool isSameConfiguration_impl(const Eigen::VectorXd& q1, const Eigen::VectorXd& q2, const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const
370  {
371  typedef Eigen::Map<const Motion_t::Quaternion_t> ConstQuaternionMap_t;
372 
373  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_1 = q1.segment<NQ> (idx_q ());
374  Eigen::VectorXd::ConstFixedSegmentReturnType<NQ>::Type & q_2 = q2.segment<NQ> (idx_q ());
375 
376  ConstQuaternionMap_t quat1(q_1.tail<4> ().data());
377  ConstQuaternionMap_t quat2(q_2.tail<4> ().data());
378 
379  return ( q_1.head<3>().isApprox(q_2.head<3>(), prec) && defineSameRotation(quat1,quat2) );
380  }
381 
382  static std::string classname() { return std::string("JointModelFreeFlyer"); }
383  std::string shortname() const { return classname(); }
384 
385  }; // struct JointModelFreeFlyer
386 
387 } // namespace se3
388 
389 #endif // ifndef __se3_joint_free_flyer_hpp__
Concreate Class representing a force.
Definition: force.hpp:243
const Vector6 & toVector() const
Return the force.
Definition: force.hpp:102