|
1 | 1 |
|
2 | 2 | #include <boost/test/tools/old/interface.hpp> |
3 | 3 | #include <boost/test/unit_test.hpp> |
| 4 | +#include <pinocchio/algorithm/center-of-mass.hpp> |
| 5 | +#include <pinocchio/algorithm/frames.hpp> |
4 | 6 |
|
5 | 7 | #include "simple-mpc/inverse-dynamics.hpp" |
6 | 8 | #include "simple-mpc/robot-handler.hpp" |
@@ -48,10 +50,14 @@ class TestKinoID |
48 | 50 | solver.getAccelerations(ddq); |
49 | 51 |
|
50 | 52 | // Integrate |
| 53 | + step_i += 1; |
51 | 54 | t += dt; |
52 | 55 | q = pinocchio::integrate(model_handler.getModel(), q, (dq + ddq / 2. * dt) * dt); |
53 | 56 | dq += ddq * dt; |
54 | 57 |
|
| 58 | + // Update data handler |
| 59 | + data_handler.updateInternalData(q, dq, true); |
| 60 | + |
55 | 61 | // Check common to all tests |
56 | 62 | check_joint_limits(); |
57 | 63 | } |
@@ -92,6 +98,7 @@ class TestKinoID |
92 | 98 | KinodynamicsID solver; |
93 | 99 |
|
94 | 100 | double t = 0.; |
| 101 | + int step_i = 0; |
95 | 102 | Eigen::VectorXd q; |
96 | 103 | Eigen::VectorXd dq; |
97 | 104 | Eigen::VectorXd ddq; |
@@ -132,59 +139,92 @@ BOOST_AUTO_TEST_CASE(KinodynamicsID_postureTask) |
132 | 139 | } |
133 | 140 | } |
134 | 141 |
|
135 | | -BOOST_AUTO_TEST_CASE(KinodynamicsID_contact) |
| 142 | +void test_contact(TestKinoID test) |
136 | 143 | { |
137 | | - TestKinoID test( |
138 | | - getSoloHandler(), KinodynamicsID::Settings() |
139 | | - .set_kp_posture(10.0) |
140 | | - .set_kp_contact(10.0) |
141 | | - .set_w_base(10.) |
142 | | - .set_w_contact_motion(1.0) |
143 | | - .set_w_contact_force(1.0)); |
144 | | - |
145 | 144 | // Easy access |
146 | 145 | const RobotModelHandler & model_handler = test.model_handler; |
| 146 | + const RobotDataHandler & data_handler = test.data_handler; |
147 | 147 | const size_t nq = model_handler.getModel().nq; |
148 | 148 | const size_t nv = model_handler.getModel().nv; |
149 | 149 |
|
150 | 150 | // No need to set target as KinodynamicsID sets it by default to reference state |
151 | 151 | const Eigen::VectorXd q_target = model_handler.getReferenceState().head(nq); |
152 | 152 |
|
153 | | - // Change initial state |
154 | | - test.q = solo_q_start(model_handler); |
155 | | - |
156 | 153 | // Let the robot stabilize |
157 | | - const int N_STEP_ON_GROUND = 6000; |
158 | | - const int N_STEP_FREE_FALL = 2000; |
159 | | - for (int i = 0; i < N_STEP_ON_GROUND + N_STEP_FREE_FALL; i++) |
| 154 | + const int N_STEP = 500; |
| 155 | + while (test.step_i < N_STEP) |
160 | 156 | { |
161 | 157 | // Solve |
162 | 158 | test.step(); |
163 | 159 |
|
164 | | - if (i == N_STEP_ON_GROUND) |
| 160 | + for (int i = 0; i < test.q.size(); i++) |
165 | 161 | { |
166 | | - // Robot had time to reach permanent regime, is it stable on ground ? |
167 | | - BOOST_CHECK_SMALL(test.dq.head(3).norm(), 1e-4); |
168 | | - BOOST_CHECK_SMALL(test.ddq.head(3).norm(), 1e-4); |
169 | | - |
170 | | - // Remove contacts |
171 | | - test.solver.setTarget( |
172 | | - q_target, Eigen::VectorXd::Zero(nv), Eigen::VectorXd::Zero(nv), {false, false, false, false}, {}); |
| 162 | + std::cout << test.q[i] << " "; |
173 | 163 | } |
174 | | - if (i == N_STEP_ON_GROUND + N_STEP_FREE_FALL - 1) |
| 164 | + std::cout << std::endl; |
| 165 | + |
| 166 | + // Check that contact velocity is null |
| 167 | + for (int foot_nb = 0; foot_nb < model_handler.getFeetNb(); foot_nb++) |
175 | 168 | { |
176 | | - // Robot had time to reach permanent regime, is it robot free falling ? |
177 | | - BOOST_CHECK_SMALL(test.ddq.head(3).norm() - model_handler.getModel().gravity.linear().norm(), 0.01); |
| 169 | + const pinocchio::Motion foot_vel = pinocchio::getFrameVelocity( |
| 170 | + model_handler.getModel(), data_handler.getData(), model_handler.getFootFrameId(foot_nb), pinocchio::WORLD); |
| 171 | + BOOST_CHECK_LE(foot_vel.linear().norm(), 1e-2); |
| 172 | + if (model_handler.getFootType(foot_nb) == RobotModelHandler::FootType::QUAD) |
| 173 | + { |
| 174 | + // Rotation should also be null for quadrilateral contacts |
| 175 | + BOOST_CHECK_LE(foot_vel.angular().norm(), 1e-1); |
| 176 | + } |
178 | 177 | } |
179 | 178 | } |
180 | 179 | } |
181 | 180 |
|
| 181 | +BOOST_AUTO_TEST_CASE(KinodynamicsID_contactPoint_cost) |
| 182 | +{ |
| 183 | + TestKinoID simu( |
| 184 | + getSoloHandler(), KinodynamicsID::Settings() |
| 185 | + .set_kp_base(1.0) |
| 186 | + .set_kp_contact(10.0) |
| 187 | + .set_w_base(1.) |
| 188 | + .set_w_contact_motion(10.0) |
| 189 | + .set_w_contact_force(1.0)); |
| 190 | + simu.q = solo_q_start(simu.model_handler); // Set initial configuration |
| 191 | + test_contact(simu); |
| 192 | +} |
| 193 | + |
| 194 | +BOOST_AUTO_TEST_CASE(KinodynamicsID_contactPoint_equality) |
| 195 | +{ |
| 196 | + TestKinoID simu( |
| 197 | + getSoloHandler(), KinodynamicsID::Settings() |
| 198 | + .set_kp_base(1.0) |
| 199 | + .set_kp_contact(10.0) |
| 200 | + .set_w_base(1.) |
| 201 | + .set_w_contact_motion(10.0) |
| 202 | + .set_w_contact_force(1.0) |
| 203 | + .set_contact_motion_equality(true)); |
| 204 | + simu.q = solo_q_start(simu.model_handler); // Set initial configuration |
| 205 | + test_contact(simu); |
| 206 | +} |
| 207 | + |
| 208 | +BOOST_AUTO_TEST_CASE(KinodynamicsID_contactQuad_equality) |
| 209 | +{ |
| 210 | + TestKinoID simu( |
| 211 | + getTalosModelHandler(), KinodynamicsID::Settings() |
| 212 | + .set_kp_base(1.0) |
| 213 | + .set_kp_posture(1.) |
| 214 | + .set_kp_contact(10.0) |
| 215 | + .set_w_base(1.) |
| 216 | + .set_w_posture(0.1) |
| 217 | + .set_w_contact_motion(10.0) |
| 218 | + .set_contact_motion_equality(true)); |
| 219 | + test_contact(simu); |
| 220 | +} |
| 221 | + |
182 | 222 | BOOST_AUTO_TEST_CASE(KinodynamicsID_baseTask) |
183 | 223 | { |
184 | 224 | TestKinoID test( |
185 | 225 | getSoloHandler(), KinodynamicsID::Settings() |
186 | 226 | .set_kp_base(7.) |
187 | | - .set_kp_contact(10.0) |
| 227 | + .set_kp_contact(.1) |
188 | 228 | .set_w_base(100.0) |
189 | 229 | .set_w_contact_force(1.0) |
190 | 230 | .set_w_contact_motion(1.0)); |
|
0 commit comments