Directory: | ./ |
---|---|
File: | unittest/contact-inverse-dynamics.cpp |
Date: | 2025-02-12 21:03:38 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 37 | 66 | 56.1% |
Branches: | 77 | 242 | 31.8% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2019-2023 INRIA | ||
3 | // | ||
4 | |||
5 | #include "pinocchio/algorithm/aba.hpp" | ||
6 | #include "pinocchio/algorithm/rnea.hpp" | ||
7 | #include "pinocchio/algorithm/frames.hpp" | ||
8 | #include "pinocchio/algorithm/jacobian.hpp" | ||
9 | #include "pinocchio/algorithm/centroidal.hpp" | ||
10 | #include "pinocchio/algorithm/kinematics.hpp" | ||
11 | #include "pinocchio/algorithm/contact-info.hpp" | ||
12 | #include "pinocchio/algorithm/compute-all-terms.hpp" | ||
13 | #include "pinocchio/algorithm/constrained-dynamics.hpp" | ||
14 | #include "pinocchio/algorithm/contact-dynamics.hpp" | ||
15 | #include "pinocchio/algorithm/contact-inverse-dynamics.hpp" | ||
16 | #include "pinocchio/algorithm/joint-configuration.hpp" | ||
17 | #include "pinocchio/multibody/sample-models.hpp" | ||
18 | #include "pinocchio/utils/timer.hpp" | ||
19 | #include "pinocchio/spatial/classic-acceleration.hpp" | ||
20 | |||
21 | #include <iostream> | ||
22 | |||
23 | #include <boost/test/unit_test.hpp> | ||
24 | #include <boost/utility/binary.hpp> | ||
25 | #include <optional> | ||
26 | |||
27 | #define KP 10 | ||
28 | #define KD 10 | ||
29 | |||
30 | BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE) | ||
31 | |||
32 | /// \brief Computes motions in the world frame | ||
33 | ✗ | pinocchio::Motion computeAcceleration( | |
34 | const pinocchio::Model & model, | ||
35 | pinocchio::Data & data, | ||
36 | const pinocchio::JointIndex & joint_id, | ||
37 | pinocchio::ReferenceFrame reference_frame, | ||
38 | const pinocchio::ContactType type, | ||
39 | const pinocchio::SE3 & placement = pinocchio::SE3::Identity()) | ||
40 | { | ||
41 | PINOCCHIO_UNUSED_VARIABLE(model); | ||
42 | using namespace pinocchio; | ||
43 | ✗ | Motion res(Motion::Zero()); | |
44 | |||
45 | ✗ | const Data::SE3 & oMi = data.oMi[joint_id]; | |
46 | ✗ | const Data::SE3 & iMc = placement; | |
47 | ✗ | const Data::SE3 oMc = oMi * iMc; | |
48 | |||
49 | ✗ | const Motion ov = oMi.act(data.v[joint_id]); | |
50 | ✗ | const Motion oa = oMi.act(data.a[joint_id]); | |
51 | |||
52 | ✗ | switch (reference_frame) | |
53 | { | ||
54 | ✗ | case WORLD: | |
55 | ✗ | if (type == CONTACT_3D) | |
56 | ✗ | classicAcceleration(ov, oa, res.linear()); | |
57 | else | ||
58 | ✗ | res.linear() = oa.linear(); | |
59 | ✗ | res.angular() = oa.angular(); | |
60 | ✗ | break; | |
61 | ✗ | case LOCAL_WORLD_ALIGNED: | |
62 | ✗ | if (type == CONTACT_3D) | |
63 | ✗ | res.linear() = oMc.rotation() * classicAcceleration(data.v[joint_id], data.a[joint_id], iMc); | |
64 | else | ||
65 | ✗ | res.linear() = oMc.rotation() * (iMc.actInv(data.a[joint_id])).linear(); | |
66 | ✗ | res.angular() = oMi.rotation() * data.a[joint_id].angular(); | |
67 | ✗ | break; | |
68 | ✗ | case LOCAL: | |
69 | ✗ | if (type == CONTACT_3D) | |
70 | ✗ | classicAcceleration(data.v[joint_id], data.a[joint_id], iMc, res.linear()); | |
71 | else | ||
72 | ✗ | res.linear() = (iMc.actInv(data.a[joint_id])).linear(); | |
73 | ✗ | res.angular() = iMc.rotation().transpose() * data.a[joint_id].angular(); | |
74 | ✗ | break; | |
75 | ✗ | default: | |
76 | ✗ | break; | |
77 | } | ||
78 | |||
79 | ✗ | return res; | |
80 | } | ||
81 | |||
82 |
33/66✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 66 taken 1 times.
✗ Branch 67 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 1 times.
✗ Branch 74 not taken.
✓ Branch 77 taken 1 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 1 times.
✗ Branch 81 not taken.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
✓ Branch 86 taken 1 times.
✗ Branch 87 not taken.
✓ Branch 91 taken 1 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✓ Branch 98 taken 1 times.
✗ Branch 99 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 1 times.
✗ Branch 106 not taken.
✓ Branch 108 taken 1 times.
✗ Branch 109 not taken.
✓ Branch 111 taken 1 times.
✗ Branch 112 not taken.
✓ Branch 116 taken 1 times.
✗ Branch 117 not taken.
|
4 | BOOST_AUTO_TEST_CASE(test_contact_inverse_dynamics_3D) |
83 | { | ||
84 | using namespace Eigen; | ||
85 | using namespace pinocchio; | ||
86 | |||
87 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | pinocchio::Model model; |
88 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | pinocchio::buildModels::humanoidRandom(model, true); |
89 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | pinocchio::Data data(model), data_ref(model); |
90 | |||
91 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | model.lowerPositionLimit.head<3>().fill(-1.); |
92 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | model.upperPositionLimit.head<3>().fill(1.); |
93 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | VectorXd q = randomConfiguration(model); |
94 | |||
95 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | VectorXd v = VectorXd::Random(model.nv); |
96 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | VectorXd tau = VectorXd::Random(model.nv); |
97 | |||
98 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | const std::string RF = "rleg6_joint"; |
99 | // const Model::JointIndex RF_id = model.getJointId(RF); | ||
100 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | const std::string LF = "lleg6_joint"; |
101 | // const Model::JointIndex LF_id = model.getJointId(LF); | ||
102 | |||
103 | // Contact models and data | ||
104 | typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(RigidConstraintModel) | ||
105 | RigidConstraintModelVector; | ||
106 | typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(RigidConstraintData) RigidConstraintDataVector; | ||
107 | typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(CoulombFrictionCone) CoulombFrictionConeVector; | ||
108 | |||
109 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | RigidConstraintModelVector contact_models; |
110 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | RigidConstraintDataVector contact_datas; |
111 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | CoulombFrictionConeVector cones; |
112 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | RigidConstraintModel ci_RF(CONTACT_3D, model, model.getJointId(RF), LOCAL); |
113 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | contact_models.push_back(ci_RF); |
114 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | contact_datas.push_back(RigidConstraintData(ci_RF)); |
115 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | cones.push_back(CoulombFrictionCone(0.4)); |
116 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | RigidConstraintModel ci_LF(CONTACT_3D, model, model.getJointId(LF), LOCAL); |
117 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | contact_models.push_back(ci_LF); |
118 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | contact_datas.push_back(RigidConstraintData(ci_LF)); |
119 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | cones.push_back(CoulombFrictionCone(0.4)); |
120 | |||
121 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | RigidConstraintDataVector contact_datas_ref(contact_datas); |
122 | |||
123 | 2 | Eigen::DenseIndex constraint_dim = 0; | |
124 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
6 | for (size_t k = 0; k < contact_models.size(); ++k) |
125 | 4 | constraint_dim += contact_models[k].size(); | |
126 | |||
127 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | Eigen::MatrixXd J_ref(constraint_dim, model.nv); |
128 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | J_ref.setZero(); |
129 | |||
130 | 2 | double dt = 1e-3; | |
131 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | Eigen::VectorXd R = Eigen::VectorXd::Zero(constraint_dim); |
132 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | Eigen::VectorXd constraint_correction = Eigen::VectorXd::Zero(constraint_dim); |
133 | 2 | boost::optional<Eigen::VectorXd> lambda_guess = boost::optional<Eigen::VectorXd>(boost::none); | |
134 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | Eigen::VectorXd a = Eigen::VectorXd::Zero(model.nv); |
135 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | ProximalSettings prox_settings(1e-12, 1e-6, 1); |
136 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | initConstraintDynamics(model, data_ref, contact_models); |
137 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | contactInverseDynamics( |
138 | model, data_ref, q, v, a, dt, contact_models, contact_datas, cones, R, constraint_correction, | ||
139 | prox_settings, lambda_guess); | ||
140 | // constraintDynamics(model, data_ref, q, v, tau, contact_models, contact_datas_ref, | ||
141 | // prox_settings_cd); forwardKinematics(model, data_ref, q, v, v*0); | ||
142 | |||
143 | // Data::Matrix6x Jtmp = Data::Matrix6x::Zero(6,model.nv); | ||
144 | // getJointJacobian(model,data_ref,ci_RF.joint1_id,ci_RF.reference_frame,Jtmp); | ||
145 | // J_ref.middleRows<3>(0) = Jtmp.middleRows<3>(Motion::LINEAR); | ||
146 | // Jtmp.setZero(); getJointJacobian(model,data_ref,ci_LF.joint1_id,ci_LF.reference_frame,Jtmp); | ||
147 | // J_ref.middleRows<3>(3) = Jtmp.middleRows<3>(Motion::LINEAR); | ||
148 | |||
149 | // Eigen::VectorXd gamma(constraint_dim); | ||
150 | |||
151 | // gamma.segment<3>(0) = | ||
152 | // computeAcceleration(model,data_ref,ci_RF.joint1_id,ci_RF.reference_frame,ci_RF.type).linear(); | ||
153 | // gamma.segment<3>(3) = | ||
154 | // computeAcceleration(model,data_ref,ci_LF.joint1_id,ci_LF.reference_frame,ci_LF.type).linear(); | ||
155 | |||
156 | // BOOST_CHECK((J_ref*data_ref.ddq + gamma).isZero()); | ||
157 | |||
158 | // Data data_constrained_dyn(model); | ||
159 | |||
160 | // PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH | ||
161 | // PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_DEPRECECATED_DECLARATIONS | ||
162 | // forwardDynamics(model,data_constrained_dyn,q,v,tau,J_ref,gamma,0.); | ||
163 | // PINOCCHIO_COMPILER_DIAGNOSTIC_POP | ||
164 | |||
165 | // BOOST_CHECK((J_ref*data_constrained_dyn.ddq + gamma).isZero()); | ||
166 | |||
167 | // ProximalSettings prox_settings; | ||
168 | // prox_settings.max_iter = 10; | ||
169 | // prox_settings.mu = 1e8; | ||
170 | // contactABA(model, data, q, v, tau, contact_models, contact_datas, prox_settings); | ||
171 | |||
172 | // BOOST_CHECK((J_ref*data.ddq + gamma).isZero()); | ||
173 | |||
174 | // // Call the algorithm a second time | ||
175 | // Data data2(model); | ||
176 | // ProximalSettings prox_settings2; | ||
177 | // contactABA(model, data2, q, v, tau, contact_models, contact_datas, prox_settings2); | ||
178 | |||
179 | // BOOST_CHECK(prox_settings2.iter == 0); | ||
180 | 2 | } | |
181 | |||
182 | BOOST_AUTO_TEST_SUITE_END() | ||
183 |