GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/multibody/contacts/multiple-contacts.hpp
Date: 2025-01-16 08:47:40
Exec Total Coverage
Lines: 22 25 88.0%
Branches: 17 32 53.1%

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