Directory: | ./ |
---|---|
File: | include/crocoddyl/multibody/actions/contact-invdyn.hpp |
Date: | 2025-01-30 11:01:55 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 107 | 128 | 83.6% |
Branches: | 66 | 136 | 48.5% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | ||
2 | // BSD 3-Clause License | ||
3 | // | ||
4 | // Copyright (C) 2021-2024, Heriot-Watt University, University of Edinburgh | ||
5 | // Copyright note valid unless otherwise stated in individual files. | ||
6 | // All rights reserved. | ||
7 | /////////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | #ifndef CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_ | ||
10 | #define CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_ | ||
11 | |||
12 | #include "crocoddyl/core/actuation-base.hpp" | ||
13 | #include "crocoddyl/core/constraints/constraint-manager.hpp" | ||
14 | #include "crocoddyl/core/costs/cost-sum.hpp" | ||
15 | #include "crocoddyl/core/diff-action-base.hpp" | ||
16 | #include "crocoddyl/multibody/contacts/multiple-contacts.hpp" | ||
17 | #include "crocoddyl/multibody/data/contacts.hpp" | ||
18 | #include "crocoddyl/multibody/fwd.hpp" | ||
19 | #include "crocoddyl/multibody/states/multibody.hpp" | ||
20 | |||
21 | namespace crocoddyl { | ||
22 | |||
23 | /** | ||
24 | * @brief Differential action model for contact inverse dynamics in multibody | ||
25 | * systems. | ||
26 | * | ||
27 | * This class implements forward kinematic with holonomic contact constraints | ||
28 | * (defined at the acceleration level) and inverse-dynamics computation using | ||
29 | * the Recursive Newton Euler Algorithm (RNEA). The stack of cost and constraint | ||
30 | * functions are implemented in `CostModelSumTpl` and | ||
31 | * `ConstraintModelManagerTpl`, respectively. The acceleration and contact | ||
32 | * forces are decision variables defined as the control inputs, and the | ||
33 | * under-actuation and contact constraint are under the name `tau` and its frame | ||
34 | * name, thus the user is not allowed to use it. | ||
35 | * | ||
36 | * Additionally, it is important to note that `calcDiff()` computes the | ||
37 | * derivatives using the latest stored values by `calc()`. Thus, we need to | ||
38 | * first run `calc()`. | ||
39 | * | ||
40 | * \sa `DifferentialActionModelAbstractTpl`, `calc()`, `calcDiff()`, | ||
41 | * `createData()` | ||
42 | */ | ||
43 | template <typename _Scalar> | ||
44 | class DifferentialActionModelContactInvDynamicsTpl | ||
45 | : public DifferentialActionModelAbstractTpl<_Scalar> { | ||
46 | public: | ||
47 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
48 | |||
49 | typedef _Scalar Scalar; | ||
50 | typedef DifferentialActionModelAbstractTpl<Scalar> Base; | ||
51 | typedef DifferentialActionDataContactInvDynamicsTpl<Scalar> Data; | ||
52 | typedef StateMultibodyTpl<Scalar> StateMultibody; | ||
53 | typedef ActuationModelAbstractTpl<Scalar> ActuationModelAbstract; | ||
54 | typedef CostModelSumTpl<Scalar> CostModelSum; | ||
55 | typedef ConstraintModelManagerTpl<Scalar> ConstraintModelManager; | ||
56 | typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple; | ||
57 | typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract; | ||
58 | typedef DifferentialActionDataAbstractTpl<Scalar> | ||
59 | DifferentialActionDataAbstract; | ||
60 | typedef ContactItemTpl<Scalar> ContactItem; | ||
61 | typedef MathBaseTpl<Scalar> MathBase; | ||
62 | typedef typename MathBase::VectorXs VectorXs; | ||
63 | typedef typename MathBase::MatrixXs MatrixXs; | ||
64 | |||
65 | /** | ||
66 | * @brief Initialize the contact inverse-dynamics action model | ||
67 | * | ||
68 | * It describes the kinematic evolution of the multibody system with contacts, | ||
69 | * and computes the needed torques using inverse-dynamics. | ||
70 | * | ||
71 | * @param[in] state State of the multibody system | ||
72 | * @param[in] actuation Actuation model | ||
73 | * @param[in] contacts Multiple contacts | ||
74 | * @param[in] costs Cost model | ||
75 | */ | ||
76 | DifferentialActionModelContactInvDynamicsTpl( | ||
77 | std::shared_ptr<StateMultibody> state, | ||
78 | std::shared_ptr<ActuationModelAbstract> actuation, | ||
79 | std::shared_ptr<ContactModelMultiple> contacts, | ||
80 | std::shared_ptr<CostModelSum> costs); | ||
81 | |||
82 | /** | ||
83 | * @brief Initialize the contact inverse-dynamics action model | ||
84 | * | ||
85 | * @param[in] state State of the multibody system | ||
86 | * @param[in] actuation Actuation model | ||
87 | * @param[in] contacts Multiple contacts | ||
88 | * @param[in] costs Cost model | ||
89 | * @param[in] constraints Constraints model | ||
90 | */ | ||
91 | DifferentialActionModelContactInvDynamicsTpl( | ||
92 | std::shared_ptr<StateMultibody> state, | ||
93 | std::shared_ptr<ActuationModelAbstract> actuation, | ||
94 | std::shared_ptr<ContactModelMultiple> contacts, | ||
95 | std::shared_ptr<CostModelSum> costs, | ||
96 | std::shared_ptr<ConstraintModelManager> constraints); | ||
97 | virtual ~DifferentialActionModelContactInvDynamicsTpl(); | ||
98 | |||
99 | /** | ||
100 | * @brief Compute the system acceleration, cost value and constraint residuals | ||
101 | * | ||
102 | * It extracts the acceleration value from control vector and also computes | ||
103 | * the cost and constraints. | ||
104 | * | ||
105 | * @param[in] data Contact inverse-dynamics data | ||
106 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
107 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$ | ||
108 | */ | ||
109 | virtual void calc(const std::shared_ptr<DifferentialActionDataAbstract>& data, | ||
110 | const Eigen::Ref<const VectorXs>& x, | ||
111 | const Eigen::Ref<const VectorXs>& u); | ||
112 | |||
113 | /** | ||
114 | * @brief @copydoc Base::calc(const | ||
115 | * std::shared_ptr<DifferentialActionDataAbstract>& data, const | ||
116 | * Eigen::Ref<const VectorXs>& x) | ||
117 | */ | ||
118 | virtual void calc(const std::shared_ptr<DifferentialActionDataAbstract>& data, | ||
119 | const Eigen::Ref<const VectorXs>& x); | ||
120 | |||
121 | /** | ||
122 | * @brief Compute the derivatives of the dynamics, cost and constraint | ||
123 | * functions | ||
124 | * | ||
125 | * It computes the partial derivatives of the dynamical system and the cost | ||
126 | * and contraint functions. It assumes that `calc()` has been run first. This | ||
127 | * function builds a quadratic approximation of the time-continuous action | ||
128 | * model (i.e., dynamical system, cost and constraint functions). | ||
129 | * | ||
130 | * @param[in] data Contact inverse-dynamics data | ||
131 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
132 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$ | ||
133 | */ | ||
134 | virtual void calcDiff( | ||
135 | const std::shared_ptr<DifferentialActionDataAbstract>& data, | ||
136 | const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u); | ||
137 | |||
138 | /** | ||
139 | * @brief @copydoc Base::calcDiff(const | ||
140 | * std::shared_ptr<DifferentialActionDataAbstract>& data, const | ||
141 | * Eigen::Ref<const VectorXs>& x) | ||
142 | */ | ||
143 | virtual void calcDiff( | ||
144 | const std::shared_ptr<DifferentialActionDataAbstract>& data, | ||
145 | const Eigen::Ref<const VectorXs>& x); | ||
146 | |||
147 | /** | ||
148 | * @brief Create the contact inverse-dynamics data | ||
149 | * | ||
150 | * @return contact inverse-dynamics data | ||
151 | */ | ||
152 | virtual std::shared_ptr<DifferentialActionDataAbstract> createData(); | ||
153 | |||
154 | /** | ||
155 | * @brief Checks that a specific data belongs to the contact inverse-dynamics | ||
156 | * model | ||
157 | */ | ||
158 | virtual bool checkData( | ||
159 | const std::shared_ptr<DifferentialActionDataAbstract>& data); | ||
160 | |||
161 | /** | ||
162 | * @brief Computes the quasic static commands | ||
163 | * | ||
164 | * The quasic static commands are the ones produced for a reference posture as | ||
165 | * an equilibrium point with zero acceleration, i.e., for | ||
166 | * \f$\mathbf{f^q_x}\delta\mathbf{q}+\mathbf{f_u}\delta\mathbf{u}=\mathbf{0}\f$ | ||
167 | * | ||
168 | * @param[in] data Contact inverse-dynamics data | ||
169 | * @param[out] u Quasic-static commands | ||
170 | * @param[in] x State point (velocity has to be zero) | ||
171 | * @param[in] maxiter Maximum allowed number of iterations (default 100) | ||
172 | * @param[in] tol Tolerance (default 1e-9) | ||
173 | */ | ||
174 | virtual void quasiStatic( | ||
175 | const std::shared_ptr<DifferentialActionDataAbstract>& data, | ||
176 | Eigen::Ref<VectorXs> u, const Eigen::Ref<const VectorXs>& x, | ||
177 | const std::size_t maxiter = 100, const Scalar tol = Scalar(1e-9)); | ||
178 | |||
179 | /** | ||
180 | * @brief Return the number of inequality constraints | ||
181 | */ | ||
182 | virtual std::size_t get_ng() const; | ||
183 | |||
184 | /** | ||
185 | * @brief Return the number of equality constraints | ||
186 | */ | ||
187 | virtual std::size_t get_nh() const; | ||
188 | |||
189 | /** | ||
190 | * @brief Return the number of equality terminal constraints | ||
191 | */ | ||
192 | virtual std::size_t get_ng_T() const; | ||
193 | |||
194 | /** | ||
195 | * @brief Return the number of equality terminal constraints | ||
196 | */ | ||
197 | virtual std::size_t get_nh_T() const; | ||
198 | |||
199 | /** | ||
200 | * @brief Return the lower bound of the inequality constraints | ||
201 | */ | ||
202 | virtual const VectorXs& get_g_lb() const; | ||
203 | |||
204 | /** | ||
205 | * @brief Return the upper bound of the inequality constraints | ||
206 | */ | ||
207 | virtual const VectorXs& get_g_ub() const; | ||
208 | |||
209 | /** | ||
210 | * @brief Return the actuation model | ||
211 | */ | ||
212 | const std::shared_ptr<ActuationModelAbstract>& get_actuation() const; | ||
213 | |||
214 | /** | ||
215 | * @brief Return the contact model | ||
216 | */ | ||
217 | const std::shared_ptr<ContactModelMultiple>& get_contacts() const; | ||
218 | |||
219 | /** | ||
220 | * @brief Return the cost model | ||
221 | */ | ||
222 | const std::shared_ptr<CostModelSum>& get_costs() const; | ||
223 | |||
224 | /** | ||
225 | * @brief Return the constraint model manager | ||
226 | */ | ||
227 | const std::shared_ptr<ConstraintModelManager>& get_constraints() const; | ||
228 | |||
229 | /** | ||
230 | * @brief Return the Pinocchio model | ||
231 | */ | ||
232 | pinocchio::ModelTpl<Scalar>& get_pinocchio() const; | ||
233 | |||
234 | /** | ||
235 | * @brief Print relevant information of the contact inverse-dynamics model | ||
236 | * @param[out] os Output stream object | ||
237 | */ | ||
238 | virtual void print(std::ostream& os) const; | ||
239 | |||
240 | protected: | ||
241 | using Base::g_lb_; //!< Lower bound of the inequality constraints | ||
242 | using Base::g_ub_; //!< Upper bound of the inequality constraints | ||
243 | using Base::ng_; //!< Number of inequality constraints | ||
244 | using Base::nh_; //!< Number of equality constraints | ||
245 | using Base::nu_; //!< Control dimension | ||
246 | using Base::state_; //!< Model of the state | ||
247 | |||
248 | private: | ||
249 | void init(const std::shared_ptr<StateMultibody>& state); | ||
250 | std::shared_ptr<ActuationModelAbstract> actuation_; //!< Actuation model | ||
251 | std::shared_ptr<ContactModelMultiple> contacts_; //!< Contact model | ||
252 | std::shared_ptr<CostModelSum> costs_; //!< Cost model | ||
253 | std::shared_ptr<ConstraintModelManager> constraints_; //!< Constraint model | ||
254 | pinocchio::ModelTpl<Scalar>& pinocchio_; //!< Pinocchio model | ||
255 | |||
256 | public: | ||
257 | /** | ||
258 | * @brief Actuation residual | ||
259 | * | ||
260 | * This residual function enforces the torques of under-actuated joints (e.g., | ||
261 | * floating-base joints) to be zero. We compute these torques and their | ||
262 | * derivatives using RNEA inside | ||
263 | * `DifferentialActionModelContactInvDynamicsTpl`. | ||
264 | * | ||
265 | * As described in `ResidualModelAbstractTpl`, the residual value and its | ||
266 | * Jacobians are calculated by `calc` and `calcDiff`, respectively. | ||
267 | * | ||
268 | * \sa `ResidualModelAbstractTpl`, `calc()`, `calcDiff()`, `createData()` | ||
269 | */ | ||
270 | class ResidualModelActuation : public ResidualModelAbstractTpl<_Scalar> { | ||
271 | public: | ||
272 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
273 | |||
274 | typedef _Scalar Scalar; | ||
275 | typedef MathBaseTpl<Scalar> MathBase; | ||
276 | typedef ResidualModelAbstractTpl<Scalar> Base; | ||
277 | typedef StateMultibodyTpl<Scalar> StateMultibody; | ||
278 | typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract; | ||
279 | typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract; | ||
280 | typedef typename MathBase::VectorXs VectorXs; | ||
281 | |||
282 | /** | ||
283 | * @brief Initialize the actuation residual model | ||
284 | * | ||
285 | * @param[in] state State of the multibody system | ||
286 | * @param[in] nu Dimension of the joint torques | ||
287 | * @param[in] nc Dimension of all the contacts | ||
288 | */ | ||
289 | 251 | ResidualModelActuation(std::shared_ptr<StateMultibody> state, | |
290 | const std::size_t nu, const std::size_t nc) | ||
291 | 502 | : Base(state, state->get_nv() - nu, state->get_nv() + nc, true, true, | |
292 | true), | ||
293 | 251 | na_(nu), | |
294 |
1/2✓ Branch 4 taken 251 times.
✗ Branch 5 not taken.
|
753 | nc_(nc) {} |
295 | 502 | virtual ~ResidualModelActuation() {} | |
296 | |||
297 | /** | ||
298 | * @brief Compute the actuation residual | ||
299 | * | ||
300 | * @param[in] data Actuation residual data | ||
301 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
302 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nv+nu}\f$ | ||
303 | */ | ||
304 | 23365 | virtual void calc(const std::shared_ptr<ResidualDataAbstract>& data, | |
305 | const Eigen::Ref<const VectorXs>&, | ||
306 | const Eigen::Ref<const VectorXs>&) { | ||
307 | typename Data::ResidualDataActuation* d = | ||
308 | 23365 | static_cast<typename Data::ResidualDataActuation*>(data.get()); | |
309 | // Update the under-actuation set and residual | ||
310 | 23365 | std::size_t nrow = 0; | |
311 | 665320 | for (std::size_t k = 0; | |
312 |
2/2✓ Branch 2 taken 641955 times.
✓ Branch 3 taken 23365 times.
|
665320 | k < static_cast<std::size_t>(d->actuation->tau_set.size()); ++k) { |
313 |
2/2✓ Branch 3 taken 127365 times.
✓ Branch 4 taken 514590 times.
|
641955 | if (!d->actuation->tau_set[k]) { |
314 | 127365 | data->r(nrow) = d->pinocchio->tau(k); | |
315 | 127365 | nrow += 1; | |
316 | } | ||
317 | } | ||
318 | 23365 | } | |
319 | |||
320 | /** | ||
321 | * @brief @copydoc Base::calc(const std::shared_ptr<ResidualDataAbstract>& | ||
322 | * data, const Eigen::Ref<const VectorXs>& x) | ||
323 | */ | ||
324 | ✗ | virtual void calc(const std::shared_ptr<ResidualDataAbstract>& data, | |
325 | const Eigen::Ref<const VectorXs>&) { | ||
326 | ✗ | data->r.setZero(); | |
327 | } | ||
328 | |||
329 | /** | ||
330 | * @brief Compute the derivatives of the actuation residual | ||
331 | * | ||
332 | * @param[in] data Actuation residual data | ||
333 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
334 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$ | ||
335 | */ | ||
336 | 3135 | virtual void calcDiff(const std::shared_ptr<ResidualDataAbstract>& data, | |
337 | const Eigen::Ref<const VectorXs>&, | ||
338 | const Eigen::Ref<const VectorXs>&) { | ||
339 | typename Data::ResidualDataActuation* d = | ||
340 | 3135 | static_cast<typename Data::ResidualDataActuation*>(data.get()); | |
341 | 3135 | std::size_t nrow = 0; | |
342 | 3135 | const std::size_t nv = state_->get_nv(); | |
343 |
1/2✓ Branch 2 taken 3135 times.
✗ Branch 3 not taken.
|
3135 | d->dtau_dx.leftCols(nv) = d->pinocchio->dtau_dq; |
344 |
1/2✓ Branch 2 taken 3135 times.
✗ Branch 3 not taken.
|
3135 | d->dtau_dx.rightCols(nv) = d->pinocchio->dtau_dv; |
345 | 3135 | d->dtau_dx -= d->actuation->dtau_dx; | |
346 |
1/2✓ Branch 2 taken 3135 times.
✗ Branch 3 not taken.
|
3135 | d->dtau_du.leftCols(nv) = d->pinocchio->M; |
347 |
3/6✓ Branch 3 taken 3135 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3135 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3135 times.
✗ Branch 10 not taken.
|
3135 | d->dtau_du.rightCols(nc_) = -d->contact->Jc.transpose(); |
348 | 77748 | for (std::size_t k = 0; | |
349 |
2/2✓ Branch 2 taken 74613 times.
✓ Branch 3 taken 3135 times.
|
77748 | k < static_cast<std::size_t>(d->actuation->tau_set.size()); ++k) { |
350 |
2/2✓ Branch 3 taken 15675 times.
✓ Branch 4 taken 58938 times.
|
74613 | if (!d->actuation->tau_set[k]) { |
351 |
2/4✓ Branch 2 taken 15675 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15675 times.
✗ Branch 6 not taken.
|
15675 | d->Rx.row(nrow) = d->dtau_dx.row(k); |
352 |
2/4✓ Branch 2 taken 15675 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15675 times.
✗ Branch 6 not taken.
|
15675 | d->Ru.row(nrow) = d->dtau_du.row(k); |
353 | 15675 | nrow += 1; | |
354 | } | ||
355 | } | ||
356 | 3135 | } | |
357 | |||
358 | /** | ||
359 | * @brief @copydoc Base::calcDiff(const | ||
360 | * std::shared_ptr<ResidualDataAbstract>& data, const Eigen::Ref<const | ||
361 | * VectorXs>& x) | ||
362 | */ | ||
363 | ✗ | virtual void calcDiff(const std::shared_ptr<ResidualDataAbstract>& data, | |
364 | const Eigen::Ref<const VectorXs>&) { | ||
365 | ✗ | data->Rx.setZero(); | |
366 | ✗ | data->Ru.setZero(); | |
367 | } | ||
368 | |||
369 | /** | ||
370 | * @brief Create the actuation residual data | ||
371 | * | ||
372 | * @return Actuation residual data | ||
373 | */ | ||
374 | 27948 | virtual std::shared_ptr<ResidualDataAbstract> createData( | |
375 | DataCollectorAbstract* const data) { | ||
376 | return std::allocate_shared<typename Data::ResidualDataActuation>( | ||
377 | ✗ | Eigen::aligned_allocator<typename Data::ResidualDataActuation>(), | |
378 |
1/2✓ Branch 2 taken 27948 times.
✗ Branch 3 not taken.
|
27948 | this, data); |
379 | } | ||
380 | |||
381 | /** | ||
382 | * @brief Print relevant information of the actuation residual model | ||
383 | * | ||
384 | * @param[out] os Output stream object | ||
385 | */ | ||
386 | ✗ | virtual void print(std::ostream& os) const { | |
387 | ✗ | os << "ResidualModelActuation {nx=" << state_->get_nx() | |
388 | ✗ | << ", ndx=" << state_->get_ndx() << ", nu=" << nu_ << ", na=" << na_ | |
389 | ✗ | << "}"; | |
390 | } | ||
391 | |||
392 | protected: | ||
393 | using Base::nu_; | ||
394 | using Base::state_; | ||
395 | |||
396 | private: | ||
397 | std::size_t na_; //!< Number of actuated joints | ||
398 | std::size_t nc_; //!< Number of contacts | ||
399 | }; | ||
400 | |||
401 | public: | ||
402 | /** | ||
403 | * @brief Contact-acceleration residual | ||
404 | * | ||
405 | * This residual function is defined as \f$\mathbf{r} = \mathbf{a_0}\f$, where | ||
406 | * \f$\mathbf{a_0}\f$ defines the desired contact acceleration, which might | ||
407 | * also include the Baumgarte stabilization gains. Furthermore, the Jacobians | ||
408 | * of the residual function are computed analytically. This is used by | ||
409 | * `ConstraintModelManagerTpl` inside parent | ||
410 | * `DifferentialActionModelContactInvDynamicsTpl` class. | ||
411 | * | ||
412 | * As described in `ResidualModelAbstractTpl`, the residual value and its | ||
413 | * Jacobians are calculated by `calc` and `calcDiff`, respectively. | ||
414 | * | ||
415 | * \sa `ResidualModelAbstractTpl`, `calc()`, `calcDiff()`, `createData()` | ||
416 | */ | ||
417 | class ResidualModelContact : public ResidualModelAbstractTpl<_Scalar> { | ||
418 | public: | ||
419 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
420 | |||
421 | typedef _Scalar Scalar; | ||
422 | typedef MathBaseTpl<Scalar> MathBase; | ||
423 | typedef ResidualModelAbstractTpl<Scalar> Base; | ||
424 | typedef StateMultibodyTpl<Scalar> StateMultibody; | ||
425 | typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract; | ||
426 | typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract; | ||
427 | typedef typename MathBase::VectorXs VectorXs; | ||
428 | typedef typename MathBase::MatrixXs MatrixXs; | ||
429 | |||
430 | /** | ||
431 | * @brief Initialize the contact-acceleration residual model | ||
432 | * | ||
433 | * @param[in] state State of the multibody system | ||
434 | * @param[in] id Contact frame id | ||
435 | * @param[in] nr Dimension of the contact-acceleration residual | ||
436 | * @param[in] nc Dimension of all contacts | ||
437 | */ | ||
438 | 700 | ResidualModelContact(std::shared_ptr<StateMultibody> state, | |
439 | const pinocchio::FrameIndex id, const std::size_t nr, | ||
440 | const std::size_t nc) | ||
441 | 700 | : Base(state, nr, state->get_nv() + nc, true, true, true), | |
442 | 700 | id_(id), | |
443 |
2/4✓ Branch 3 taken 700 times.
✗ Branch 4 not taken.
✓ Branch 11 taken 700 times.
✗ Branch 12 not taken.
|
1400 | frame_name_(state->get_pinocchio()->frames[id].name) {} |
444 | 1400 | virtual ~ResidualModelContact() {} | |
445 | |||
446 | /** | ||
447 | * @brief Compute the contact-acceleration residual | ||
448 | * | ||
449 | * @param[in] data Contact-acceleration residual data | ||
450 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
451 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nv+nu}\f$ | ||
452 | */ | ||
453 | 63366 | void calc(const std::shared_ptr<ResidualDataAbstract>& data, | |
454 | const Eigen::Ref<const VectorXs>&, | ||
455 | const Eigen::Ref<const VectorXs>&) { | ||
456 | typename Data::ResidualDataContact* d = | ||
457 | 63366 | static_cast<typename Data::ResidualDataContact*>(data.get()); | |
458 | 63366 | d->r = d->contact->a0; | |
459 | 63366 | } | |
460 | |||
461 | /** | ||
462 | * @brief @copydoc Base::calc(const std::shared_ptr<ResidualDataAbstract>& | ||
463 | * data, const Eigen::Ref<const VectorXs>& x) | ||
464 | */ | ||
465 | ✗ | virtual void calc(const std::shared_ptr<ResidualDataAbstract>& data, | |
466 | const Eigen::Ref<const VectorXs>&) { | ||
467 | ✗ | data->r.setZero(); | |
468 | } | ||
469 | |||
470 | /** | ||
471 | * @brief Compute the derivatives of the contact-acceleration residual | ||
472 | * | ||
473 | * @param[in] data Contact-acceleration residual data | ||
474 | * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$ | ||
475 | * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$ | ||
476 | */ | ||
477 | 8778 | void calcDiff(const std::shared_ptr<ResidualDataAbstract>& data, | |
478 | const Eigen::Ref<const VectorXs>&, | ||
479 | const Eigen::Ref<const VectorXs>&) { | ||
480 | typename Data::ResidualDataContact* d = | ||
481 | 8778 | static_cast<typename Data::ResidualDataContact*>(data.get()); | |
482 | 8778 | d->Rx = d->contact->da0_dx; | |
483 |
1/2✓ Branch 4 taken 8778 times.
✗ Branch 5 not taken.
|
8778 | d->Ru.leftCols(state_->get_nv()) = d->contact->Jc; |
484 | 8778 | } | |
485 | |||
486 | /** | ||
487 | * @brief @copydoc Base::calcDiff(const | ||
488 | * std::shared_ptr<ResidualDataAbstract>& data, const Eigen::Ref<const | ||
489 | * VectorXs>& x) | ||
490 | */ | ||
491 | ✗ | virtual void calcDiff(const std::shared_ptr<ResidualDataAbstract>& data, | |
492 | const Eigen::Ref<const VectorXs>&) { | ||
493 | ✗ | data->Rx.setZero(); | |
494 | ✗ | data->Ru.setZero(); | |
495 | } | ||
496 | |||
497 | /** | ||
498 | * @brief Create the contact-acceleration residual data | ||
499 | * | ||
500 | * @return contact-acceleration residual data | ||
501 | */ | ||
502 | 76196 | virtual std::shared_ptr<ResidualDataAbstract> createData( | |
503 | DataCollectorAbstract* const data) { | ||
504 | return std::allocate_shared<typename Data::ResidualDataContact>( | ||
505 | ✗ | Eigen::aligned_allocator<typename Data::ResidualDataContact>(), this, | |
506 |
1/2✓ Branch 2 taken 76196 times.
✗ Branch 3 not taken.
|
76196 | data, id_); |
507 | } | ||
508 | |||
509 | /** | ||
510 | * @brief Print relevant information of the contact-acceleration residual | ||
511 | * model | ||
512 | * | ||
513 | * @param[out] os Output stream object | ||
514 | */ | ||
515 | ✗ | virtual void print(std::ostream& os) const { | |
516 | ✗ | os << "ResidualModelContact {frame=" << frame_name_ << ", nr=" << nr_ | |
517 | ✗ | << "}"; | |
518 | } | ||
519 | |||
520 | protected: | ||
521 | using Base::nr_; | ||
522 | using Base::nu_; | ||
523 | using Base::state_; | ||
524 | |||
525 | private: | ||
526 | pinocchio::FrameIndex id_; //!< Reference frame id | ||
527 | std::string frame_name_; //!< Reference frame name | ||
528 | }; | ||
529 | }; | ||
530 | template <typename _Scalar> | ||
531 | struct DifferentialActionDataContactInvDynamicsTpl | ||
532 | : public DifferentialActionDataAbstractTpl<_Scalar> { | ||
533 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
534 | typedef _Scalar Scalar; | ||
535 | typedef MathBaseTpl<Scalar> MathBase; | ||
536 | typedef DifferentialActionDataAbstractTpl<Scalar> Base; | ||
537 | typedef JointDataAbstractTpl<Scalar> JointDataAbstract; | ||
538 | typedef DataCollectorJointActMultibodyInContactTpl<Scalar> | ||
539 | DataCollectorJointActMultibodyInContact; | ||
540 | typedef CostDataSumTpl<Scalar> CostDataSum; | ||
541 | typedef ConstraintDataManagerTpl<Scalar> ConstraintDataManager; | ||
542 | typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple; | ||
543 | typedef typename MathBase::VectorXs VectorXs; | ||
544 | typedef typename MathBase::MatrixXs MatrixXs; | ||
545 | |||
546 | template <template <typename Scalar> class Model> | ||
547 | 31430 | explicit DifferentialActionDataContactInvDynamicsTpl( | |
548 | Model<Scalar>* const model) | ||
549 | : Base(model), | ||
550 |
1/2✓ Branch 1 taken 31430 times.
✗ Branch 2 not taken.
|
31430 | pinocchio(pinocchio::DataTpl<Scalar>(model->get_pinocchio())), |
551 |
3/6✓ Branch 2 taken 31430 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 31430 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 31430 times.
✗ Branch 10 not taken.
|
94290 | multibody( |
552 |
1/2✓ Branch 3 taken 31430 times.
✗ Branch 4 not taken.
|
31430 | &pinocchio, model->get_actuation()->createData(), |
553 | std::make_shared<JointDataAbstract>( | ||
554 | 62860 | model->get_state(), model->get_actuation(), model->get_nu()), | |
555 | 31430 | model->get_contacts()->createData(&pinocchio)), | |
556 |
1/2✓ Branch 4 taken 31430 times.
✗ Branch 5 not taken.
|
31430 | tmp_xstatic(model->get_state()->get_nx()), |
557 |
1/2✓ Branch 4 taken 31430 times.
✗ Branch 5 not taken.
|
62860 | tmp_rstatic(model->get_actuation()->get_nu() + |
558 | 31430 | model->get_contacts()->get_nc()), | |
559 |
1/2✓ Branch 3 taken 31430 times.
✗ Branch 4 not taken.
|
31430 | tmp_Jstatic(model->get_state()->get_nv(), |
560 | 62860 | model->get_actuation()->get_nu() + | |
561 | 94290 | model->get_contacts()->get_nc()) { | |
562 | // Set constant values for Fu, df_dx, and df_du | ||
563 | 31430 | const std::size_t nv = model->get_state()->get_nv(); | |
564 | 31430 | const std::size_t nc = model->get_contacts()->get_nc_total(); | |
565 |
3/6✓ Branch 1 taken 31430 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31430 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 31430 times.
✗ Branch 8 not taken.
|
31430 | Fu.leftCols(nv).diagonal().setOnes(); |
566 |
3/6✓ Branch 2 taken 31430 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 31430 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 31430 times.
✗ Branch 9 not taken.
|
31430 | multibody.joint->da_du.leftCols(nv).diagonal().setOnes(); |
567 |
2/4✓ Branch 4 taken 31430 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 31430 times.
✗ Branch 8 not taken.
|
31430 | MatrixXs df_dx = MatrixXs::Zero(nc, model->get_state()->get_ndx()); |
568 |
2/4✓ Branch 2 taken 31430 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 31430 times.
✗ Branch 6 not taken.
|
31430 | MatrixXs df_du = MatrixXs::Zero(nc, model->get_nu()); |
569 | 31430 | std::size_t fid = 0; | |
570 | 31430 | for (typename ContactModelMultiple::ContactModelContainer::const_iterator | |
571 | 31430 | it = model->get_contacts()->get_contacts().begin(); | |
572 |
2/2✓ Branch 5 taken 76196 times.
✓ Branch 6 taken 31430 times.
|
107626 | it != model->get_contacts()->get_contacts().end(); ++it) { |
573 | 76196 | const std::size_t nc = it->second->contact->get_nc(); | |
574 |
3/6✓ Branch 1 taken 76196 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76196 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 76196 times.
✗ Branch 8 not taken.
|
76196 | df_du.block(fid, nv + fid, nc, nc).diagonal().setOnes(); |
575 | 76196 | fid += nc; | |
576 | } | ||
577 |
1/2✓ Branch 3 taken 31430 times.
✗ Branch 4 not taken.
|
31430 | model->get_contacts()->updateForceDiff(multibody.contacts, df_dx, df_du); |
578 |
1/2✓ Branch 3 taken 31430 times.
✗ Branch 4 not taken.
|
31430 | costs = model->get_costs()->createData(&multibody); |
579 |
1/2✓ Branch 3 taken 31430 times.
✗ Branch 4 not taken.
|
31430 | constraints = model->get_constraints()->createData(&multibody); |
580 |
1/2✓ Branch 2 taken 31430 times.
✗ Branch 3 not taken.
|
31430 | costs->shareMemory(this); |
581 |
1/2✓ Branch 2 taken 31430 times.
✗ Branch 3 not taken.
|
31430 | constraints->shareMemory(this); |
582 | |||
583 |
1/2✓ Branch 1 taken 31430 times.
✗ Branch 2 not taken.
|
31430 | tmp_xstatic.setZero(); |
584 |
1/2✓ Branch 1 taken 31430 times.
✗ Branch 2 not taken.
|
31430 | tmp_rstatic.setZero(); |
585 |
1/2✓ Branch 1 taken 31430 times.
✗ Branch 2 not taken.
|
31430 | tmp_Jstatic.setZero(); |
586 | 31430 | } | |
587 | |||
588 | pinocchio::DataTpl<Scalar> pinocchio; //!< Pinocchio data | ||
589 | DataCollectorJointActMultibodyInContact multibody; //!< Multibody data | ||
590 | std::shared_ptr<CostDataSum> costs; //!< Costs data | ||
591 | std::shared_ptr<ConstraintDataManager> constraints; //!< Constraints data | ||
592 | VectorXs | ||
593 | tmp_xstatic; //!< State point used for computing the quasi-static input | ||
594 | VectorXs | ||
595 | tmp_rstatic; //!< Factorization used for computing the quasi-static input | ||
596 | MatrixXs tmp_Jstatic; //!< Jacobian used for computing the quasi-static input | ||
597 | |||
598 | using Base::cost; | ||
599 | using Base::Fu; | ||
600 | using Base::Fx; | ||
601 | using Base::Lu; | ||
602 | using Base::Luu; | ||
603 | using Base::Lx; | ||
604 | using Base::Lxu; | ||
605 | using Base::Lxx; | ||
606 | using Base::r; | ||
607 | using Base::xout; | ||
608 | |||
609 | struct ResidualDataActuation : public ResidualDataAbstractTpl<_Scalar> { | ||
610 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
611 | |||
612 | typedef _Scalar Scalar; | ||
613 | typedef MathBaseTpl<Scalar> MathBase; | ||
614 | typedef ResidualDataAbstractTpl<Scalar> Base; | ||
615 | typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract; | ||
616 | typedef DataCollectorActMultibodyInContactTpl<Scalar> | ||
617 | DataCollectorActMultibodyInContact; | ||
618 | typedef ActuationDataAbstractTpl<Scalar> ActuationDataAbstract; | ||
619 | typedef ContactDataMultipleTpl<Scalar> ContactDataMultiple; | ||
620 | typedef typename MathBase::MatrixXs MatrixXs; | ||
621 | |||
622 | template <template <typename Scalar> class Model> | ||
623 | 27948 | ResidualDataActuation(Model<Scalar>* const model, | |
624 | DataCollectorAbstract* const data) | ||
625 | : Base(model, data), | ||
626 |
1/2✓ Branch 7 taken 27948 times.
✗ Branch 8 not taken.
|
27948 | dtau_dx(model->get_state()->get_nv(), model->get_state()->get_ndx()), |
627 |
1/2✓ Branch 8 taken 27948 times.
✗ Branch 9 not taken.
|
55896 | dtau_du(model->get_state()->get_nv(), model->get_nu()) { |
628 | // Check that proper shared data has been passed | ||
629 | 27948 | DataCollectorActMultibodyInContact* d = | |
630 |
1/2✓ Branch 0 taken 27948 times.
✗ Branch 1 not taken.
|
27948 | dynamic_cast<DataCollectorActMultibodyInContact*>(shared); |
631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27948 times.
|
27948 | if (d == NULL) { |
632 | ✗ | throw_pretty( | |
633 | "Invalid argument: the shared data should be derived from " | ||
634 | "DataCollectorActMultibodyInContact"); | ||
635 | } | ||
636 | // Avoids data casting at runtime | ||
637 | 27948 | pinocchio = d->pinocchio; | |
638 | 27948 | actuation = d->actuation; | |
639 | 27948 | contact = d->contacts; | |
640 |
1/2✓ Branch 1 taken 27948 times.
✗ Branch 2 not taken.
|
27948 | dtau_dx.setZero(); |
641 |
1/2✓ Branch 1 taken 27948 times.
✗ Branch 2 not taken.
|
27948 | dtau_du.setZero(); |
642 | 27948 | } | |
643 | |||
644 | pinocchio::DataTpl<Scalar>* pinocchio; //!< Pinocchio data | ||
645 | std::shared_ptr<ActuationDataAbstract> actuation; //!< Actuation data | ||
646 | std::shared_ptr<ContactDataMultiple> contact; //!< Contact data | ||
647 | MatrixXs dtau_dx; | ||
648 | MatrixXs dtau_du; | ||
649 | using Base::r; | ||
650 | using Base::Ru; | ||
651 | using Base::Rx; | ||
652 | using Base::shared; | ||
653 | }; | ||
654 | |||
655 | struct ResidualDataContact : public ResidualDataAbstractTpl<_Scalar> { | ||
656 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
657 | |||
658 | typedef _Scalar Scalar; | ||
659 | typedef MathBaseTpl<Scalar> MathBase; | ||
660 | typedef ResidualDataAbstractTpl<Scalar> Base; | ||
661 | typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract; | ||
662 | typedef DataCollectorMultibodyInContactTpl<Scalar> | ||
663 | DataCollectorMultibodyInContact; | ||
664 | typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple; | ||
665 | |||
666 | template <template <typename Scalar> class Model> | ||
667 | 76196 | ResidualDataContact(Model<Scalar>* const model, | |
668 | DataCollectorAbstract* const data, const std::size_t id) | ||
669 | 76196 | : Base(model, data) { | |
670 | 76196 | DataCollectorMultibodyInContact* d = | |
671 |
1/2✓ Branch 0 taken 76196 times.
✗ Branch 1 not taken.
|
76196 | dynamic_cast<DataCollectorMultibodyInContact*>(shared); |
672 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76196 times.
|
76196 | if (d == NULL) { |
673 | ✗ | throw_pretty( | |
674 | "Invalid argument: the shared data should be derived from " | ||
675 | "DataCollectorMultibodyInContact"); | ||
676 | } | ||
677 | 76196 | typename ContactModelMultiple::ContactDataContainer::iterator it, end; | |
678 | 152392 | for (it = d->contacts->contacts.begin(), | |
679 | 76196 | end = d->contacts->contacts.end(); | |
680 |
1/2✓ Branch 2 taken 151420 times.
✗ Branch 3 not taken.
|
151420 | it != end; ++it) { |
681 |
2/2✓ Branch 2 taken 76196 times.
✓ Branch 3 taken 75224 times.
|
151420 | if (id == it->second->frame) { // TODO(cmastalli): use model->get_id() |
682 | // and avoid to pass id in constructor | ||
683 | 76196 | contact = it->second.get(); | |
684 | 76196 | break; | |
685 | } | ||
686 | } | ||
687 | 76196 | } | |
688 | |||
689 | ContactDataAbstractTpl<Scalar>* contact; //!< Contact force data | ||
690 | using Base::r; | ||
691 | using Base::Ru; | ||
692 | using Base::Rx; | ||
693 | using Base::shared; | ||
694 | }; | ||
695 | }; | ||
696 | } // namespace crocoddyl | ||
697 | |||
698 | /* --- Details -------------------------------------------------------------- */ | ||
699 | /* --- Details -------------------------------------------------------------- */ | ||
700 | /* --- Details -------------------------------------------------------------- */ | ||
701 | #include <crocoddyl/multibody/actions/contact-invdyn.hxx> | ||
702 | |||
703 | #endif // CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_ | ||
704 |