GCC Code Coverage Report


Directory: ./
File: include/hpp/constraints/symbolic-calculus.hh
Date: 2025-05-05 12:19:30
Exec Total Coverage
Lines: 277 382 72.5%
Branches: 180 545 33.0%

Line Branch Exec Source
1 // Copyright (c) 2014, LAAS-CNRS
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // 1. Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28
29 #ifndef HPP_CONSTRAINTS_SYMBOLIC_CALCULUS_HH
30 #define HPP_CONSTRAINTS_SYMBOLIC_CALCULUS_HH
31
32 #define HPP_CONSTRAINTS_CB_REF shared_ptr
33 #define HPP_CONSTRAINTS_CB_WKREF shared_ptr
34
35 #define HPP_CONSTRAINTS_CB_DEFINE_OPERATOR1(op, InType, OutType) \
36 template <typename RhsType> \
37 typename Traits<OutType<RhsType> >::Ptr_t op( \
38 const InType& lhs, const HPP_CONSTRAINTS_CB_REF<RhsType>& rhs) { \
39 typedef OutType<RhsType> Op_t; \
40 return Op_t::create(lhs, rhs); \
41 }
42 #define HPP_CONSTRAINTS_CB_FRIEND_OPERATOR1(op, InType, OutType) \
43 template <typename RhsType> \
44 friend typename Traits<OutType<RhsType> >::Ptr_t op( \
45 const InType& lhs, const HPP_CONSTRAINTS_CB_REF<RhsType>& rhs);
46
47 #define HPP_CONSTRAINTS_CB_DEFINE_OPERATOR2(op, OutType) \
48 template <typename LhsType, typename RhsType> \
49 typename Traits<OutType<LhsType, RhsType> >::Ptr_t op( \
50 const HPP_CONSTRAINTS_CB_REF<LhsType>& lhs, \
51 const HPP_CONSTRAINTS_CB_REF<RhsType>& rhs) { \
52 typedef OutType<LhsType, RhsType> Op_t; \
53 return Op_t::create(lhs, rhs); \
54 }
55
56 #define HPP_CONSTRAINTS_CB_FRIEND_OPERATOR2(op, OutType) \
57 template <typename LhsType, typename RhsType> \
58 friend typename Traits<OutType<LhsType, RhsType> >::Ptr_t op( \
59 const HPP_CONSTRAINTS_CB_REF<LhsType>& lhs, \
60 const HPP_CONSTRAINTS_CB_REF<RhsType>& rhs);
61
62 #define HPP_CONSTRAINTS_CB_CREATE1(Class, Arg0Type) \
63 static typename Traits<Class>::Ptr_t create(Arg0Type arg0) { \
64 typename Traits<Class>::Ptr_t ptr(new Class(arg0)); \
65 ptr->init(ptr); \
66 return ptr; \
67 }
68
69 #define HPP_CONSTRAINTS_CB_CREATE2(Class, Arg0Type, Arg1Type) \
70 static typename Traits<Class>::Ptr_t create(Arg0Type arg0, Arg1Type arg1) { \
71 typename Traits<Class>::Ptr_t ptr(new Class(arg0, arg1)); \
72 ptr->init(ptr); \
73 return ptr; \
74 }
75
76 #define HPP_CONSTRAINTS_CB_CREATE3(Class, Arg0Type, Arg1Type, Arg2Type) \
77 static typename Traits<Class>::Ptr_t create(Arg0Type arg0, Arg1Type arg1, \
78 Arg2Type arg2) { \
79 typename Traits<Class>::Ptr_t ptr(new Class(arg0, arg1, arg2)); \
80 ptr->init(ptr); \
81 return ptr; \
82 }
83
84 #include <Eigen/SVD>
85 #include <hpp/constraints/fwd.hh>
86 #include <hpp/constraints/macros.hh>
87 #include <hpp/constraints/svd.hh>
88 #include <hpp/constraints/tools.hh>
89 #include <hpp/pinocchio/center-of-mass-computation.hh>
90 #include <hpp/pinocchio/joint.hh>
91 #include <hpp/pinocchio/liegroup-element.hh>
92
93 namespace hpp {
94 namespace constraints {
95 /// \defgroup symbolic_calculus Symbolic calculus
96
97 /// \addtogroup symbolic_calculus
98 /// \{
99
100 template <typename ValueType, typename JacobianType>
101 class CalculusBaseAbstract;
102 template <typename T>
103 class Traits;
104
105 template <typename LhsValue, typename RhsValue>
106 class Expression;
107 template <typename LhsValue, typename RhsValue>
108 class CrossProduct;
109 template <typename LhsValue, typename RhsValue>
110 class ScalarProduct;
111 template <typename LhsValue, typename RhsValue>
112 class Difference;
113 template <typename LhsValue, typename RhsValue>
114 class Sum;
115 template <typename RhsValue>
116 class ScalarMultiply;
117 template <typename RhsValue>
118 class RotationMultiply;
119 typedef eigen::matrix3_t CrossMatrix;
120 typedef Eigen::Matrix<value_type, 1, Eigen::Dynamic, Eigen::RowMajor>
121 RowJacobianMatrix;
122 typedef Eigen::Matrix<value_type, 3, Eigen::Dynamic, Eigen::RowMajor>
123 JacobianMatrix;
124
125 template <typename Class>
126 struct Traits {
127 typedef HPP_CONSTRAINTS_CB_REF<Class> Ptr_t;
128 typedef HPP_CONSTRAINTS_CB_WKREF<Class> WkPtr_t;
129 };
130 template <>
131 struct Traits<value_type> {
132 typedef value_type Ptr_t;
133 typedef value_type WkPtr_t;
134 };
135 template <>
136 struct Traits<pinocchio::Joint> {
137 typedef JointPtr_t Ptr_t;
138 typedef JointPtr_t WkPtr_t;
139 };
140
141 struct JointTranspose {
142 1 JointTranspose(const JointPtr_t& joint) : j_(joint) {}
143 const JointPtr_t j_;
144 };
145 template <>
146 struct Traits<JointTranspose> {
147 typedef JointTranspose Ptr_t;
148 typedef JointTranspose WkPtr_t;
149 };
150
151 /// Abstract class defining a basic common interface.
152 ///
153 /// The purpose of this class is to allow the user to define an expression
154 /// without requiring to explicitly write its type. The type will be
155 /// automatically deduced by the compiler.
156 ///
157 /// \code
158 /// // First define a, b and c with basic elements.
159 /// CalculusBaseAbstract<OutValueType, OutJacobianType>::Ptr_t
160 /// myExpression_ptr =
161 /// CalculusBaseAbstract<OutValueType, OutJacobianType>::create (a + b * c)
162 /// \endcode
163 template <class ValueType = eigen::vector3_t,
164 class JacobianType = JacobianMatrix>
165 class CalculusBaseAbstract {
166 public:
167 typedef ValueType ValueType_t;
168 typedef JacobianType JacobianType_t;
169
170 virtual const ValueType& value() const = 0;
171 virtual const JacobianType& jacobian() const = 0;
172 virtual void computeValue(const ConfigurationIn_t arg) = 0;
173 virtual void computeJacobian(const ConfigurationIn_t arg) = 0;
174 virtual void invalidate() = 0;
175 };
176
177 /// Main abstract class.
178 ///
179 /// The framework is using CRTP to virtual function calls overload.
180 /// Keep in mind, so far, no mathematical simplification is done on the
181 /// expression you provide. It means that you may have a more efficient
182 /// expression by calculating and simplifying the jacobian yourself.
183 /// These classes provide:
184 /// \li a fast way of defining new constraints,
185 /// \li a robust way of calculation of jacobians -
186 /// hand calculation error proof
187 /// \li a fast way to check the results of your calculations.
188 template <class T, class ValueType = vector3_t,
189 class JacobianType = JacobianMatrix, class CrossType = CrossMatrix>
190 class CalculusBase : public CalculusBaseAbstract<ValueType, JacobianType> {
191 public:
192
3/5
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 49 times.
✗ Branch 8 not taken.
118 CalculusBase() : cross_(CrossMatrix::Zero()) {}
193
194 5 CalculusBase(const ValueType& value, const JacobianType& jacobian)
195
5/8
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
5 : value_(value), jacobian_(jacobian), cross_(CrossMatrix::Zero()) {}
196
197 CalculusBase(const CalculusBase& o)
198 : value_(o.value()), jacobian_(o.jacobian_), cross_(o.cross()) {}
199
200 37270 inline const ValueType& value() const { return value_; }
201 109638 inline const JacobianType& jacobian() const { return jacobian_; }
202 21004 void computeValue(const ConfigurationIn_t arg) {
203
2/2
✓ Branch 0 taken 5520 times.
✓ Branch 1 taken 15484 times.
42008 if (vValid_) return;
204
1/2
✓ Branch 2 taken 14714 times.
✗ Branch 3 not taken.
30968 static_cast<T*>(this)->impl_value(arg);
205 30968 vValid_ = true;
206 }
207 48638 void computeJacobian(const ConfigurationIn_t arg) {
208
2/2
✓ Branch 0 taken 41806 times.
✓ Branch 1 taken 6832 times.
97276 if (jValid_) return;
209
1/2
✓ Branch 2 taken 5016 times.
✗ Branch 3 not taken.
13664 static_cast<T*>(this)->impl_jacobian(arg);
210 13664 jValid_ = true;
211 }
212 22026 void invalidate() {
213 44052 vValid_ = false;
214 44052 jValid_ = false;
215 44052 cValid_ = false;
216 44052 }
217 5059 inline const CrossType& cross() const { return cross_; }
218 5059 void computeCrossValue(const ConfigurationIn_t arg) {
219
2/2
✓ Branch 0 taken 1284 times.
✓ Branch 1 taken 3775 times.
10018 if (cValid_) return;
220
1/2
✓ Branch 2 taken 3775 times.
✗ Branch 3 not taken.
7450 computeValue(arg);
221 7450 computeCrossMatrix(value_, cross_);
222 7450 cValid_ = true;
223 }
224
225 protected:
226 ValueType value_;
227 JacobianType jacobian_;
228 CrossType cross_;
229
230 bool vValid_, jValid_, cValid_;
231
232 122 void init(const typename Traits<T>::Ptr_t& ptr) { wkPtr_ = ptr; }
233
234 private:
235 typename Traits<T>::WkPtr_t wkPtr_;
236
237 public:
238 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
239 };
240
241 15 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR2(operator-, Difference)
242 2 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR2(operator+, Sum)
243 29 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR2(operator*, ScalarProduct)
244 15 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR2(operator^, CrossProduct)
245
246 1 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR1(operator*, value_type, ScalarMultiply)
247 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR1(operator*, JointPtr_t, RotationMultiply)
248 1 HPP_CONSTRAINTS_CB_DEFINE_OPERATOR1(operator*, JointTranspose, RotationMultiply)
249
250 /// Base class for classes representing an operation.
251 template <typename LhsValue, typename RhsValue>
252 class Expression {
253 public:
254 typedef shared_ptr<Expression<LhsValue, RhsValue> > Ptr_t;
255 typedef weak_ptr<Expression<LhsValue, RhsValue> > WkPtr_t;
256
257 static Ptr_t create() {
258 Ptr_t p(new Expression());
259 p->init(p);
260 return p;
261 }
262
263 80 static Ptr_t create(const typename Traits<LhsValue>::Ptr_t& lhs,
264 const typename Traits<RhsValue>::Ptr_t& rhs) {
265
1/2
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
80 Ptr_t p(new Expression(lhs, rhs));
266 80 p->init(p);
267 80 return p;
268 }
269
270 const LhsValue& lhs() const { return lhs_; }
271
272 const RhsValue& rhs() const { return rhs_; }
273
274 Expression() {}
275
276 Expression(const Expression& other) : rhs_(other.rhs()), lhs_(other.lhs()) {}
277
278 80 Expression(const typename Traits<LhsValue>::Ptr_t& lhs,
279 const typename Traits<RhsValue>::Ptr_t& rhs)
280 80 : rhs_(rhs), lhs_(lhs) {}
281
282 80 inline void init(Ptr_t self) { self_ = self; }
283
284 typename Traits<RhsValue>::Ptr_t rhs_;
285 typename Traits<LhsValue>::Ptr_t lhs_;
286 typename Traits<Expression>::WkPtr_t self_;
287
288 public:
289 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
290 };
291
292 /// Cross product of two expressions.
293 template <typename LhsValue, typename RhsValue>
294 class CrossProduct : public CalculusBase<CrossProduct<LhsValue, RhsValue> > {
295 public:
296 typedef CalculusBase<CrossProduct<LhsValue, RhsValue> > Parent_t;
297
298
2/4
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
26 HPP_CONSTRAINTS_CB_CREATE2(CrossProduct,
299 const typename Traits<LhsValue>::Ptr_t&,
300 const typename Traits<RhsValue>::Ptr_t&)
301
302 CrossProduct() {}
303
304 CrossProduct(const CalculusBase<CrossProduct>& other)
305 : Parent_t(other), e_(static_cast<const CrossProduct&>(other).e_) {}
306
307 26 CrossProduct(const typename Traits<LhsValue>::Ptr_t& lhs,
308 const typename Traits<RhsValue>::Ptr_t& rhs)
309
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
26 : e_(Expression<LhsValue, RhsValue>::create(lhs, rhs)) {}
310
311 5742 void impl_value(const ConfigurationIn_t arg) {
312
1/2
✓ Branch 4 taken 2871 times.
✗ Branch 5 not taken.
5742 e_->lhs_->computeCrossValue(arg);
313
1/2
✓ Branch 4 taken 2871 times.
✗ Branch 5 not taken.
5742 e_->rhs_->computeValue(arg);
314
1/2
✓ Branch 8 taken 2871 times.
✗ Branch 9 not taken.
5742 this->value_ = e_->lhs_->cross() * e_->rhs_->value();
315 5742 }
316 1044 void impl_jacobian(const ConfigurationIn_t arg) {
317
1/2
✓ Branch 4 taken 1044 times.
✗ Branch 5 not taken.
2088 e_->lhs_->computeCrossValue(arg);
318
1/2
✓ Branch 4 taken 1044 times.
✗ Branch 5 not taken.
2088 e_->rhs_->computeCrossValue(arg);
319
1/2
✓ Branch 4 taken 1044 times.
✗ Branch 5 not taken.
2088 e_->lhs_->computeJacobian(arg);
320
1/2
✓ Branch 4 taken 1044 times.
✗ Branch 5 not taken.
2088 e_->rhs_->computeJacobian(arg);
321
4/8
✓ Branch 3 taken 1044 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 1044 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1044 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1044 times.
✗ Branch 16 not taken.
2088 this->jacobian_ = e_->lhs_->cross() * e_->rhs_->jacobian() -
322 2088 e_->rhs_->cross() * e_->lhs_->jacobian();
323 2088 }
324 2871 void invalidate() {
325 5742 Parent_t::invalidate();
326 5742 e_->rhs_->invalidate();
327 5742 e_->lhs_->invalidate();
328 5742 }
329
330 protected:
331 typename Expression<LhsValue, RhsValue>::Ptr_t e_;
332
333 friend class Expression<LhsValue, RhsValue>;
334 };
335
336 /// Scalar product of two expressions.
337 template <typename LhsValue, typename RhsValue>
338 class ScalarProduct
339 : public CalculusBase<ScalarProduct<LhsValue, RhsValue>,
340 Eigen::Matrix<value_type, 1, 1>, RowJacobianMatrix> {
341 public:
342 typedef CalculusBase<ScalarProduct<LhsValue, RhsValue>,
343 Eigen::Matrix<value_type, 1, 1>, RowJacobianMatrix>
344 Parent_t;
345
346
2/4
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
29 HPP_CONSTRAINTS_CB_CREATE2(ScalarProduct,
347 const typename Traits<LhsValue>::Ptr_t&,
348 const typename Traits<RhsValue>::Ptr_t&)
349
350 ScalarProduct() {}
351
352 ScalarProduct(const CalculusBase<ScalarProduct>& other)
353 : CalculusBase<ScalarProduct>(other),
354 e_(static_cast<const ScalarProduct&>(other).e_) {}
355
356 29 ScalarProduct(const typename Traits<LhsValue>::Ptr_t& lhs,
357 const typename Traits<RhsValue>::Ptr_t& rhs)
358
1/2
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
29 : e_(Expression<LhsValue, RhsValue>::create(lhs, rhs)) {}
359
360 2718 void impl_value(const ConfigurationIn_t arg) {
361
1/2
✓ Branch 4 taken 1409 times.
✗ Branch 5 not taken.
2718 e_->lhs_->computeValue(arg);
362
1/2
✓ Branch 4 taken 1409 times.
✗ Branch 5 not taken.
2718 e_->rhs_->computeValue(arg);
363 2718 this->value_[0] = e_->lhs_->value().dot(e_->rhs_->value());
364 2718 }
365 706 void impl_jacobian(const ConfigurationIn_t arg) {
366
1/2
✓ Branch 4 taken 706 times.
✗ Branch 5 not taken.
1312 e_->lhs_->computeValue(arg);
367
1/2
✓ Branch 4 taken 706 times.
✗ Branch 5 not taken.
1312 e_->rhs_->computeValue(arg);
368
1/2
✓ Branch 4 taken 706 times.
✗ Branch 5 not taken.
1312 e_->lhs_->computeJacobian(arg);
369
1/2
✓ Branch 4 taken 706 times.
✗ Branch 5 not taken.
1312 e_->rhs_->computeJacobian(arg);
370
6/12
✓ Branch 3 taken 706 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 706 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 706 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 706 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 706 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 706 times.
✗ Branch 21 not taken.
1312 this->jacobian_ = e_->lhs_->value().transpose() * e_->rhs_->jacobian() +
371
1/2
✓ Branch 8 taken 706 times.
✗ Branch 9 not taken.
1312 e_->rhs_->value().transpose() * e_->lhs_->jacobian();
372 1312 }
373 2015 void invalidate() {
374 3930 Parent_t::invalidate();
375 3930 e_->rhs_->invalidate();
376 3930 e_->lhs_->invalidate();
377 3930 }
378
379 protected:
380 typename Expression<LhsValue, RhsValue>::Ptr_t e_;
381
382 friend class Expression<LhsValue, RhsValue>;
383 };
384
385 /// Difference of two expressions.
386 template <typename LhsValue, typename RhsValue>
387 class Difference : public CalculusBase<Difference<LhsValue, RhsValue> > {
388 public:
389 typedef CalculusBase<Difference<LhsValue, RhsValue> > Parent_t;
390
391
2/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
15 HPP_CONSTRAINTS_CB_CREATE2(Difference,
392 const typename Traits<LhsValue>::Ptr_t&,
393 const typename Traits<RhsValue>::Ptr_t&)
394
395 Difference() {}
396
397 Difference(const CalculusBase<Difference>& other)
398 : CalculusBase<Difference>(other),
399 e_(static_cast<const Difference&>(other).e_) {}
400
401 15 Difference(const typename Traits<LhsValue>::Ptr_t& lhs,
402 const typename Traits<RhsValue>::Ptr_t& rhs)
403
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
15 : e_(Expression<LhsValue, RhsValue>::create(lhs, rhs)) {}
404
405 6614 void impl_value(const ConfigurationIn_t arg) {
406
1/2
✓ Branch 4 taken 3357 times.
✗ Branch 5 not taken.
6614 e_->lhs_->computeValue(arg);
407
1/2
✓ Branch 4 taken 3357 times.
✗ Branch 5 not taken.
6614 e_->rhs_->computeValue(arg);
408
1/2
✓ Branch 8 taken 3357 times.
✗ Branch 9 not taken.
6614 this->value_ = e_->lhs_->value() - e_->rhs_->value();
409 6614 }
410 1266 void impl_jacobian(const ConfigurationIn_t arg) {
411
1/2
✓ Branch 4 taken 1266 times.
✗ Branch 5 not taken.
2432 e_->lhs_->computeJacobian(arg);
412
1/2
✓ Branch 4 taken 1266 times.
✗ Branch 5 not taken.
2432 e_->rhs_->computeJacobian(arg);
413
1/2
✓ Branch 8 taken 1266 times.
✗ Branch 9 not taken.
2432 this->jacobian_ = e_->lhs_->jacobian() - e_->rhs_->jacobian();
414 2432 }
415 4117 void invalidate() {
416 8134 Parent_t::invalidate();
417 8134 e_->rhs_->invalidate();
418 8134 e_->lhs_->invalidate();
419 8134 }
420
421 protected:
422 typename Expression<LhsValue, RhsValue>::Ptr_t e_;
423
424 friend class Expression<LhsValue, RhsValue>;
425 };
426
427 /// Sum of two expressions.
428 template <typename LhsValue, typename RhsValue>
429 class Sum : public CalculusBase<Sum<LhsValue, RhsValue> > {
430 public:
431 typedef CalculusBase<Sum<LhsValue, RhsValue> > Parent_t;
432
433
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
4 HPP_CONSTRAINTS_CB_CREATE2(Sum, const typename Traits<LhsValue>::Ptr_t&,
434 const typename Traits<RhsValue>::Ptr_t&)
435
436 Sum() {}
437
438 Sum(const CalculusBase<Sum>& other)
439 : CalculusBase<Sum>(other), e_(static_cast<const Sum&>(other).e_) {}
440
441 4 Sum(const typename Traits<RhsValue>::Ptr_t& rhs,
442 const typename Traits<LhsValue>::Ptr_t& lhs)
443
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 : e_(Expression<LhsValue, RhsValue>::create(lhs, rhs)) {}
444
445 400 void impl_value(const ConfigurationIn_t arg) {
446
1/2
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
400 e_->lhs_->computeValue(arg);
447
1/2
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
400 e_->rhs_->computeValue(arg);
448
1/2
✓ Branch 8 taken 200 times.
✗ Branch 9 not taken.
400 this->value_ = e_->lhs_->value() + e_->rhs_->value();
449 400 }
450 200 void impl_jacobian(const ConfigurationIn_t arg) {
451
1/2
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
400 e_->lhs_->computeJacobian(arg);
452
1/2
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
400 e_->rhs_->computeJacobian(arg);
453
1/2
✓ Branch 8 taken 200 times.
✗ Branch 9 not taken.
400 this->jacobian_ = e_->lhs_->jacobian() + e_->rhs_->jacobian();
454 400 }
455 200 void invalidate() {
456 400 Parent_t::invalidate();
457 400 e_->rhs_->invalidate();
458 400 e_->lhs_->invalidate();
459 400 }
460
461 protected:
462 typename Expression<LhsValue, RhsValue>::Ptr_t e_;
463
464 friend class Expression<LhsValue, RhsValue>;
465 };
466
467 /// Multiplication of an expression by a scalar.
468 template <typename RhsValue>
469 class ScalarMultiply : public CalculusBase<ScalarMultiply<RhsValue> > {
470 public:
471 typedef CalculusBase<ScalarMultiply<RhsValue> > Parent_t;
472
473
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 HPP_CONSTRAINTS_CB_CREATE2(ScalarMultiply,
474 const typename Traits<value_type>::Ptr_t&,
475 const typename Traits<RhsValue>::Ptr_t&)
476
477 ScalarMultiply() {}
478
479 ScalarMultiply(const CalculusBase<ScalarMultiply>& other)
480 : CalculusBase<ScalarMultiply>(other),
481 e_(static_cast<const ScalarMultiply&>(other).e_) {}
482
483 1 ScalarMultiply(const typename Traits<value_type>::Ptr_t& scalar,
484 const typename Traits<RhsValue>::Ptr_t& rhs)
485
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 : e_(Expression<value_type, RhsValue>::create(scalar, rhs)) {}
486
487 100 void impl_value(const ConfigurationIn_t arg) {
488
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 e_->rhs_->computeValue(arg);
489
1/2
✓ Branch 6 taken 100 times.
✗ Branch 7 not taken.
100 this->value_ = e_->lhs_ * e_->rhs_->value();
490 100 }
491 100 void impl_jacobian(const ConfigurationIn_t arg) {
492
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 e_->rhs_->computeJacobian(arg);
493
1/2
✓ Branch 6 taken 100 times.
✗ Branch 7 not taken.
100 this->jacobian_ = e_->lhs_ * e_->rhs_->jacobian();
494 100 }
495 100 void invalidate() {
496 100 Parent_t::invalidate();
497 100 e_->rhs_->invalidate();
498 100 }
499
500 protected:
501 typename Expression<value_type, RhsValue>::Ptr_t e_;
502
503 friend class Expression<value_type, RhsValue>;
504 };
505
506 /// Multiplication of an expression by a rotation matrix.
507 template <typename RhsValue>
508 class RotationMultiply : public CalculusBase<RotationMultiply<RhsValue> > {
509 public:
510 typedef CalculusBase<RotationMultiply<RhsValue> > Parent_t;
511
512 RotationMultiply() {}
513
514 RotationMultiply(const CalculusBase<RotationMultiply>& other)
515 : CalculusBase<RotationMultiply>(other),
516 e_(static_cast<const RotationMultiply&>(other).e_),
517 transpose_(other.transpose_) {}
518
519 HPP_CONSTRAINTS_CB_CREATE2(RotationMultiply,
520 const typename Traits<pinocchio::Joint>::Ptr_t&,
521 const typename Traits<RhsValue>::Ptr_t&)
522
523
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 HPP_CONSTRAINTS_CB_CREATE2(RotationMultiply,
524 const typename Traits<JointTranspose>::Ptr_t&,
525 const typename Traits<RhsValue>::Ptr_t&)
526
527 1 RotationMultiply(const typename Traits<JointTranspose>::Ptr_t& joint,
528 const typename Traits<RhsValue>::Ptr_t& rhs)
529 1 : e_(Expression<pinocchio::Joint, RhsValue>::create(joint.j_, rhs)),
530
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 transpose_(true) {}
531
532 RotationMultiply(const typename Traits<pinocchio::Joint>::Ptr_t& joint,
533 const typename Traits<RhsValue>::Ptr_t& rhs,
534 bool transpose = false)
535 : e_(Expression<pinocchio::Joint, RhsValue>::create(joint, rhs)),
536 transpose_(transpose) {}
537
538 100 void impl_value(const ConfigurationIn_t arg) {
539
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 e_->rhs_->computeValue(arg);
540 100 const matrix3_t& R = e_->lhs_->currentTransformation().rotation();
541
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 if (transpose_)
542
2/4
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
100 this->value_ = R.transpose() * e_->rhs_->value();
543 else
544 this->value_ = R * e_->rhs_->value();
545 100 }
546 100 void impl_jacobian(const ConfigurationIn_t arg) {
547
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 e_->rhs_->computeJacobian(arg);
548
1/2
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 e_->rhs_->computeCrossValue(arg);
549 100 const JointJacobian_t& J = e_->lhs_->jacobian();
550 100 const matrix3_t& R = e_->lhs_->currentTransformation().rotation();
551
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 if (transpose_)
552
3/6
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
200 this->jacobian_ =
553
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
100 R.transpose() *
554
2/4
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
200 ((e_->rhs_->cross() * R) * J.bottomRows<3>() + e_->rhs_->jacobian());
555 else
556 this->jacobian_ = R * ((e_->rhs_->cross() * R) * J.bottomRows<3>() +
557 e_->rhs_->jacobian());
558 100 }
559 100 void invalidate() {
560 100 Parent_t::invalidate();
561 100 e_->rhs_->invalidate();
562 100 }
563
564 protected:
565 typename Expression<pinocchio::Joint, RhsValue>::Ptr_t e_;
566
567 friend class Expression<pinocchio::Joint, RhsValue>;
568
569 private:
570 bool transpose_;
571 };
572
573 /// Basic expression representing a point in a joint frame.
574 class PointInJoint : public CalculusBase<PointInJoint> {
575 public:
576 typedef CalculusBase<PointInJoint> Parent_t;
577
578
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 HPP_CONSTRAINTS_CB_CREATE2(PointInJoint, const JointPtr_t&, const vector3_t&)
579 HPP_CONSTRAINTS_CB_CREATE3(PointInJoint, const JointPtr_t&, const vector3_t&,
580 const size_type&)
581
582 PointInJoint() {}
583
584 PointInJoint(const CalculusBase<PointInJoint>& other)
585 : CalculusBase<PointInJoint>(other) {
586 const PointInJoint& o = static_cast<const PointInJoint&>(other);
587 joint_ = o.joint();
588 local_ = o.local();
589 center_ = local_.isZero();
590 }
591
592 PointInJoint(const PointInJoint& pointInJoint)
593 : CalculusBase<PointInJoint>(pointInJoint),
594 joint_(pointInJoint.joint()),
595 local_(pointInJoint.local()),
596 center_(local_.isZero()) {}
597
598 2 PointInJoint(const JointPtr_t& joint, const vector3_t& pointInLocalFrame)
599 4 : joint_(joint),
600
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 local_(pointInLocalFrame),
601
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 center_(pointInLocalFrame.isZero()) {
602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 assert(joint_ != NULL);
603 2 }
604
605 PointInJoint(const JointPtr_t& joint, const vector3_t& pointInLocalFrame,
606 size_type nbDof)
607 : joint_(joint),
608 local_(pointInLocalFrame),
609 center_(pointInLocalFrame.isZero()) {
610 if (joint_ == NULL) {
611 for (int i = 0; i < 3; ++i) this->value_[i] = local_[i];
612 this->jacobian_.resize(3, nbDof);
613 this->jacobian_.setZero();
614 this->cross_.setZero();
615 }
616 }
617
618 const JointPtr_t& joint() const { return joint_; }
619 const vector3_t& local() const { return local_; }
620 200 void impl_value(const ConfigurationIn_t) {
621
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
200 if (joint_ == NULL) return;
622 200 this->value_ = joint_->currentTransformation().act(local_);
623 }
624 200 void impl_jacobian(const ConfigurationIn_t) {
625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
200 if (joint_ == NULL) return;
626 200 const JointJacobian_t& J(joint_->jacobian());
627 200 const matrix3_t& R = joint_->currentTransformation().rotation();
628
3/6
✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 200 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 200 times.
✗ Branch 9 not taken.
200 this->jacobian_.noalias() = R * J.topRows<3>();
629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (!center_) {
630 computeCrossRXl();
631 this->jacobian_.noalias() -= (this->cross_ * R) * J.bottomRows<3>();
632 }
633 }
634 void computeCrossRXl() {
635 if (joint_ == NULL) return;
636 if (center_) {
637 this->cross_.setZero();
638 return;
639 }
640 computeCrossMatrix(joint_->currentTransformation().rotation() * local_,
641 this->cross_);
642 }
643
644 protected:
645 JointPtr_t joint_;
646 vector3_t local_;
647 bool center_;
648
649 public:
650 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
651 };
652
653 /// Basic expression representing a vector in a joint frame.
654 class VectorInJoint : public CalculusBase<VectorInJoint> {
655 public:
656 HPP_CONSTRAINTS_CB_CREATE2(VectorInJoint, const JointPtr_t&, const vector3_t&)
657 HPP_CONSTRAINTS_CB_CREATE3(VectorInJoint, const JointPtr_t&, const vector3_t&,
658 const size_type&)
659
660 VectorInJoint() {}
661
662 VectorInJoint(const CalculusBase<VectorInJoint>& other)
663 : CalculusBase<VectorInJoint>(other),
664 joint_(static_cast<const VectorInJoint&>(other).joint()),
665 vector_(static_cast<const VectorInJoint&>(other).vector()) {}
666
667 VectorInJoint(const VectorInJoint& vectorInJoint)
668 : CalculusBase<VectorInJoint>(vectorInJoint),
669 joint_(vectorInJoint.joint()),
670 vector_(vectorInJoint.vector()) {}
671
672 VectorInJoint(const JointPtr_t& joint, const vector3_t& vectorInLocalFrame)
673 : joint_(joint), vector_(vectorInLocalFrame) {}
674
675 VectorInJoint(const JointPtr_t& joint, const vector3_t& vectorInLocalFrame,
676 const size_type& nbDof)
677 : joint_(joint), vector_(vectorInLocalFrame) {
678 if (joint_ == NULL) {
679 for (int i = 0; i < 3; ++i) this->value_[i] = vector_[i];
680 this->jacobian_.resize(3, nbDof);
681 this->jacobian_.setZero();
682 this->cross_.setZero();
683 }
684 }
685
686 const JointPtr_t& joint() const { return joint_; }
687 const vector3_t& vector() const { return vector_; }
688 void impl_value(const ConfigurationIn_t) {
689 if (joint_ == NULL) return;
690 this->value_ = joint_->currentTransformation().rotation() * vector_;
691 }
692 void impl_jacobian(const ConfigurationIn_t) {
693 if (joint_ == NULL) return;
694 const JointJacobian_t& J(joint_->jacobian());
695 const matrix3_t& R = joint_->currentTransformation().rotation();
696 computeCrossRXl();
697 this->jacobian_.noalias() = (-this->cross_ * R) * J.bottomRows<3>();
698 }
699 void computeCrossRXl() {
700 if (joint_ == NULL) return;
701 computeCrossMatrix(joint_->currentTransformation().rotation() * vector_,
702 this->cross_);
703 }
704
705 protected:
706 JointPtr_t joint_;
707 vector3_t vector_;
708
709 public:
710 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
711 };
712
713 /// Basic expression mapping a function as an expression
714 template <typename FunctionType>
715 class FunctionExp
716 : public CalculusBase<FunctionExp<FunctionType>, vector_t, matrix_t> {
717 public:
718 typedef CalculusBase<FunctionExp<FunctionType>, vector_t, matrix_t> Parent_t;
719 typedef shared_ptr<FunctionType> FunctionTypePtr_t;
720
721
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 HPP_CONSTRAINTS_CB_CREATE1(FunctionExp<FunctionType>,
722 const FunctionTypePtr_t&)
723
724 FunctionExp() {}
725
726 FunctionExp(const Parent_t& other)
727 : Parent_t(other), f_(other.f_), lge_(other.lge_) {}
728
729 FunctionExp(const FunctionExp& other)
730 : Parent_t(other), f_(other.f_), lge_(other.lge_) {}
731
732 /// Constructor
733 ///
734 /// \param func the inner function
735 1 FunctionExp(const FunctionTypePtr_t& func)
736 1 : Parent_t(vector_t::Zero(func->outputSize()),
737 1 matrix_t::Zero(func->outputDerivativeSize(),
738 1 func->inputDerivativeSize())),
739 1 f_(func),
740
5/10
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
3 lge_(func->outputSpace()) {}
741
742 100 void impl_value(const ConfigurationIn_t arg) {
743
2/4
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 100 times.
✗ Branch 7 not taken.
100 f_->value(lge_, arg);
744 100 this->value_ = lge_.vector();
745 100 }
746 100 void impl_jacobian(const ConfigurationIn_t arg) {
747
2/4
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 100 times.
✗ Branch 7 not taken.
100 f_->jacobian(this->jacobian_, arg);
748 100 }
749
750 private:
751 FunctionTypePtr_t f_;
752 LiegroupElement lge_;
753 };
754
755 /// Basic expression representing a static point
756 ///
757 /// Its value is constant and its jacobian is a zero matrix.
758 class Point : public CalculusBase<Point, vector3_t, JacobianMatrix> {
759 public:
760
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 HPP_CONSTRAINTS_CB_CREATE2(Point, const vector3_t&, const size_t&)
761
762 Point() {}
763
764 Point(const CalculusBase<Point, vector3_t, JacobianMatrix>& other)
765 : CalculusBase<Point, eigen::vector3_t, JacobianMatrix>(other) {}
766
767 Point(const Point& point)
768 : CalculusBase<Point, vector3_t, JacobianMatrix>(point) {}
769
770 /// Constructor
771 ///
772 /// \param point the static point
773 /// \param jacobianNbCols number of column of the jacobian
774 1 Point(const vector3_t& point, size_t jacobianNbCols)
775 1 : CalculusBase<Point, vector3_t, JacobianMatrix>(
776
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 point, JacobianMatrix::Zero(3, jacobianNbCols)) {}
777
778 770 void impl_value(const ConfigurationIn_t) {}
779 244 void impl_jacobian(const ConfigurationIn_t) {}
780 };
781
782 /// Basic expression representing a COM.
783 class PointCom : public CalculusBase<PointCom, vector3_t, ComJacobian_t> {
784 public:
785 typedef CalculusBase<PointCom, vector3_t, ComJacobian_t> Parent_t;
786 HPP_CONSTRAINTS_CB_CREATE1(PointCom, const CenterOfMassComputationPtr_t&)
787
788 PointCom() {}
789
790 PointCom(const Parent_t& other)
791 : Parent_t(other),
792 comc_(static_cast<const PointCom&>(other).centerOfMassComputation()) {}
793
794 PointCom(const CenterOfMassComputationPtr_t& comc) : comc_(comc) {}
795
796 inline const vector3_t& value() const { return comc_->com(); }
797 inline const ComJacobian_t& jacobian() const { return comc_->jacobian(); }
798
799 const CenterOfMassComputationPtr_t& centerOfMassComputation() const {
800 return comc_;
801 }
802 void impl_value(const ConfigurationIn_t) {
803 comc_->compute(hpp::pinocchio::COM);
804 }
805 void impl_jacobian(const ConfigurationIn_t) {
806 comc_->compute(hpp::pinocchio::COMPUTE_ALL);
807 // TODO: there is memory and time to be saved here as this copy is
808 // not important.
809 // this->jacobian_ = comc_->jacobian ();
810 }
811
812 protected:
813 CenterOfMassComputationPtr_t comc_;
814 };
815
816 class JointFrame
817 : public CalculusBase<JointFrame, Eigen::Matrix<value_type, 6, 1>,
818 Eigen::Matrix<value_type, 6, Eigen::Dynamic> > {
819 public:
820 typedef CalculusBase<JointFrame, ValueType_t, JacobianType_t> Parent_t;
821
822
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 HPP_CONSTRAINTS_CB_CREATE1(JointFrame, const JointPtr_t&)
823
824 JointFrame() {}
825
826 JointFrame(const Parent_t& other)
827 : Parent_t(other), joint_(static_cast<const JointFrame&>(other).joint_) {}
828
829 JointFrame(const JointFrame& jf) : Parent_t(jf), joint_(jf.joint()) {}
830
831 1 JointFrame(const JointPtr_t& joint) : joint_(joint) {
832
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 assert(joint_ != NULL);
833
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->jacobian_.resize(6,
834
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 joint->robot()->numberDof() -
835 2 joint->robot()->extraConfigSpace().dimension());
836 1 }
837
838 const JointPtr_t& joint() const { return joint_; }
839 200 void impl_value(const ConfigurationIn_t) {
840 200 const Transform3s& M = joint_->currentTransformation();
841
1/2
✓ Branch 3 taken 200 times.
✗ Branch 4 not taken.
200 this->value_.head<3>() = M.translation();
842
2/4
✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 200 times.
✗ Branch 6 not taken.
200 logSO3(M.rotation(), theta_, this->value_.tail<3>());
843 200 }
844 100 void impl_jacobian(const ConfigurationIn_t arg) {
845
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 computeValue(arg);
846
1/2
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
100 const JointJacobian_t& J(joint_->jacobian());
847
2/4
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
100 const matrix3_t& R(joint_->currentTransformation().rotation());
848 // Compute vector r
849
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
100 eigen::matrix3_t Jlog;
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 assert(theta_ >= 0);
851
2/4
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
100 JlogSO3(theta_, this->value_.tail<3>(), Jlog);
852
5/10
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 100 times.
✗ Branch 14 not taken.
100 this->jacobian_.topRows<3>().noalias() = R * J.topRows<3>();
853
5/10
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 100 times.
✗ Branch 14 not taken.
100 this->jacobian_.bottomRows<3>().noalias() = Jlog * J.bottomRows<3>();
854 100 }
855
856 protected:
857 JointPtr_t joint_;
858 double theta_;
859
860 public:
861 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
862 };
863
864 /// Matrix having Expression elements
865 template <typename ValueType = eigen::vector3_t,
866 typename JacobianType = JacobianMatrix>
867 class MatrixOfExpressions
868 : public CalculusBase<
869 MatrixOfExpressions<ValueType, JacobianType>,
870 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>,
871 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> > {
872 public:
873 typedef Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> Value_t;
874 typedef Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> Jacobian_t;
875 typedef Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> PseudoInv_t;
876 typedef Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>
877 PseudoInvJacobian_t;
878 typedef CalculusBase<MatrixOfExpressions, Value_t, Jacobian_t> Parent_t;
879 typedef CalculusBaseAbstract<ValueType, JacobianType> Element_t;
880 typedef typename Traits<Element_t>::Ptr_t ElementPtr_t;
881 typedef Eigen::JacobiSVD<Value_t> SVD_t;
882
883 HPP_CONSTRAINTS_CB_CREATE2(MatrixOfExpressions,
884 const Eigen::Ref<const Value_t>&,
885 const Eigen::Ref<const Jacobian_t>&)
886
887 1 MatrixOfExpressions(const Eigen::Ref<const Value_t>& value,
888 const Eigen::Ref<const Jacobian_t>& jacobian)
889 : Parent_t(value, jacobian),
890 1 nRows_(0),
891 1 nCols_(0),
892
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 svd_(value.rows(), value.cols(),
893 Eigen::ComputeFullU | Eigen::ComputeFullV),
894 1 piValid_(false),
895
6/12
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
2 svdValid_(false) {}
896
897 MatrixOfExpressions(const Parent_t& other)
898 : Parent_t(other),
899 nRows_(static_cast<const MatrixOfExpressions&>(other).nRows_),
900 nCols_(static_cast<const MatrixOfExpressions&>(other).nCols_),
901 elements_(static_cast<const MatrixOfExpressions&>(other).elements_),
902 svd_(static_cast<const MatrixOfExpressions&>(other).svd_),
903 piValid_(static_cast<const MatrixOfExpressions&>(other).piValid_),
904 svdValid_(static_cast<const MatrixOfExpressions&>(other).svdValid_) {}
905
906 MatrixOfExpressions(const MatrixOfExpressions& matrix)
907 : Parent_t(matrix),
908 nRows_(matrix.nRows_),
909 nCols_(matrix.nCols_),
910 elements_(matrix.elements_),
911 svd_(matrix.svd_),
912 piValid_(matrix.piValid_),
913 svdValid_(matrix.svdValid_) {}
914
915 1 void setSize(std::size_t nRows, std::size_t nCols) {
916 1 nRows_ = nRows;
917 1 nCols_ = nCols;
918 1 elements_.resize(nRows_);
919
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 for (std::size_t i = 0; i < nRows; ++i) elements_[i].resize(nCols);
920 1 }
921
922 ElementPtr_t& operator()(std::size_t i, std::size_t j) {
923 return elements_[i][j];
924 }
925
926 4 void set(std::size_t i, std::size_t j, const ElementPtr_t ptr) {
927 4 elements_[i][j] = ptr;
928 4 }
929
930 100 void impl_value(const ConfigurationIn_t arg) {
931 100 size_type r = 0, c = 0, nr = 0, nc = 0;
932
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 100 times.
300 for (std::size_t i = 0; i < nRows_; ++i) {
933 200 c = 0;
934 200 nr = elements_[i][0]->value().rows();
935
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 200 times.
600 for (std::size_t j = 0; j < nCols_; ++j) {
936
1/2
✓ Branch 5 taken 400 times.
✗ Branch 6 not taken.
400 elements_[i][j]->computeValue(arg);
937
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 400 times.
400 assert(nr == elements_[i][j]->value().rows());
938 400 nc = elements_[i][j]->value().cols();
939
1/2
✓ Branch 6 taken 400 times.
✗ Branch 7 not taken.
400 this->value_.block(r, c, nr, nc) = elements_[i][j]->value();
940 400 c += nc;
941 }
942 200 r += nr;
943 }
944 100 }
945 100 void impl_jacobian(const ConfigurationIn_t arg) {
946 100 size_type r = 0, c = 0, nr = 0, nc = 0;
947
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 100 times.
300 for (std::size_t i = 0; i < nRows_; ++i) {
948 200 c = 0;
949 200 nr = elements_[i][0]->jacobian().rows();
950
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 200 times.
600 for (std::size_t j = 0; j < nCols_; ++j) {
951
1/2
✓ Branch 5 taken 400 times.
✗ Branch 6 not taken.
400 elements_[i][j]->computeJacobian(arg);
952
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 400 times.
400 assert(nr == elements_[i][j]->jacobian().rows());
953 400 nc = elements_[i][j]->jacobian().cols();
954
1/2
✓ Branch 6 taken 400 times.
✗ Branch 7 not taken.
400 this->jacobian_.block(r, c, nr, nc) = elements_[i][j]->jacobian();
955 400 c += nc;
956 }
957 200 r += nr;
958 }
959 100 }
960
961 inline const PseudoInv_t& pinv() const { return pi_; }
962 inline const PseudoInvJacobian_t& pinvJacobian() const { return pij_; }
963 void computeSVD(const ConfigurationIn_t arg) {
964 if (svdValid_) return;
965 this->computeValue(arg);
966 svd_.compute(this->value_);
967 HPP_DEBUG_SVDCHECK(svd_);
968 svdValid_ = true;
969 }
970 void computePseudoInverse(const ConfigurationIn_t arg) {
971 if (piValid_) return;
972 this->computeValue(arg);
973 this->computeSVD(arg);
974 pi_.resize(this->value_.cols(), this->value_.rows());
975 pseudoInverse<SVD_t>(svd_, pi_);
976 piValid_ = true;
977 }
978 void computePseudoInverseJacobian(
979 const ConfigurationIn_t arg,
980 const Eigen::Ref<const Eigen::Matrix<value_type, Eigen::Dynamic, 1> >&
981 rhs) {
982 this->computeJacobian(arg);
983 computePseudoInverse(arg);
984 const std::size_t nbDof = elements_[0][0]->jacobian().cols();
985 const std::size_t inSize = this->value_.cols();
986 const vector_t piTrhs = svd_.solve(rhs);
987 assert(pi_.rows() == (size_type)inSize);
988
989 Jacobian_t cache(this->jacobian_.rows(), nbDof);
990 jacobianTimes(arg, piTrhs, cache);
991 pij_.noalias() = -pi_ * cache;
992 cache.resize(inSize, nbDof);
993
994 pkInv_.resize(pi_.cols(), pi_.cols());
995 projectorOnKernelOfInv<SVD_t>(svd_, pkInv_, true);
996 jacobianTransposeTimes(arg, pkInv_ * rhs, cache);
997 pij_.noalias() += (pi_ * pi_.transpose()) * cache;
998
999 jacobianTransposeTimes(arg, pi_.transpose() * piTrhs, cache);
1000 pk_.resize(inSize, inSize);
1001 projectorOnKernel<SVD_t>(svd_, pk_, true);
1002 pij_.noalias() += pk_ * cache;
1003 }
1004
1005 10000 void jacobianTimes(
1006 const ConfigurationIn_t arg,
1007 const Eigen::Ref<const Eigen::Matrix<value_type, Eigen::Dynamic, 1> >&
1008 rhs,
1009 Eigen::Ref<Jacobian_t> cache) const {
1010 10000 size_type r = 0, c = 0, nr = 0, nc = 0;
1011 10000 cache.setZero();
1012
2/2
✓ Branch 0 taken 20000 times.
✓ Branch 1 taken 10000 times.
30000 for (std::size_t i = 0; i < nRows_; ++i) {
1013 20000 c = 0;
1014 20000 nr = elements_[i][0]->jacobian().rows();
1015
2/2
✓ Branch 0 taken 40000 times.
✓ Branch 1 taken 20000 times.
60000 for (std::size_t j = 0; j < nCols_; ++j) {
1016
1/2
✓ Branch 5 taken 40000 times.
✗ Branch 6 not taken.
40000 elements_[i][j]->computeJacobian(arg);
1017
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 40000 times.
40000 assert(nr == elements_[i][j]->jacobian().rows());
1018 40000 nc = elements_[i][j]->jacobian().cols();
1019
4/8
✓ Branch 1 taken 40000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40000 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 40000 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 40000 times.
✗ Branch 11 not taken.
40000 cache.middleRows(r, nr).noalias() +=
1020
1/2
✓ Branch 2 taken 40000 times.
✗ Branch 3 not taken.
40000 this->jacobian_.block(r, c, nr, nc) * rhs[j];
1021 40000 c += nc;
1022 }
1023 20000 r += nr;
1024 }
1025 10000 }
1026
1027 void jacobianTransposeTimes(
1028 const ConfigurationIn_t arg,
1029 const Eigen::Ref<const Eigen::Matrix<value_type, Eigen::Dynamic, 1> >&
1030 rhs,
1031 Eigen::Ref<Jacobian_t> cache) const {
1032 size_type r = 0, c = 0, nr = 0, nc = 0;
1033 cache.setZero();
1034 for (std::size_t i = 0; i < nRows_; ++i) {
1035 c = 0;
1036 nr = elements_[i][0]->jacobian().rows();
1037 for (std::size_t j = 0; j < nCols_; ++j) {
1038 elements_[i][j]->computeJacobian(arg);
1039 assert(nr == elements_[i][j]->jacobian().rows());
1040 nc = elements_[i][j]->jacobian().cols();
1041 cache.row(j) += rhs.segment(r, nr).transpose() *
1042 this->jacobian_.block(r, c, nr, nc);
1043 c += nc;
1044 }
1045 r += nr;
1046 }
1047 }
1048
1049 Eigen::JacobiSVD<Value_t>& svd() { return svd_; }
1050
1051 100 void invalidate() {
1052 100 Parent_t::invalidate();
1053
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 100 times.
300 for (std::size_t i = 0; i < nRows_; ++i)
1054
2/2
✓ Branch 4 taken 400 times.
✓ Branch 5 taken 200 times.
600 for (std::size_t j = 0; j < nCols_; ++j) elements_[i][j]->invalidate();
1055 100 piValid_ = false;
1056 100 svdValid_ = false;
1057 100 }
1058
1059 std::size_t nRows_, nCols_;
1060 std::vector<std::vector<ElementPtr_t> > elements_;
1061
1062 private:
1063 SVD_t svd_;
1064 matrix_t pkInv_, pk_;
1065 PseudoInv_t pi_;
1066 PseudoInvJacobian_t pij_;
1067 bool piValid_, svdValid_;
1068
1069 public:
1070 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
1071 };
1072
1073 /// \}
1074 } // namespace constraints
1075 } // namespace hpp
1076
1077 #endif // HPP_CONSTRAINTS_SYMBOLIC_CALCULUS_HH
1078