pinocchio  2.1.3
cartesian-product.hpp
1 //
2 // Copyright (c) 2016-2018 CNRS
3 //
4 
5 #ifndef __pinocchio_cartesian_product_operation_hpp__
6 #define __pinocchio_cartesian_product_operation_hpp__
7 
8 #include <pinocchio/multibody/liegroup/liegroup-base.hpp>
9 
10 namespace pinocchio
11 {
12  template<int dim1, int dim2>
13  struct eval_set_dim
14  {
15  enum { value = dim1 + dim2 };
16  };
17 
18  template<int dim>
19  struct eval_set_dim<dim,Eigen::Dynamic>
20  {
21  enum { value = Eigen::Dynamic };
22  };
23 
24  template<int dim>
25  struct eval_set_dim<Eigen::Dynamic,dim>
26  {
27  enum { value = Eigen::Dynamic };
28  };
29 
30  template<typename LieGroup1, typename LieGroup2>
32 
33  template<typename LieGroup1, typename LieGroup2>
34  struct traits<CartesianProductOperation<LieGroup1, LieGroup2> > {
35  typedef typename traits<LieGroup1>::Scalar Scalar;
36  enum {
40  };
41  };
42 
43  template<typename LieGroup1, typename LieGroup2>
44  struct CartesianProductOperation : public LieGroupBase <CartesianProductOperation<LieGroup1, LieGroup2> >
45  {
46  PINOCCHIO_LIE_GROUP_TPL_PUBLIC_INTERFACE(CartesianProductOperation);
47 
48  CartesianProductOperation () : lg1_ (), lg2_ ()
49  {
50  }
55  Index nq () const
56  {
57  return lg1_.nq () + lg2_.nq ();
58  }
60  Index nv () const
61  {
62  return lg1_.nv () + lg2_.nv ();
63  }
64 
65  ConfigVector_t neutral () const
66  {
67  ConfigVector_t n;
68  n.resize (nq ());
69  Qo1(n) = lg1_.neutral ();
70  Qo2(n) = lg2_.neutral ();
71  return n;
72  }
73 
74  std::string name () const
75  {
76  std::ostringstream oss; oss << lg1_.name () << "*" << lg2_.name ();
77  return oss.str ();
78  }
79 
80  template <class ConfigL_t, class ConfigR_t, class Tangent_t>
81  void difference_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
82  const Eigen::MatrixBase<ConfigR_t> & q1,
83  const Eigen::MatrixBase<Tangent_t> & d) const
84  {
85  lg1_.difference(Q1(q0), Q1(q1), Vo1(d));
86  lg2_.difference(Q2(q0), Q2(q1), Vo2(d));
87  }
88 
89  template <ArgumentPosition arg, class ConfigL_t, class ConfigR_t, class JacobianOut_t>
90  void dDifference (const Eigen::MatrixBase<ConfigL_t> & q0,
91  const Eigen::MatrixBase<ConfigR_t> & q1,
92  const Eigen::MatrixBase<JacobianOut_t>& J) const
93  {
94  J12(J).setZero();
95  J21(J).setZero();
96 
97  lg1_.template dDifference<arg> (Q1(q0), Q1(q1), J11(J));
98  lg2_.template dDifference<arg> (Q2(q0), Q2(q1), J22(J));
99  }
100 
101  template <class ConfigIn_t, class Velocity_t, class ConfigOut_t>
102  void integrate_impl(const Eigen::MatrixBase<ConfigIn_t> & q,
103  const Eigen::MatrixBase<Velocity_t> & v,
104  const Eigen::MatrixBase<ConfigOut_t> & qout) const
105  {
106  lg1_.integrate(Q1(q), V1(v), Qo1(qout));
107  lg2_.integrate(Q2(q), V2(v), Qo2(qout));
108  }
109 
110  template <class Config_t, class Jacobian_t>
111  void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase<Config_t> & q,
112  const Eigen::MatrixBase<Jacobian_t> & J) const
113  {
114  assert(J.rows() == nq() && J.cols() == nv() && "J is not of the right dimension");
115  Jacobian_t & J_ = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
116  J_.topRightCorner(lg1_.nq(),lg2_.nv()).setZero();
117  J_.bottomLeftCorner(lg2_.nq(),lg1_.nv()).setZero();
118 
119  lg1_.integrateCoeffWiseJacobian(Q1(q),
120  J_.topLeftCorner(lg1_.nq(),lg1_.nv()));
121  lg2_.integrateCoeffWiseJacobian(Q2(q), J_.bottomRightCorner(lg2_.nq(),lg2_.nv()));
122  }
123 
124  template <class Config_t, class Tangent_t, class JacobianOut_t>
125  void dIntegrate_dq_impl(const Eigen::MatrixBase<Config_t > & q,
126  const Eigen::MatrixBase<Tangent_t> & v,
127  const Eigen::MatrixBase<JacobianOut_t> & J) const
128  {
129  J12(J).setZero();
130  J21(J).setZero();
131  lg1_.dIntegrate_dq(Q1(q), V1(v), J11(J));
132  lg2_.dIntegrate_dq(Q2(q), V2(v), J22(J));
133  }
134 
135  template <class Config_t, class Tangent_t, class JacobianOut_t>
136  void dIntegrate_dv_impl(const Eigen::MatrixBase<Config_t > & q,
137  const Eigen::MatrixBase<Tangent_t> & v,
138  const Eigen::MatrixBase<JacobianOut_t> & J) const
139  {
140  J12(J).setZero();
141  J21(J).setZero();
142  lg1_.dIntegrate_dv(Q1(q), V1(v), J11(J));
143  lg2_.dIntegrate_dv(Q2(q), V2(v), J22(J));
144  }
145 
146  template <class ConfigL_t, class ConfigR_t>
147  Scalar squaredDistance_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
148  const Eigen::MatrixBase<ConfigR_t> & q1) const
149  {
150  return lg1_.squaredDistance(Q1(q0), Q1(q1))
151  + lg2_.squaredDistance(Q2(q0), Q2(q1));
152  }
153 
154  template <class Config_t>
155  void normalize_impl (const Eigen::MatrixBase<Config_t>& qout) const
156  {
157  lg1_.normalize(Qo1(qout));
158  lg2_.normalize(Qo2(qout));
159  }
160 
161  template <class Config_t>
162  void random_impl (const Eigen::MatrixBase<Config_t>& qout) const
163  {
164  lg1_.random(Qo1(qout));
165  lg2_.random(Qo2(qout));
166  }
167 
168  template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
169  void randomConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & lower,
170  const Eigen::MatrixBase<ConfigR_t> & upper,
171  const Eigen::MatrixBase<ConfigOut_t> & qout)
172  const
173  {
174  lg1_.randomConfiguration(Q1(lower), Q1(upper), Qo1(qout));
175  lg2_.randomConfiguration(Q2(lower), Q2(upper), Qo2(qout));
176  }
177 
178  template <class ConfigL_t, class ConfigR_t>
179  bool isSameConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
180  const Eigen::MatrixBase<ConfigR_t> & q1,
181  const Scalar & prec) const
182  {
183  return lg1_.isSameConfiguration(Q1(q0), Q1(q1), prec)
184  && lg2_.isSameConfiguration(Q2(q0), Q2(q1), prec);
185  }
186  private:
187  LieGroup1 lg1_;
188  LieGroup2 lg2_;
189 
190  // VectorSpaceOperationTpl<-1> within CartesianProductOperation will not work
191  // if Eigen version is lower than 3.2.1
192 #if EIGEN_VERSION_AT_LEAST(3,2,1)
193 # define REMOVE_IF_EIGEN_TOO_LOW(x) x
194 #else
195 # define REMOVE_IF_EIGEN_TOO_LOW(x)
196 #endif
197 
198  template <typename Config > typename Config ::template ConstFixedSegmentReturnType<LieGroup1::NQ>::Type Q1 (const Eigen::MatrixBase<Config >& q) const { return q.derived().template head<LieGroup1::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg1_.nq())); }
199  template <typename Config > typename Config ::template ConstFixedSegmentReturnType<LieGroup2::NQ>::Type Q2 (const Eigen::MatrixBase<Config >& q) const { return q.derived().template tail<LieGroup2::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg2_.nq())); }
200  template <typename Tangent> typename Tangent::template ConstFixedSegmentReturnType<LieGroup1::NV>::Type V1 (const Eigen::MatrixBase<Tangent>& v) const { return v.derived().template head<LieGroup1::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg1_.nv())); }
201  template <typename Tangent> typename Tangent::template ConstFixedSegmentReturnType<LieGroup2::NV>::Type V2 (const Eigen::MatrixBase<Tangent>& v) const { return v.derived().template tail<LieGroup2::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg2_.nv())); }
202 
203  template <typename Config > typename Config ::template FixedSegmentReturnType<LieGroup1::NQ>::Type Qo1 (const Eigen::MatrixBase<Config >& q) const { return const_cast<Config &>(q.derived()).template head<LieGroup1::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg1_.nq())); }
204  template <typename Config > typename Config ::template FixedSegmentReturnType<LieGroup2::NQ>::Type Qo2 (const Eigen::MatrixBase<Config >& q) const { return const_cast<Config &>(q.derived()).template tail<LieGroup2::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg2_.nq())); }
205  template <typename Tangent> typename Tangent::template FixedSegmentReturnType<LieGroup1::NV>::Type Vo1 (const Eigen::MatrixBase<Tangent>& v) const { return const_cast<Tangent&>(v.derived()).template head<LieGroup1::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg1_.nv())); }
206  template <typename Tangent> typename Tangent::template FixedSegmentReturnType<LieGroup2::NV>::Type Vo2 (const Eigen::MatrixBase<Tangent>& v) const { return const_cast<Tangent&>(v.derived()).template tail<LieGroup2::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg2_.nv())); }
207 
208  template <typename Jac> Eigen::Block<Jac, LieGroup1::NV, LieGroup1::NV> J11 (const Eigen::MatrixBase<Jac>& J) const { return const_cast<Jac&>(J.derived()).template topLeftCorner<LieGroup1::NV, LieGroup1::NV>(lg1_.nv(),lg1_.nv()); }
209  template <typename Jac> Eigen::Block<Jac, LieGroup1::NV, LieGroup2::NV> J12 (const Eigen::MatrixBase<Jac>& J) const { return const_cast<Jac&>(J.derived()).template topRightCorner<LieGroup1::NV, LieGroup2::NV>(lg1_.nv(),lg2_.nv()); }
210  template <typename Jac> Eigen::Block<Jac, LieGroup2::NV, LieGroup1::NV> J21 (const Eigen::MatrixBase<Jac>& J) const { return const_cast<Jac&>(J.derived()).template bottomLeftCorner<LieGroup2::NV, LieGroup1::NV>(lg2_.nv(),lg1_.nv()); }
211  template <typename Jac> Eigen::Block<Jac, LieGroup2::NV, LieGroup2::NV> J22 (const Eigen::MatrixBase<Jac>& J) const { return const_cast<Jac&>(J.derived()).template bottomRightCorner<LieGroup2::NV, LieGroup2::NV>(lg2_.nv(),lg2_.nv()); }
212 #undef REMOVE_IF_EIGEN_TOO_LOW
213 
214  }; // struct CartesianProductOperation
215 
216 } // namespace pinocchio
217 
218 #endif // ifndef __pinocchio_cartesian_product_operation_hpp__
int nv(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNvVisitor to get the dimension of the joint tangent space...
int nq(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNqVisitor to get the dimension of the joint configuration space...
Source from #include <cppad/example/cppad_eigen.hpp>
Definition: cppad.hpp:24
std::string name(const LieGroupGenericTpl< LieGroupCollection > &lg)
Visit a LieGroupVariant to get the name of it.
Index nv() const
Get dimension of Lie Group tangent space.
Main pinocchio namespace.
Definition: treeview.dox:24
void neutral(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ReturnType > &qout)
Return the neutral configuration element related to the model configuration space.
Common traits structure to fully define base classes for CRTP.
Definition: spatial/fwd.hpp:29