GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/multibody/contacts/multiple-contacts.hpp
Date: 2025-03-26 19:23:43
Exec Total Coverage
Lines: 22 29 75.9%
Branches: 32 64 50.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, LAAS-CNRS, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifndef CROCODDYL_MULTIBODY_CONTACTS_MULTIPLE_CONTACTS_HPP_
11 #define CROCODDYL_MULTIBODY_CONTACTS_MULTIPLE_CONTACTS_HPP_
12
13 #include <map>
14 #include <set>
15 #include <string>
16 #include <utility>
17
18 #include "crocoddyl/multibody/contact-base.hpp"
19 #include "crocoddyl/multibody/fwd.hpp"
20
21 namespace crocoddyl {
22
23 template <typename _Scalar>
24 struct ContactItemTpl {
25 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
26
27 typedef _Scalar Scalar;
28 typedef ContactModelAbstractTpl<Scalar> ContactModelAbstract;
29
30 ContactItemTpl() {}
31 1717 ContactItemTpl(const std::string& name,
32 std::shared_ptr<ContactModelAbstract> contact,
33 const bool active = true)
34 1717 : name(name), contact(contact), active(active) {}
35
36 template <typename NewScalar>
37 ContactItemTpl<NewScalar> cast() const {
38 typedef ContactItemTpl<NewScalar> ReturnType;
39 ReturnType ret(name, contact->template cast<NewScalar>(), active);
40 return ret;
41 }
42
43 /**
44 * @brief Print information on the contact item
45 */
46 friend std::ostream& operator<<(std::ostream& os,
47 const ContactItemTpl<Scalar>& model) {
48 os << "{" << *model.contact << "}";
49 return os;
50 }
51
52 std::string name;
53 std::shared_ptr<ContactModelAbstract> contact;
54 bool active;
55 };
56
57 /**
58 * @brief Define a stack of contact models
59 *
60 * The contact models can be defined with active and inactive status. The idea
61 * behind this design choice is to be able to create a mechanism that allocates
62 * the entire data needed for the computations. Then, there are designed
63 * routines that update the only active contacts.
64 */
65 template <typename _Scalar>
66 class ContactModelMultipleTpl {
67 public:
68 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
69
70 typedef _Scalar Scalar;
71 typedef MathBaseTpl<Scalar> MathBase;
72 typedef StateMultibodyTpl<Scalar> StateMultibody;
73 typedef ContactDataAbstractTpl<Scalar> ContactDataAbstract;
74 typedef ContactDataMultipleTpl<Scalar> ContactDataMultiple;
75 typedef ContactModelAbstractTpl<Scalar> ContactModelAbstract;
76
77 typedef ContactItemTpl<Scalar> ContactItem;
78
79 typedef typename MathBase::Vector2s Vector2s;
80 typedef typename MathBase::Vector3s Vector3s;
81 typedef typename MathBase::VectorXs VectorXs;
82 typedef typename MathBase::MatrixXs MatrixXs;
83
84 typedef std::map<std::string, std::shared_ptr<ContactItem> >
85 ContactModelContainer;
86 typedef std::map<std::string, std::shared_ptr<ContactDataAbstract> >
87 ContactDataContainer;
88 typedef typename pinocchio::container::aligned_vector<
89 pinocchio::ForceTpl<Scalar> >::iterator ForceIterator;
90
91 /**
92 * @brief Initialize the multi-contact model
93 *
94 * @param[in] state Multibody state
95 * @param[in] nu Dimension of control vector
96 */
97 ContactModelMultipleTpl(std::shared_ptr<StateMultibody> state,
98 const std::size_t nu);
99
100 /**
101 * @brief Initialize the multi-contact model
102 *
103 * @param[in] state Multibody state
104 */
105 ContactModelMultipleTpl(std::shared_ptr<StateMultibody> state);
106 ~ContactModelMultipleTpl();
107
108 /**
109 * @brief Add contact item
110 *
111 * Note that the memory is allocated for inactive contacts as well.
112 *
113 * @param[in] name Contact name
114 * @param[in] contact Contact model
115 * @param[in] active Contact status (active by default)
116 */
117 void addContact(const std::string& name,
118 std::shared_ptr<ContactModelAbstract> contact,
119 const bool active = true);
120
121 /**
122 * @brief Remove contact item
123 *
124 * @param[in] name Contact name
125 */
126 void removeContact(const std::string& name);
127
128 /**
129 * @brief Change the contact status
130 *
131 * @param[in] name Contact name
132 * @param[in] active Contact status (True for active)
133 */
134 void changeContactStatus(const std::string& name, const bool active);
135
136 /**
137 * @brief Compute the contact Jacobian and contact acceleration
138 *
139 * @param[in] data Multi-contact data
140 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
141 */
142 void calc(const std::shared_ptr<ContactDataMultiple>& data,
143 const Eigen::Ref<const VectorXs>& x);
144
145 /**
146 * @brief Compute the derivatives of the contact holonomic constraint
147 *
148 * @param[in] data Multi-contact data
149 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
150 */
151 void calcDiff(const std::shared_ptr<ContactDataMultiple>& data,
152 const Eigen::Ref<const VectorXs>& x);
153
154 /**
155 * @brief Update the constrained system acceleration
156 *
157 * @param[in] data Multi-contact data
158 * @param[in] dv Constrained system acceleration
159 * \f$\dot{\mathbf{v}}\in\mathbb{R}^{nv}\f$
160 */
161 void updateAcceleration(const std::shared_ptr<ContactDataMultiple>& data,
162 const VectorXs& dv) const;
163
164 /**
165 * @brief Update the spatial force defined in frame coordinate
166 *
167 * @param[in] data Multi-contact data
168 * @param[in] force Spatial force defined in frame coordinate
169 * \f${}^o\underline{\boldsymbol{\lambda}}_c\in\mathbb{R}^{nc}\f$
170 */
171 void updateForce(const std::shared_ptr<ContactDataMultiple>& data,
172 const VectorXs& force);
173
174 /**
175 * @brief Update the Jacobian of the constrained system acceleration
176 *
177 * @param[in] data Multi-contact data
178 * @param[in] ddv_dx Jacobian of the system acceleration in generalized
179 * coordinates
180 * \f$\frac{\partial\dot{\mathbf{v}}}{\partial\mathbf{x}}\in\mathbb{R}^{nv\times
181 * ndx}\f$
182 */
183 void updateAccelerationDiff(const std::shared_ptr<ContactDataMultiple>& data,
184 const MatrixXs& ddv_dx) const;
185
186 /**
187 * @brief Update the Jacobian of the spatial force defined in frame coordinate
188 *
189 * @param[in] data Multi-contact data
190 * @param[in] df_dx Jacobian of the spatial impulse defined in frame
191 * coordinate
192 * \f$\frac{\partial{}^o\underline{\boldsymbol{\lambda}}_c}{\partial\mathbf{x}}\in\mathbb{R}^{nc\times{ndx}}\f$
193 * @param[in] df_du Jacobian of the spatial impulse defined in frame
194 * coordinate
195 * \f$\frac{\partial{}^o\underline{\boldsymbol{\lambda}}_c}{\partial\mathbf{u}}\in\mathbb{R}^{nc\times{nu}}\f$
196 */
197 void updateForceDiff(const std::shared_ptr<ContactDataMultiple>& data,
198 const MatrixXs& df_dx, const MatrixXs& df_du) const;
199
200 /**
201 * @brief Update the RNEA derivatives dtau_dq by adding the skew term
202 * (necessary for contacts expressed in LOCAL_WORLD_ALIGNED / WORLD)
203 *
204 * To learn more about the computation of the contact derivatives in different
205 * frames see https://hal.science/hal-03758989/document.
206 *
207 * @param[in] data Multi-contact data
208 * @param[in] pinocchio Pinocchio data
209 */
210 void updateRneaDiff(const std::shared_ptr<ContactDataMultiple>& data,
211 pinocchio::DataTpl<Scalar>& pinocchio) const;
212
213 /**
214 * @brief Create the multi-contact data
215 *
216 * @param[in] data Pinocchio data
217 * @return the multi-contact data.
218 */
219 std::shared_ptr<ContactDataMultiple> createData(
220 pinocchio::DataTpl<Scalar>* const data);
221
222 /**
223 * @brief Cast the multi-contact model to a different scalar type.
224 *
225 * It is useful for operations requiring different precision or scalar types.
226 *
227 * @tparam NewScalar The new scalar type to cast to.
228 * @return ContactModelMultipleTpl<NewScalar> A multi-contact model with the
229 * new scalar type.
230 */
231 template <typename NewScalar>
232 ContactModelMultipleTpl<NewScalar> cast() const;
233
234 /**
235 * @brief Return the multibody state
236 */
237 const std::shared_ptr<StateMultibody>& get_state() const;
238
239 /**
240 * @brief Return the contact models
241 */
242 const ContactModelContainer& get_contacts() const;
243
244 /**
245 * @brief Return the dimension of active contacts
246 */
247 std::size_t get_nc() const;
248
249 /**
250 * @brief Return the dimension of all contacts
251 */
252 std::size_t get_nc_total() const;
253
254 /**
255 * @brief Return the dimension of control vector
256 */
257 std::size_t get_nu() const;
258
259 /**
260 * @brief Return the names of the set of active contacts
261 */
262 const std::set<std::string>& get_active_set() const;
263
264 /**
265 * @brief Return the names of the set of inactive contacts
266 */
267 const std::set<std::string>& get_inactive_set() const;
268
269 /**
270 * @brief Return the status of a given contact name
271 */
272 bool getContactStatus(const std::string& name) const;
273
274 /**
275 * @brief Return the type of contact computation
276 *
277 * True for all contacts, otherwise false for active contacts
278 */
279 bool getComputeAllContacts() const;
280
281 /**
282 * @brief Set the tyoe of contact computation: all or active contacts
283 *
284 * @param status Type of contact computation (true for all contacts and false
285 * for active contacts)
286 */
287 void setComputeAllContacts(const bool status);
288
289 /**
290 * @brief Print information on the contact models
291 */
292 template <class Scalar>
293 friend std::ostream& operator<<(std::ostream& os,
294 const ContactModelMultipleTpl<Scalar>& model);
295
296 private:
297 std::shared_ptr<StateMultibody> state_;
298 ContactModelContainer contacts_;
299 std::size_t nc_;
300 std::size_t nc_total_;
301 std::size_t nu_;
302 std::set<std::string> active_set_;
303 std::set<std::string> inactive_set_;
304 bool compute_all_contacts_;
305 };
306
307 /**
308 * @brief Define the multi-contact data
309 *
310 * \sa ContactModelMultipleTpl
311 */
312 template <typename _Scalar>
313 struct ContactDataMultipleTpl {
314 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
315
316 typedef _Scalar Scalar;
317 typedef MathBaseTpl<Scalar> MathBase;
318 typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple;
319 typedef ContactItemTpl<Scalar> ContactItem;
320 typedef typename MathBase::VectorXs VectorXs;
321 typedef typename MathBase::MatrixXs MatrixXs;
322
323 /**
324 * @brief Initialized a multi-contact data
325 *
326 * @param[in] model Multi-contact model
327 * @param[in] data Pinocchio data
328 */
329 template <template <typename Scalar> class Model>
330 71013 ContactDataMultipleTpl(Model<Scalar>* const model,
331 pinocchio::DataTpl<Scalar>* const data)
332
2/4
✓ Branch 4 taken 70999 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 70999 times.
✗ Branch 8 not taken.
71013 : Jc(model->get_nc_total(), model->get_state()->get_nv()),
333
2/4
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70999 times.
✗ Branch 5 not taken.
71013 a0(model->get_nc_total()),
334
4/8
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 70999 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 70999 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 70999 times.
✗ Branch 12 not taken.
71013 da0_dx(model->get_nc_total(), model->get_state()->get_ndx()),
335
3/6
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 70999 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 70999 times.
✗ Branch 9 not taken.
71013 dv(model->get_state()->get_nv()),
336
5/10
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 70999 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 70999 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 70999 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 70999 times.
✗ Branch 16 not taken.
71013 ddv_dx(model->get_state()->get_nv(), model->get_state()->get_ndx()),
337
4/8
✓ Branch 2 taken 70999 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 70999 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 70999 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 70999 times.
✗ Branch 14 not taken.
71013 fext(model->get_state()->get_pinocchio()->njoints,
338 71013 pinocchio::ForceTpl<Scalar>::Zero()) {
339
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 Jc.setZero();
340
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 a0.setZero();
341
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 da0_dx.setZero();
342
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 dv.setZero();
343
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 ddv_dx.setZero();
344 71013 for (typename ContactModelMultiple::ContactModelContainer::const_iterator
345
1/2
✓ Branch 1 taken 70999 times.
✗ Branch 2 not taken.
71013 it = model->get_contacts().begin();
346
3/4
✓ Branch 1 taken 231813 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 160814 times.
✓ Branch 6 taken 70999 times.
231840 it != model->get_contacts().end(); ++it) {
347 160827 const std::shared_ptr<ContactItem>& item = it->second;
348
1/2
✓ Branch 1 taken 160814 times.
✗ Branch 2 not taken.
160827 contacts.insert(
349
2/4
✓ Branch 3 taken 160814 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 160814 times.
✗ Branch 8 not taken.
160827 std::make_pair(item->name, item->contact->createData(data)));
350 }
351 71013 }
352
353 MatrixXs Jc; //!< Contact Jacobian in frame coordinate
354 //!< \f$\mathbf{J}_c\in\mathbb{R}^{nc_{total}\times{nv}}\f$
355 //!< (memory defined for active and inactive contacts)
356 VectorXs a0; //!< Desired spatial contact acceleration in frame coordinate
357 //!< \f$\underline{\mathbf{a}}_0\in\mathbb{R}^{nc_{total}}\f$
358 //!< (memory defined for active and inactive contacts)
359 MatrixXs
360 da0_dx; //!< Jacobian of the desired spatial contact acceleration in
361 //!< frame coordinate
362 //!< \f$\frac{\partial\underline{\mathbf{a}}_0}{\partial\mathbf{x}}\in\mathbb{R}^{nc_{total}\times{ndx}}\f$
363 //!< (memory defined for active and inactive contacts)
364 VectorXs dv; //!< Constrained system acceleration in generalized coordinates
365 //!< \f$\dot{\mathbf{v}}\in\mathbb{R}^{nv}\f$
366 MatrixXs
367 ddv_dx; //!< Jacobian of the system acceleration in generalized
368 //!< coordinates
369 //!< \f$\frac{\partial\dot{\mathbf{v}}}{\partial\mathbf{x}}\in\mathbb{R}^{nv\times
370 //!< ndx}\f$
371 typename ContactModelMultiple::ContactDataContainer
372 contacts; //!< Stack of contact data
373 pinocchio::container::aligned_vector<pinocchio::ForceTpl<Scalar> >
374 fext; //!< External spatial forces in body coordinates
375 };
376
377 } // namespace crocoddyl
378
379 /* --- Details -------------------------------------------------------------- */
380 /* --- Details -------------------------------------------------------------- */
381 /* --- Details -------------------------------------------------------------- */
382 #include "crocoddyl/multibody/contacts/multiple-contacts.hxx"
383
384 CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(crocoddyl::ContactItemTpl)
385 CROCODDYL_DECLARE_EXTERN_TEMPLATE_CLASS(crocoddyl::ContactModelMultipleTpl)
386 CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(crocoddyl::ContactDataMultipleTpl)
387
388 #endif // CROCODDYL_MULTIBODY_CONTACTS_MULTIPLE_CONTACTS_HPP_
389