GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/multibody/liegroup/cartesian-product.hpp Lines: 87 91 95.6 %
Date: 2024-01-23 21:41:47 Branches: 80 162 49.4 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2016-2020 CNRS CNRS
3
//
4
5
#ifndef __pinocchio_multibody_liegroup_cartesian_product_operation_hpp__
6
#define __pinocchio_multibody_liegroup_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>
31
  struct CartesianProductOperation;
32
33
  template<typename LieGroup1, typename LieGroup2>
34
  struct traits<CartesianProductOperation<LieGroup1, LieGroup2> > {
35
    typedef typename traits<LieGroup1>::Scalar Scalar;
36
    enum {
37
      Options = traits<LieGroup1>::Options,
38
      NQ = eval_set_dim<LieGroup1::NQ,LieGroup2::NQ>::value,
39
      NV = eval_set_dim<LieGroup1::NV,LieGroup2::NV>::value
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
13690
    CartesianProductOperation () : lg1 (), lg2 ()
49
    {
50
13690
    }
51
    // Get dimension of Lie Group vector representation
52
    //
53
    // For instance, for SO(3), the dimension of the vector representation is
54
    // 4 (quaternion) while the dimension of the tangent space is 3.
55
2398
    Index nq () const
56
    {
57
2398
      return lg1.nq () + lg2.nq ();
58
    }
59
60
    // Get dimension of Lie Group tangent space
61
1608
    Index nv () const
62
    {
63
1608
      return lg1.nv () + lg2.nv ();
64
    }
65
66
5
    ConfigVector_t neutral () const
67
    {
68
5
      ConfigVector_t n;
69
5
      n.resize (nq ());
70

5
      Qo1(n) = lg1.neutral ();
71

5
      Qo2(n) = lg2.neutral ();
72
5
      return n;
73
    }
74
75
244
    std::string name () const
76
    {
77



488
      std::ostringstream oss; oss << lg1.name () << "*" << lg2.name ();
78
488
      return oss.str ();
79
    }
80
81
    template <class ConfigL_t, class ConfigR_t, class Tangent_t>
82
1557
    void difference_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
83
                         const Eigen::MatrixBase<ConfigR_t> & q1,
84
                         const Eigen::MatrixBase<Tangent_t> & d) const
85
    {
86

1557
      lg1.difference(Q1(q0), Q1(q1), Vo1(d));
87

1557
      lg2.difference(Q2(q0), Q2(q1), Vo2(d));
88
1557
    }
89
90
    template <ArgumentPosition arg, class ConfigL_t, class ConfigR_t, class JacobianOut_t>
91
324
    void dDifference_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
92
                          const Eigen::MatrixBase<ConfigR_t> & q1,
93
                          const Eigen::MatrixBase<JacobianOut_t> & J) const
94
    {
95
324
      J12(J).setZero();
96
324
      J21(J).setZero();
97
98

324
      lg1.template dDifference<arg> (Q1(q0), Q1(q1), J11(J));
99

324
      lg2.template dDifference<arg> (Q2(q0), Q2(q1), J22(J));
100
324
    }
101
102
    template <class ConfigIn_t, class Velocity_t, class ConfigOut_t>
103
2379
    void integrate_impl(const Eigen::MatrixBase<ConfigIn_t> & q,
104
                        const Eigen::MatrixBase<Velocity_t> & v,
105
                        const Eigen::MatrixBase<ConfigOut_t> & qout) const
106
    {
107

2379
      lg1.integrate(Q1(q), V1(v), Qo1(qout));
108

2379
      lg2.integrate(Q2(q), V2(v), Qo2(qout));
109
2379
    }
110
111
    template <class Config_t, class Jacobian_t>
112
80
    void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase<Config_t> & q,
113
                                         const Eigen::MatrixBase<Jacobian_t> & J) const
114
    {
115

80
      assert(J.rows() == nq() && J.cols() == nv() && "J is not of the right dimension");
116
80
      Jacobian_t & J_ = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
117
80
      J_.topRightCorner(lg1.nq(),lg2.nv()).setZero();
118
80
      J_.bottomLeftCorner(lg2.nq(),lg1.nv()).setZero();
119
120

80
      lg1.integrateCoeffWiseJacobian(Q1(q),
121
                                      J_.topLeftCorner(lg1.nq(),lg1.nv()));
122

80
      lg2.integrateCoeffWiseJacobian(Q2(q), J_.bottomRightCorner(lg2.nq(),lg2.nv()));
123
80
    }
124
125
    template <class Config_t, class Tangent_t, class JacobianOut_t>
126
85
    void dIntegrate_dq_impl(const Eigen::MatrixBase<Config_t > & q,
127
                            const Eigen::MatrixBase<Tangent_t> & v,
128
                            const Eigen::MatrixBase<JacobianOut_t> & J,
129
                            const AssignmentOperatorType op=SETTO) const
130
    {
131
85
      switch(op)
132
        {
133
85
        case SETTO:
134
85
          J12(J).setZero();
135
85
          J21(J).setZero();
136
          // fallthrough
137
85
        case ADDTO:
138
        case RMTO:
139

85
          lg1.dIntegrate_dq(Q1(q), V1(v), J11(J),op);
140

85
          lg2.dIntegrate_dq(Q2(q), V2(v), J22(J),op);
141
85
          break;
142
        default:
143
          assert(false && "Wrong Op requesed value");
144
          break;
145
        }
146
85
    }
147
148
    template <class Config_t, class Tangent_t, class JacobianOut_t>
149
165
    void dIntegrate_dv_impl(const Eigen::MatrixBase<Config_t > & q,
150
                            const Eigen::MatrixBase<Tangent_t> & v,
151
                            const Eigen::MatrixBase<JacobianOut_t> & J,
152
                            const AssignmentOperatorType op=SETTO) const
153
    {
154
165
      switch(op)
155
        {
156
165
        case SETTO:
157
165
          J12(J).setZero();
158
165
          J21(J).setZero();
159
          // fallthrough
160
165
        case ADDTO:
161
        case RMTO:
162

165
          lg1.dIntegrate_dv(Q1(q), V1(v), J11(J),op);
163

165
          lg2.dIntegrate_dv(Q2(q), V2(v), J22(J),op);
164
165
          break;
165
        default:
166
          assert(false && "Wrong Op requesed value");
167
          break;
168
        }
169
165
    }
170
171
    template <class Config_t, class Tangent_t, class JacobianIn_t, class JacobianOut_t>
172
    void dIntegrateTransport_dq_impl(const Eigen::MatrixBase<Config_t > & q,
173
                                     const Eigen::MatrixBase<Tangent_t> & v,
174
                                     const Eigen::MatrixBase<JacobianIn_t> & J_in,
175
                                     const Eigen::MatrixBase<JacobianOut_t> & J_out) const
176
    {
177
      JacobianOut_t& Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
178
      JacobianOut_t& Jin = PINOCCHIO_EIGEN_CONST_CAST(JacobianIn_t,J_in);
179
      lg1.dIntegrateTransport_dq(Q1(q), V1(v), Jin.template topRows<LieGroup1::NV>(),Jout.template topRows<LieGroup1::NV>());
180
      lg2.dIntegrateTransport_dq(Q2(q), V2(v), Jin.template bottomRows<LieGroup2::NV>(),Jout.template bottomRows<LieGroup2::NV>());
181
    }
182
183
    template <class Config_t, class Tangent_t, class JacobianIn_t, class JacobianOut_t>
184
    void dIntegrateTransport_dv_impl(const Eigen::MatrixBase<Config_t > & q,
185
                                     const Eigen::MatrixBase<Tangent_t> & v,
186
                                     const Eigen::MatrixBase<JacobianIn_t> & J_in,
187
                                     const Eigen::MatrixBase<JacobianOut_t> & J_out) const
188
    {
189
      JacobianOut_t& Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
190
      JacobianOut_t& Jin = PINOCCHIO_EIGEN_CONST_CAST(JacobianIn_t,J_in);
191
      lg1.dIntegrateTransport_dv(Q1(q), V1(v), Jin.template topRows<LieGroup1::NV>(),Jout.template topRows<LieGroup1::NV>());
192
      lg2.dIntegrateTransport_dv(Q2(q), V2(v), Jin.template bottomRows<LieGroup2::NV>(),Jout.template bottomRows<LieGroup2::NV>());
193
    }
194
195
196
    template <class Config_t, class Tangent_t, class Jacobian_t>
197
    void dIntegrateTransport_dq_impl(const Eigen::MatrixBase<Config_t > & q,
198
                                     const Eigen::MatrixBase<Tangent_t> & v,
199
                                     const Eigen::MatrixBase<Jacobian_t> & Jin) const
200
    {
201
      Jacobian_t& J = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,Jin);
202
      lg1.dIntegrateTransport_dq(Q1(q), V1(v), J.template topRows<LieGroup1::NV>());
203
      lg2.dIntegrateTransport_dq(Q2(q), V2(v), J.template bottomRows<LieGroup2::NV>());
204
    }
205
206
    template <class Config_t, class Tangent_t, class Jacobian_t>
207
    void dIntegrateTransport_dv_impl(const Eigen::MatrixBase<Config_t > & q,
208
                                     const Eigen::MatrixBase<Tangent_t> & v,
209
                                     const Eigen::MatrixBase<Jacobian_t> & Jin) const
210
    {
211
      Jacobian_t& J = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,Jin);
212
      lg1.dIntegrateTransport_dv(Q1(q), V1(v), J.template topRows<LieGroup1::NV>());
213
      lg2.dIntegrateTransport_dv(Q2(q), V2(v), J.template bottomRows<LieGroup2::NV>());
214
    }
215
216
    template <class ConfigL_t, class ConfigR_t>
217
2
    Scalar squaredDistance_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
218
                                const Eigen::MatrixBase<ConfigR_t> & q1) const
219
    {
220
2
      return lg1.squaredDistance(Q1(q0), Q1(q1))
221


2
        +    lg2.squaredDistance(Q2(q0), Q2(q1));
222
    }
223
224
    template <class Config_t>
225
1
    void normalize_impl (const Eigen::MatrixBase<Config_t>& qout) const
226
    {
227
1
      lg1.normalize(Qo1(qout));
228
1
      lg2.normalize(Qo2(qout));
229
1
    }
230
231
    template <class Config_t>
232
    bool isNormalized_impl (const Eigen::MatrixBase<Config_t>& qin, const Scalar& prec) const
233
    {
234
      return lg1.isNormalized(Qo1(qin), prec) && lg2.isNormalized(Qo2(qin), prec);
235
    }
236
237
    template <class Config_t>
238
1016
    void random_impl (const Eigen::MatrixBase<Config_t>& qout) const
239
    {
240
1016
      lg1.random(Qo1(qout));
241
1016
      lg2.random(Qo2(qout));
242
1016
    }
243
244
    template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
245
12450
    void randomConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & lower,
246
                                  const Eigen::MatrixBase<ConfigR_t> & upper,
247
                                  const Eigen::MatrixBase<ConfigOut_t> & qout)
248
      const
249
    {
250

12450
      lg1.randomConfiguration(Q1(lower), Q1(upper), Qo1(qout));
251

12450
      lg2.randomConfiguration(Q2(lower), Q2(upper), Qo2(qout));
252
12450
    }
253
254
    template <class ConfigL_t, class ConfigR_t>
255
18
    bool isSameConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
256
                                  const Eigen::MatrixBase<ConfigR_t> & q1,
257
                                  const Scalar & prec) const
258
    {
259
18
      return lg1.isSameConfiguration(Q1(q0), Q1(q1), prec)
260




18
        &&   lg2.isSameConfiguration(Q2(q0), Q2(q1), prec);
261
    }
262
263
    bool isEqual_impl (const CartesianProductOperation& other) const
264
    {
265
      return lg1 == other.lg1 && lg2 == other.lg2;
266
    }
267
268
    LieGroup1 lg1;
269
    LieGroup2 lg2;
270
271
  private:
272
    // VectorSpaceOperationTpl<-1> within CartesianProductOperation will not work
273
    // if Eigen version is lower than 3.2.1
274
#if EIGEN_VERSION_AT_LEAST(3,2,1)
275
# define REMOVE_IF_EIGEN_TOO_LOW(x) x
276
#else
277
# define REMOVE_IF_EIGEN_TOO_LOW(x)
278
#endif
279
280
31420
    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())); }
281
15710
    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())); }
282
1316
    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())); }
283
1316
    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())); }
284
285
15854
    template <typename Config > typename Config ::template      FixedSegmentReturnType<LieGroup1::NQ>::Type Qo1 (const Eigen::MatrixBase<Config >& q) const { return PINOCCHIO_EIGEN_CONST_CAST(Config,q).template head<LieGroup1::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg1.nq())); }
286
7927
    template <typename Config > typename Config ::template      FixedSegmentReturnType<LieGroup2::NQ>::Type Qo2 (const Eigen::MatrixBase<Config >& q) const { return PINOCCHIO_EIGEN_CONST_CAST(Config,q).template tail<LieGroup2::NQ>(REMOVE_IF_EIGEN_TOO_LOW(lg2.nq())); }
287
779
    template <typename Tangent> typename Tangent::template      FixedSegmentReturnType<LieGroup1::NV>::Type Vo1 (const Eigen::MatrixBase<Tangent>& v) const { return PINOCCHIO_EIGEN_CONST_CAST(Tangent,v).template head<LieGroup1::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg1.nv())); }
288
779
    template <typename Tangent> typename Tangent::template      FixedSegmentReturnType<LieGroup2::NV>::Type Vo2 (const Eigen::MatrixBase<Tangent>& v) const { return PINOCCHIO_EIGEN_CONST_CAST(Tangent,v).template tail<LieGroup2::NV>(REMOVE_IF_EIGEN_TOO_LOW(lg2.nv())); }
289
290
572
    template <typename Jac> Eigen::Block<Jac, LieGroup1::NV, LieGroup1::NV> J11 (const Eigen::MatrixBase<Jac>& J) const { return PINOCCHIO_EIGEN_CONST_CAST(Jac,J).template     topLeftCorner<LieGroup1::NV, LieGroup1::NV>(lg1.nv(),lg1.nv()); }
291
288
    template <typename Jac> Eigen::Block<Jac, LieGroup1::NV, LieGroup2::NV> J12 (const Eigen::MatrixBase<Jac>& J) const { return PINOCCHIO_EIGEN_CONST_CAST(Jac,J).template    topRightCorner<LieGroup1::NV, LieGroup2::NV>(lg1.nv(),lg2.nv()); }
292
288
    template <typename Jac> Eigen::Block<Jac, LieGroup2::NV, LieGroup1::NV> J21 (const Eigen::MatrixBase<Jac>& J) const { return PINOCCHIO_EIGEN_CONST_CAST(Jac,J).template  bottomLeftCorner<LieGroup2::NV, LieGroup1::NV>(lg2.nv(),lg1.nv()); }
293
288
    template <typename Jac> Eigen::Block<Jac, LieGroup2::NV, LieGroup2::NV> J22 (const Eigen::MatrixBase<Jac>& J) const { return PINOCCHIO_EIGEN_CONST_CAST(Jac,J).template bottomRightCorner<LieGroup2::NV, LieGroup2::NV>(lg2.nv(),lg2.nv()); }
294
#undef REMOVE_IF_EIGEN_TOO_LOW
295
296
  }; // struct CartesianProductOperation
297
298
} // namespace pinocchio
299
300
#endif // ifndef __pinocchio_multibody_liegroup_cartesian_product_operation_hpp__