GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include <fstream> |
||
2 |
#include <hpp/bezier-com-traj/common_solve_methods.hh> |
||
3 |
#include <hpp/bezier-com-traj/solve.hh> |
||
4 |
#include <hpp/rbprm/contact_generation/reachability.hh> |
||
5 |
#include <hpp/rbprm/rbprm-fullbody.hh> |
||
6 |
#include <hpp/rbprm/stability/stability.hh> |
||
7 |
#include <hpp/util/timer.hh> |
||
8 |
#include <iostream> |
||
9 |
|||
10 |
#ifndef QHULL |
||
11 |
#define QHULL 0 |
||
12 |
#endif |
||
13 |
|||
14 |
#ifndef STAT_TIMINGS |
||
15 |
#define STAT_TIMINGS 0 |
||
16 |
#endif |
||
17 |
|||
18 |
#ifndef FULL_TIME_SAMPLING |
||
19 |
#define FULL_TIME_SAMPLING 0 |
||
20 |
#endif |
||
21 |
|||
22 |
namespace hpp { |
||
23 |
namespace rbprm { |
||
24 |
namespace reachability { |
||
25 |
|||
26 |
using centroidal_dynamics::Matrix3; |
||
27 |
using centroidal_dynamics::Vector3; |
||
28 |
|||
29 |
// helper method used to print vectors of string |
||
30 |
std::ostream& operator<<(std::ostream& os, |
||
31 |
const std::vector<std::string>& vect) { |
||
32 |
for (std::vector<std::string>::const_iterator sit = vect.begin(); |
||
33 |
sit != vect.end(); ++sit) { |
||
34 |
os << *sit << " ; "; |
||
35 |
} |
||
36 |
return os; |
||
37 |
} |
||
38 |
|||
39 |
void printQHullFile(const std::pair<MatrixXX, VectorX>& Ab, fcl::Vec3f intPoint, |
||
40 |
const std::string& fileName, bool clipZ = false) { |
||
41 |
std::ofstream file; |
||
42 |
using std::endl; |
||
43 |
std::string path("/local/fernbach/qhull/constraints_obj/"); |
||
44 |
path.append(fileName); |
||
45 |
hppDout(notice, "print to file : " << path); |
||
46 |
file.open(path.c_str(), std::ios::out | std::ios::trunc); |
||
47 |
file << "3 1" << endl; |
||
48 |
file << "\t " << intPoint[0] << "\t" << intPoint[1] << "\t" << intPoint[2] |
||
49 |
<< endl; |
||
50 |
file << "4" << endl; |
||
51 |
clipZ ? file << Ab.first.rows() + 2 << endl : file << Ab.first.rows() << endl; |
||
52 |
for (size_type i = 0; i < Ab.first.rows(); ++i) { |
||
53 |
file << "\t" << Ab.first(i, 0) << "\t" << Ab.first(i, 1) << "\t" |
||
54 |
<< Ab.first(i, 2) << "\t" << -Ab.second[i] - 0.005 << endl; |
||
55 |
} |
||
56 |
if (clipZ) { |
||
57 |
file << "\t" << 0 << "\t" << 0 << "\t" << 1. << "\t" << -3. << endl; |
||
58 |
file << "\t" << 0 << "\t" << 0 << "\t" << -1. << "\t" << -1. << endl; |
||
59 |
} |
||
60 |
file.close(); |
||
61 |
} |
||
62 |
|||
63 |
// Method to print (in hppDout) the inequalities express as halfspace, in a |
||
64 |
// format readable by qHull use qHalf FP | qConvex Ft to use them |
||
65 |
void printQHull(const std::pair<MatrixXX, VectorX>& Ab, |
||
66 |
fcl::Vec3f intPoint = fcl::Vec3f::Zero(), |
||
67 |
const std::string& fileName = std::string(), |
||
68 |
bool clipZ = false) { |
||
69 |
using std::endl; |
||
70 |
std::stringstream ss; |
||
71 |
ss << "qHull Output : use qhalf FP | qconvex Ft " << endl; |
||
72 |
ss << "3 1" << endl; |
||
73 |
ss << "\t " << intPoint[0] << "\t" << intPoint[1] << "\t" << intPoint[2] |
||
74 |
<< endl; |
||
75 |
ss << "4" << endl; |
||
76 |
for (size_type i = 0; i < Ab.first.rows(); ++i) { |
||
77 |
ss << "\t" << Ab.first(i, 0) << "\t" << Ab.first(i, 1) << "\t" |
||
78 |
<< Ab.first(i, 2) << "\t" << -Ab.second[i] - 0.001 << endl; |
||
79 |
} |
||
80 |
hppDout(notice, ss.str()); |
||
81 |
if (!fileName.empty()) printQHullFile(Ab, intPoint, fileName, clipZ); |
||
82 |
} |
||
83 |
|||
84 |
48 |
std::pair<MatrixXX, VectorX> stackConstraints( |
|
85 |
const std::pair<MatrixXX, VectorX>& Ab, |
||
86 |
const std::pair<MatrixXX, VectorX>& Cd) { |
||
87 |
✓✗✓✗ |
48 |
size_t numIneq = Ab.first.rows() + Cd.first.rows(); |
88 |
✓✗ | 96 |
MatrixXX M(numIneq, 3); |
89 |
✓✗ | 96 |
VectorX n(numIneq); |
90 |
✓✗✓✗ ✓✗ |
48 |
M.block(0, 0, Ab.first.rows(), 3) = Ab.first; |
91 |
✓✗✓✗ ✓✗✓✗ |
48 |
M.block(Ab.first.rows(), 0, Cd.first.rows(), 3) = Cd.first; |
92 |
✓✗✓✗ ✓✗ |
48 |
n.segment(0, Ab.first.rows()) = Ab.second; |
93 |
✓✗✓✗ ✓✗✓✗ |
48 |
n.segment(Ab.first.rows(), Cd.first.rows()) = Cd.second; |
94 |
✓✗ | 96 |
return std::make_pair(M, n); |
95 |
} |
||
96 |
|||
97 |
/** |
||
98 |
* @brief computeDistanceCost cost that minimize || x - c || |
||
99 |
* @param c0 target point (the point that we want to be the closest from) |
||
100 |
* @return the matrices H and g that express the cost |
||
101 |
*/ |
||
102 |
16 |
std::pair<MatrixXX, VectorX> computeDistanceCost(const fcl::Vec3f& c0) { |
|
103 |
✓✗✓✗ |
32 |
MatrixXX H = Matrix3::Identity(); |
104 |
✓✗✓✗ |
32 |
VectorX g = -c0; |
105 |
✓✗ | 32 |
return std::make_pair(H, g); |
106 |
} |
||
107 |
|||
108 |
16 |
bool intersectionExist(const std::pair<MatrixXX, VectorX>& Ab, |
|
109 |
const fcl::Vec3f& c, fcl::Vec3f& c_out) { |
||
110 |
hppDout(notice, "Call solveur solveIntersection"); |
||
111 |
hppDout(notice, "init = " << c); |
||
112 |
bezier_com_traj::ResultData res = |
||
113 |
✓✗✓✗ ✓✗ |
32 |
bezier_com_traj::solve(Ab, computeDistanceCost(c), c); |
114 |
✓✗ | 16 |
c_out = res.x; |
115 |
hppDout(notice, "success Solveur solveIntersection = " << res.success_); |
||
116 |
hppDout(notice, |
||
117 |
"x = [" << c_out[0] << "," << c_out[1] << "," << c_out[2] << "]"); |
||
118 |
32 |
return res.success_; |
|
119 |
} |
||
120 |
|||
121 |
32 |
std::pair<MatrixXX, VectorX> computeStabilityConstraints( |
|
122 |
const centroidal_dynamics::Equilibrium& contactPhase, |
||
123 |
const fcl::Vec3f& int_point, const fcl::Vec3f& acc) { |
||
124 |
// gravity vector |
||
125 |
hppDout(notice, "Compute stability constraints"); |
||
126 |
hppDout(notice, "With acceleration = " << acc); |
||
127 |
32 |
const Vector3& g = contactPhase.m_gravity; |
|
128 |
✓✗✓✗ ✓✗ |
32 |
const Matrix3 gSkew = bezier_com_traj::skew(g); |
129 |
✓✗✓✗ ✓✗ |
32 |
const Matrix3 accSkew = bezier_com_traj::skew(acc); |
130 |
// compute GIWC |
||
131 |
✓✗ | 64 |
centroidal_dynamics::MatrixXX Hrow; |
132 |
✓✗ | 64 |
VectorX h; |
133 |
centroidal_dynamics::LP_status status = |
||
134 |
✓✗ | 32 |
contactPhase.getPolytopeInequalities(Hrow, h); |
135 |
✗✓ | 32 |
if (status != centroidal_dynamics::LP_STATUS_OPTIMAL) { |
136 |
hppDout(warning, "getPolytopeInequalities failed, lp status : " + status); |
||
137 |
MatrixXX A(MatrixXX::Zero(0, 0)); |
||
138 |
VectorX b(VectorX::Zero(0)); |
||
139 |
return std::make_pair(A, b); |
||
140 |
} |
||
141 |
// hppDout(notice,"Hrow : \n"<<Hrow); |
||
142 |
✓✗✓✗ |
64 |
MatrixXX H = -Hrow; |
143 |
✓✗✓✗ |
32 |
H.rowwise().normalize(); |
144 |
✓✗ | 32 |
int dimH = (int)(H.rows()); |
145 |
hppDout(notice, "Dim H rows : " << dimH << " ; col : " << H.cols()); |
||
146 |
// hppDout(notice,"H : \n"<<H); |
||
147 |
✓✗✓✗ |
64 |
MatrixXX mH = contactPhase.m_mass * H; |
148 |
// constraints : mH[:,3:6] g^ x <= h + mH[:,0:3]g |
||
149 |
// A = mH g^ |
||
150 |
// b = h + mHg |
||
151 |
|||
152 |
✓✗✓✗ ✓✗✓✗ |
64 |
MatrixXX A(mH.block(0, 3, dimH, 3) * (gSkew - accSkew)); |
153 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
64 |
VectorX b(h + mH.block(0, 0, dimH, 3) * (g - acc)); |
154 |
/* hppDout(notice,"Stability constraints matrices : "); |
||
155 |
hppDout(notice,"Interior point : \n"<<int_point); |
||
156 |
hppDout(notice,"A = \n"<<A); |
||
157 |
hppDout(notice,"b = \n"<<b);*/ |
||
158 |
#if QHULL |
||
159 |
hppDout(notice, "Stability constraints qHull : "); |
||
160 |
printQHull(std::make_pair(A, b), int_point); |
||
161 |
#else |
||
162 |
(void)int_point; // silent the unused parameter warning in case QHULL 0 |
||
163 |
#endif |
||
164 |
✓✗ | 32 |
return std::make_pair(A, b); |
165 |
} |
||
166 |
|||
167 |
32 |
centroidal_dynamics::Equilibrium computeContactConeForState( |
|
168 |
const RbPrmFullBodyPtr_t& fullbody, State& state, bool& success) { |
||
169 |
hppStartBenchmark(REACHABLE_CALL_CENTROIDAL); |
||
170 |
centroidal_dynamics::Equilibrium contactCone( |
||
171 |
✓✗ | 32 |
fullbody->device_->name(), fullbody->device_->mass(), 4, |
172 |
✓✗ | 32 |
centroidal_dynamics::SOLVER_LP_QPOASES, true, 1000, false); |
173 |
32 |
centroidal_dynamics::EquilibriumAlgorithm alg = |
|
174 |
centroidal_dynamics::EQUILIBRIUM_ALGORITHM_PP; |
||
175 |
try { |
||
176 |
✓✗ | 32 |
stability::setupLibrary( |
177 |
fullbody, state, contactCone, alg, fullbody->getFriction(), 0.05, |
||
178 |
0.05); // 0.01 : 'safe' support zone, under the flexibility |
||
179 |
32 |
success = true; |
|
180 |
} catch (std::runtime_error e) { |
||
181 |
hppDout(notice, "Error in setupLibrary : " << e.what()); |
||
182 |
success = false; |
||
183 |
} |
||
184 |
hppStopBenchmark(REACHABLE_CALL_CENTROIDAL); |
||
185 |
hppDisplayBenchmark(REACHABLE_CALL_CENTROIDAL); |
||
186 |
64 |
return contactCone; |
|
187 |
} |
||
188 |
|||
189 |
32 |
std::pair<MatrixXX, VectorX> computeStabilityConstraintsForState( |
|
190 |
const RbPrmFullBodyPtr_t& fullbody, State& state, bool& success, |
||
191 |
const fcl::Vec3f& acc) { |
||
192 |
hppDout(notice, "contact order : "); |
||
193 |
hppDout(notice, " " << state.contactOrder_.front()); |
||
194 |
centroidal_dynamics::Equilibrium cone( |
||
195 |
✓✗ | 64 |
computeContactConeForState(fullbody, state, success)); |
196 |
✓✗ | 32 |
std::pair<MatrixXX, VectorX> Ab; |
197 |
✓✗ | 32 |
if (success) { |
198 |
32 |
Ab = computeStabilityConstraints( |
|
199 |
✓✗✓✗ |
32 |
cone, state.contactPositions_.at(state.contactOrder_.front()), acc); |
200 |
✓✗✓✗ ✓✗✗✓ ✗✓ |
32 |
if (Ab.first.cols() == 0 || Ab.first.rows() == 0) success = false; |
201 |
} else { |
||
202 |
MatrixXX A(MatrixXX::Zero(0, 0)); |
||
203 |
VectorX b(VectorX::Zero(0)); |
||
204 |
Ab = std::make_pair(A, b); |
||
205 |
} |
||
206 |
64 |
return Ab; |
|
207 |
} |
||
208 |
|||
209 |
32 |
std::pair<MatrixXX, VectorX> computeConstraintsForState( |
|
210 |
const RbPrmFullBodyPtr_t& fullbody, State& state, bool& success, |
||
211 |
const fcl::Vec3f& acc) { |
||
212 |
std::pair<MatrixXX, VectorX> Ab = |
||
213 |
✓✗ | 64 |
computeStabilityConstraintsForState(fullbody, state, success, acc); |
214 |
✓✗ | 32 |
if (success) |
215 |
return stackConstraints( |
||
216 |
✓✗✓✗ ✓✗ |
32 |
computeKinematicsConstraintsForState(fullbody, state), Ab); |
217 |
else |
||
218 |
return Ab; |
||
219 |
} |
||
220 |
|||
221 |
Result isReachableIntermediate(const RbPrmFullBodyPtr_t& fullbody, |
||
222 |
State& previous, State& intermediate, |
||
223 |
State& next) { |
||
224 |
// TODO |
||
225 |
hppDout(notice, "isReachableIntermadiate :"); |
||
226 |
std::vector<std::string> contactsNames = next.contactVariations(previous); |
||
227 |
hppDout(notice, "Contact variations : " << contactsNames); |
||
228 |
Result resBreak, resCreate; |
||
229 |
Result res; |
||
230 |
std::pair<MatrixXX, VectorX> Ab, Cd; |
||
231 |
resBreak = isReachable(fullbody, previous, intermediate); |
||
232 |
resCreate = isReachable(fullbody, intermediate, next); |
||
233 |
hppDout(notice, "isReachableIntermediate : "); |
||
234 |
hppDout(notice, "resBreak status : " << resBreak.status); |
||
235 |
hppDout(notice, "resCreation status : " << resCreate.status); |
||
236 |
#if QHULL |
||
237 |
hppDout(notice, "constraint for contact break : "); |
||
238 |
printQHull(resBreak.constraints_, resBreak.x, "constraints_break.txt"); |
||
239 |
hppDout(notice, "constraint for contact creation : "); |
||
240 |
printQHull(resCreate.constraints_, resCreate.x, "constraints_create.txt"); |
||
241 |
#endif |
||
242 |
if (resBreak.success() && resCreate.success()) { |
||
243 |
res.status = REACHABLE; |
||
244 |
res.x = (resBreak.x + resCreate.x) / 2.; |
||
245 |
res.xBreak_ = resBreak.x; |
||
246 |
res.xCreate_ = resCreate.x; |
||
247 |
hppDout(notice, "reachable intermediate success, x = " << res.x); |
||
248 |
// only for test, it take time to compute : |
||
249 |
#if QHULL |
||
250 |
hppDout(notice, "constraint for intersection : "); |
||
251 |
printQHull(stackConstraints(resBreak.constraints_, resCreate.constraints_), |
||
252 |
res.x, "constraints.txt"); |
||
253 |
#endif |
||
254 |
} else if (resBreak.status == UNREACHABLE && |
||
255 |
resCreate.status == UNREACHABLE) { |
||
256 |
res.status = UNREACHABLE; |
||
257 |
} else if (!resBreak.success()) { |
||
258 |
res.status = CONTACT_BREAK_FAILED; |
||
259 |
} else if (!resCreate.success()) { |
||
260 |
res.status = CONTACT_CREATION_FAILED; |
||
261 |
} |
||
262 |
return res; |
||
263 |
} |
||
264 |
|||
265 |
16 |
Result isReachable(const RbPrmFullBodyPtr_t& fullbody, State& previous, |
|
266 |
State& next, const fcl::Vec3f& acc, |
||
267 |
bool useIntermediateState) { |
||
268 |
hppStartBenchmark(IS_REACHABLE); |
||
269 |
✗✓ | 16 |
assert(previous.nbContacts > 0 && |
270 |
"Reachability : previous state have less than 1 contact."); |
||
271 |
✗✓ | 16 |
assert(next.nbContacts > 0 && |
272 |
"Reachability : next state have less than 1 contact."); |
||
273 |
32 |
std::vector<std::string> contactsCreation, contactsBreak; |
|
274 |
✓✗ | 16 |
next.contactBreaks(previous, contactsBreak); |
275 |
✓✗ | 16 |
next.contactCreations(previous, contactsCreation); |
276 |
hppDout(notice, "IsReachable called : for configuration : r([" |
||
277 |
<< pinocchio::displayConfig(previous.configuration_) |
||
278 |
<< "])"); |
||
279 |
hppDout(notice, "contact for previous : " << previous.nbContacts); |
||
280 |
hppDout(notice, "contact for next : " << next.nbContacts); |
||
281 |
hppDout(notice, "Contacts break : " << contactsBreak); |
||
282 |
hppDout(notice, "contacts creation : " << contactsCreation); |
||
283 |
|||
284 |
#if QHULL == 0 |
||
285 |
✗✓✗✗ ✗✓ |
16 |
if (contactsCreation.size() <= 0 && contactsBreak.size() <= 0) { |
286 |
hppDout(notice, "No contact variation, abort."); |
||
287 |
return Result(NO_CONTACT_VARIATION); |
||
288 |
} |
||
289 |
#endif |
||
290 |
|||
291 |
✓✗✗✓ ✗✓ |
16 |
if (contactsCreation.size() > 1 || contactsBreak.size() > 1) { |
292 |
hppDout(notice, "Too many contact variation, abort."); |
||
293 |
return Result(TOO_MANY_CONTACTS_VARIATION); |
||
294 |
} |
||
295 |
✓✗ | 32 |
State intermediate; |
296 |
✓✗✓✗ ✓✗ |
16 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) { |
297 |
✓✗✓✗ |
16 |
if (next.contactVariations(previous).size() == |
298 |
1) { // there is 1 contact repositionning between previous and next |
||
299 |
// we need to create the intermediate state, and call is reachable for the |
||
300 |
// 3 states. |
||
301 |
✓✗✓✗ |
16 |
intermediate = State(previous); |
302 |
✓✗ | 16 |
intermediate.RemoveContact(contactsBreak[0]); |
303 |
hppDout(notice, |
||
304 |
"Contact repositionning between the 2 states, create " |
||
305 |
"intermediate state"); |
||
306 |
✗✓ | 16 |
if (useIntermediateState) { |
307 |
hppDout(notice, "call isReachableIntermediate."); |
||
308 |
return isReachableIntermediate(fullbody, previous, intermediate, next); |
||
309 |
} |
||
310 |
} else { |
||
311 |
hppDout(notice, |
||
312 |
"Contact break and creation are different. You need to call " |
||
313 |
"isReachable with 2 adjacent states"); |
||
314 |
return Result(TOO_MANY_CONTACTS_VARIATION); |
||
315 |
} |
||
316 |
} |
||
317 |
|||
318 |
bool success; |
||
319 |
bool successCone; |
||
320 |
✓✗ | 32 |
Result res; |
321 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
32 |
std::pair<MatrixXX, VectorX> Ab, K_p, K_n, A_p, A_n; |
322 |
✓✗✓✗ ✓✗ |
16 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) { |
323 |
✓✗ | 16 |
A_p = computeConstraintsForState(fullbody, previous, successCone, acc); |
324 |
✗✓ | 16 |
if (!successCone) { |
325 |
hppDout(warning, |
||
326 |
"Unable to compute computeStabilityConstraintsForState."); |
||
327 |
return Result(UNABLE_TO_COMPUTE); |
||
328 |
} |
||
329 |
✓✗ | 16 |
A_n = computeConstraintsForState(fullbody, next, successCone, acc); |
330 |
✗✓ | 16 |
if (!successCone) { |
331 |
hppDout(warning, |
||
332 |
"Unable to compute computeStabilityConstraintsForState."); |
||
333 |
return Result(UNABLE_TO_COMPUTE); |
||
334 |
} |
||
335 |
✓✗ | 16 |
Ab = stackConstraints(A_p, A_n); |
336 |
} |
||
337 |
// there is only one contact creation OR (exclusive) break between the two |
||
338 |
// states test C_p \inter C_n (ie : A_p \inter K_p \inter A_n \inter K_n), |
||
339 |
// with simplifications du to relations between the constraints : |
||
340 |
else if (contactsBreak.size() > |
||
341 |
0) { // next have one less contact than previous |
||
342 |
hppDout(notice, "Contact break between previous and next state"); |
||
343 |
// A_n \inside A_p, thus A_p is redunbdant |
||
344 |
// K_p \inside K_n, thus K_n is redunbdant |
||
345 |
// So, we only need to test A_n \inter K_p |
||
346 |
// TODO : K_p can be given as parameter to avoid re-computation |
||
347 |
// std::pair<MatrixXX,VectorX> A_n = |
||
348 |
// computeStabilityConstraintsForState(fullbody,next); |
||
349 |
// std::pair<MatrixXX,VectorX> K_p = |
||
350 |
// computeKinematicsConstraintsForState(fullbody,previous); Ab = |
||
351 |
// stackConstraints(A_n,K_p); develloped computation, needed to display the |
||
352 |
// differents constraints : |
||
353 |
hppStartBenchmark(REACHABLE_STABILITY); |
||
354 |
A_n = computeStabilityConstraintsForState(fullbody, next, successCone, acc); |
||
355 |
if (!successCone) { |
||
356 |
hppDout(warning, |
||
357 |
"Unable to compute computeStabilityConstraintsForState."); |
||
358 |
return Result(UNABLE_TO_COMPUTE); |
||
359 |
} |
||
360 |
|||
361 |
hppStopBenchmark(REACHABLE_STABILITY); |
||
362 |
hppDisplayBenchmark(REACHABLE_STABILITY); |
||
363 |
hppStartBenchmark(REACHABLE_KINEMATIC); |
||
364 |
K_p = computeKinematicsConstraintsForState(fullbody, previous); |
||
365 |
hppStopBenchmark(REACHABLE_KINEMATIC); |
||
366 |
hppDisplayBenchmark(REACHABLE_KINEMATIC); |
||
367 |
hppStartBenchmark(REACHABLE_STACK); |
||
368 |
Ab = stackConstraints(A_n, K_p); |
||
369 |
hppStopBenchmark(REACHABLE_STACK); |
||
370 |
hppDisplayBenchmark(REACHABLE_STACK); |
||
371 |
} else { // next have one more contact than previous |
||
372 |
hppDout(notice, "Contact creation between previous and next"); |
||
373 |
// A_p \inside A_n, thus A_n is redunbdant |
||
374 |
// K_n \inside K_p ; and K_n = K_p \inter K_n^m (where K_n^m is the |
||
375 |
// kinematic constraint for the moving limb at state n) we use K_n^m, |
||
376 |
// because C_p can be given as parameter to avoid re-computation So, we only |
||
377 |
// need to test C_n \inter K_p_m std::pair<MatrixXX,VectorX> C_p = |
||
378 |
// computeConstraintsForState(fullbody,previous); |
||
379 |
// std::pair<MatrixXX,VectorX> K_n_m = |
||
380 |
// computeKinematicsConstraintsForLimb(fullbody,previous,contactsCreation[0]); |
||
381 |
// // kinematic constraint only for the moving contact for state previous Ab |
||
382 |
// = stackConstraints(C_p,K_n_m); |
||
383 |
hppStartBenchmark(REACHABLE_STABILITY); |
||
384 |
A_p = computeStabilityConstraintsForState(fullbody, previous, successCone, |
||
385 |
acc); |
||
386 |
if (!successCone) { |
||
387 |
hppDout(warning, |
||
388 |
"Unable to compute computeStabilityConstraintsForState."); |
||
389 |
return Result(UNABLE_TO_COMPUTE); |
||
390 |
} |
||
391 |
hppStopBenchmark(REACHABLE_STABILITY); |
||
392 |
hppDisplayBenchmark(REACHABLE_STABILITY); |
||
393 |
// K_p = computeKinematicsConstraintsForState(fullbody,previous); |
||
394 |
hppStartBenchmark(REACHABLE_KINEMATIC); |
||
395 |
K_n = computeKinematicsConstraintsForState(fullbody, next); |
||
396 |
hppStopBenchmark(REACHABLE_KINEMATIC); |
||
397 |
hppDisplayBenchmark(REACHABLE_KINEMATIC); |
||
398 |
hppStartBenchmark(REACHABLE_STACK); |
||
399 |
Ab = stackConstraints(A_p, K_n); |
||
400 |
hppStopBenchmark(REACHABLE_STACK); |
||
401 |
hppDisplayBenchmark(REACHABLE_STACK); |
||
402 |
} |
||
403 |
|||
404 |
// compute COM positions : |
||
405 |
✓✗ | 16 |
pinocchio::Computation_t flag = fullbody->device_->computationFlag(); |
406 |
16 |
pinocchio::Computation_t newflag = static_cast<pinocchio::Computation_t>( |
|
407 |
pinocchio::JOINT_POSITION | pinocchio::JACOBIAN | pinocchio::COM); |
||
408 |
✓✗ | 16 |
fullbody->device_->controlComputation(newflag); |
409 |
✓✗✓✗ |
16 |
fullbody->device_->currentConfiguration(previous.configuration_); |
410 |
✓✗ | 16 |
fullbody->device_->computeForwardKinematics(); |
411 |
✓✗✓✗ |
16 |
fcl::Vec3f com_previous = fullbody->device_->positionCenterOfMass(); |
412 |
✓✗✓✗ |
16 |
fullbody->device_->currentConfiguration(next.configuration_); |
413 |
✓✗ | 16 |
fullbody->device_->computeForwardKinematics(); |
414 |
✓✗✓✗ |
16 |
fcl::Vec3f com_next = fullbody->device_->positionCenterOfMass(); |
415 |
✓✗ | 16 |
fullbody->device_->controlComputation(flag); |
416 |
|||
417 |
// compute the position in the middle of the most constrained support polygon |
||
418 |
// (used for the cost function): |
||
419 |
✓✗ | 32 |
State smaller_state; |
420 |
✓✗✓✗ ✓✗ |
16 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) { |
421 |
✓✗ | 16 |
smaller_state = intermediate; |
422 |
} else if (contactsBreak.size() > |
||
423 |
0) { // next have the smaller support polygone |
||
424 |
smaller_state = next; |
||
425 |
} else { // previous have the smaller support polygon |
||
426 |
smaller_state = previous; |
||
427 |
} |
||
428 |
✓✗✓✗ |
16 |
fcl::Vec3f c_robust = fcl::Vec3f::Zero(); |
429 |
16 |
for (std::map<std::string, fcl::Vec3f>::const_iterator cit = |
|
430 |
16 |
smaller_state.contactPositions_.begin(); |
|
431 |
✓✓ | 48 |
cit != smaller_state.contactPositions_.end(); ++cit) { |
432 |
✓✗ | 16 |
fcl::Transform3f jointT(smaller_state.contactRotation_.at(cit->first), |
433 |
✓✗ | 32 |
cit->second); |
434 |
fcl::Vec3f position = |
||
435 |
✓✗✓✗ ✓✗ |
16 |
jointT.transform(fullbody->GetLimb(cit->first)->offset_); |
436 |
✓✗ | 16 |
c_robust += position; |
437 |
} |
||
438 |
✓✗ | 16 |
c_robust /= (fcl::FCL_REAL)smaller_state.contactPositions_.size(); |
439 |
✓✗✓✗ ✓✗ |
16 |
c_robust[2] = (com_previous[2] + com_next[2]) / 2.; |
440 |
|||
441 |
✓✗ | 16 |
fcl::Vec3f x; |
442 |
hppStartBenchmark(QP_REACHABLE); |
||
443 |
✓✗ | 16 |
success = intersectionExist(Ab, c_robust, x); |
444 |
hppStopBenchmark(QP_REACHABLE); |
||
445 |
hppDisplayBenchmark(QP_REACHABLE); |
||
446 |
✓✓ | 16 |
if (success) { |
447 |
13 |
res.status = REACHABLE; |
|
448 |
hppDout(notice, "REACHABLE"); |
||
449 |
} else { |
||
450 |
3 |
res.status = UNREACHABLE; |
|
451 |
hppDout(notice, "UNREACHABLE"); |
||
452 |
} |
||
453 |
✓✗ | 16 |
res.x = x; |
454 |
✓✗ | 16 |
res.constraints_ = Ab; |
455 |
hppStopBenchmark(IS_REACHABLE); |
||
456 |
hppDisplayBenchmark(IS_REACHABLE); |
||
457 |
|||
458 |
// compute interior point to display with qHull (only required for display and |
||
459 |
// debug) |
||
460 |
#if QHULL |
||
461 |
Vector3 int_pt_kin; |
||
462 |
fcl::Vec3f int_pt_stab; |
||
463 |
if (res.success()) { |
||
464 |
int_pt_stab = x; |
||
465 |
int_pt_kin = x; |
||
466 |
} else { |
||
467 |
if (contactsBreak.size() > 0) { |
||
468 |
int_pt_kin = com_previous; |
||
469 |
intersectionExist(A_n, (com_previous + com_next) / 2., int_pt_stab); |
||
470 |
} else { |
||
471 |
int_pt_kin = com_next; |
||
472 |
intersectionExist(A_p, (com_previous + com_next) / 2., int_pt_stab); |
||
473 |
} |
||
474 |
} |
||
475 |
|||
476 |
if (contactsBreak.size() > 0) { |
||
477 |
hppDout(notice, "Stability constraint for state i+1 :"); |
||
478 |
printQHull(A_n, int_pt_stab, "stability.txt", true); |
||
479 |
hppDout(notice, "Kinematics constraint for state i :"); |
||
480 |
printQHull(K_p, int_pt_kin, "kinematics.txt"); |
||
481 |
} else { |
||
482 |
hppDout(notice, "Stability constraint for state i :"); |
||
483 |
printQHull(A_p, int_pt_stab, "stability.txt", true); |
||
484 |
hppDout(notice, "Kinematics constraint for state i+1 :"); |
||
485 |
printQHull(K_n, int_pt_kin, "kinematics.txt"); |
||
486 |
} |
||
487 |
hppDout(notice, "Intersection of constraints :"); |
||
488 |
printQHull(Ab, int_pt_stab, "constraints.txt"); |
||
489 |
|||
490 |
if (contactsCreation.size() <= 0 && contactsBreak.size() <= 0) { |
||
491 |
hppDout(notice, "No contact variation, abort."); |
||
492 |
return Result(NO_CONTACT_VARIATION); |
||
493 |
} |
||
494 |
#endif |
||
495 |
|||
496 |
16 |
return res; |
|
497 |
} |
||
498 |
|||
499 |
void printTimingFile(std::ofstream& file, const VectorX& timings, bool success, |
||
500 |
bool quasiStaticSuccess) { |
||
501 |
using std::endl; |
||
502 |
file << timings[0] << " " << timings[1] << " " << timings[2] << " " |
||
503 |
<< (success ? "1 " : "0 ") << (quasiStaticSuccess ? "1" : "0") << endl; |
||
504 |
} |
||
505 |
|||
506 |
Result isReachableDynamic(const RbPrmFullBodyPtr_t& fullbody, State& previous, |
||
507 |
State& next, bool tryQuasiStatic, |
||
508 |
std::vector<double> timings, int numPointsPerPhases) { |
||
509 |
Result res; |
||
510 |
std::vector<std::string> contactsCreation, contactsBreak; |
||
511 |
next.contactBreaks(previous, contactsBreak); |
||
512 |
next.contactCreations(previous, contactsCreation); |
||
513 |
hppDout(notice, "IsReachableDynamic called : "); |
||
514 |
hppDout(notice, "Between configuration : " |
||
515 |
<< pinocchio::displayConfig(previous.configuration_)); |
||
516 |
hppDout(notice, "and configuration : " |
||
517 |
<< pinocchio::displayConfig(next.configuration_)); |
||
518 |
assert( |
||
519 |
fullbody->device_->extraConfigSpace().dimension() >= 6 && |
||
520 |
"You need to set at least 6 extraDOF to use the reachability methods."); |
||
521 |
if (previous.configuration_.head<3>() == next.configuration_.head<3>()) { |
||
522 |
hppDout(notice, "Same root position, unable to compute"); |
||
523 |
return Result(SAME_ROOT_POSITION); |
||
524 |
} |
||
525 |
hppDout(notice, "Contacts break : " << contactsBreak); |
||
526 |
hppDout(notice, "contacts creation : " << contactsCreation); |
||
527 |
if (contactsCreation.size() <= 0 && contactsBreak.size() <= 0) { |
||
528 |
hppDout(notice, "No contact variation, abort."); |
||
529 |
return Result(NO_CONTACT_VARIATION); |
||
530 |
} |
||
531 |
if ((contactsBreak.size() + contactsCreation.size()) > 2 || |
||
532 |
contactsBreak.size() > 1 || contactsCreation.size() > 1) { |
||
533 |
hppDout(notice, "More than 2 contact change"); |
||
534 |
return Result(TOO_MANY_CONTACTS_VARIATION); |
||
535 |
} |
||
536 |
if (contactsBreak.size() == 0) { |
||
537 |
hppDout(notice, |
||
538 |
"Only contact creation. State Next have more contact than state " |
||
539 |
"Previous"); |
||
540 |
if (previous.nbContacts <= 1) { |
||
541 |
hppDout( |
||
542 |
notice, |
||
543 |
"Previous is in single support. Unable to compute"); // FIXME : maybe |
||
544 |
// compute in |
||
545 |
// quasiStatic |
||
546 |
return Result(UNABLE_TO_COMPUTE); |
||
547 |
} |
||
548 |
} |
||
549 |
if (contactsCreation.size() == 0) { |
||
550 |
hppDout( |
||
551 |
notice, |
||
552 |
"Only contact break. State Next have less contact than state Previous"); |
||
553 |
if (next.nbContacts <= 1) { |
||
554 |
hppDout(notice, |
||
555 |
"Next is in single support. Unable to compute"); // FIXME : maybe |
||
556 |
// compute in |
||
557 |
// quasiStatic |
||
558 |
return Result(UNABLE_TO_COMPUTE); |
||
559 |
} |
||
560 |
} |
||
561 |
|||
562 |
// build intermediate state : |
||
563 |
State mid(previous); // build intermediate state |
||
564 |
if (contactsBreak.size() > 0) { |
||
565 |
mid.RemoveContact(contactsBreak[0]); |
||
566 |
} |
||
567 |
|||
568 |
#if STAT_TIMINGS |
||
569 |
// outputs timings results in file : |
||
570 |
std::ofstream file; |
||
571 |
std::string path("/local/fernbac/bench_iros18/bench/timing_hrp2_darpa.log"); |
||
572 |
hppDout(notice, "print to file : " << path); |
||
573 |
file.open(path.c_str(), std::ios_base::app); |
||
574 |
file << "# new pair of states" << std::endl; |
||
575 |
#endif |
||
576 |
bool quasiStaticSucces(false); |
||
577 |
|||
578 |
// compute COM positions : |
||
579 |
pinocchio::Computation_t flag = fullbody->device_->computationFlag(); |
||
580 |
pinocchio::Computation_t newflag = static_cast<pinocchio::Computation_t>( |
||
581 |
pinocchio::JOINT_POSITION | pinocchio::JACOBIAN | pinocchio::COM); |
||
582 |
fullbody->device_->controlComputation(newflag); |
||
583 |
fullbody->device_->currentConfiguration(previous.configuration_); |
||
584 |
fullbody->device_->computeForwardKinematics(); |
||
585 |
fcl::Vec3f com_previous = fullbody->device_->positionCenterOfMass(); |
||
586 |
fullbody->device_->currentConfiguration(next.configuration_); |
||
587 |
fullbody->device_->computeForwardKinematics(); |
||
588 |
fcl::Vec3f com_next = fullbody->device_->positionCenterOfMass(); |
||
589 |
fullbody->device_->controlComputation(flag); |
||
590 |
|||
591 |
if (tryQuasiStatic) { |
||
592 |
hppDout(notice, "Try quasi-static reachability : "); |
||
593 |
Result quasiStaticResult = |
||
594 |
isReachableIntermediate(fullbody, previous, mid, next); |
||
595 |
if (quasiStaticResult.success()) { |
||
596 |
hppDout(notice, "REACHABLE in quasi-static"); |
||
597 |
quasiStaticResult.status = QUASI_STATIC; |
||
598 |
// build a Bezier curve of order 2 : |
||
599 |
std::vector<Vector3> wps; |
||
600 |
wps.push_back(com_previous); |
||
601 |
wps.push_back(quasiStaticResult.x); |
||
602 |
wps.push_back(com_next); |
||
603 |
bezier_Ptr bezierCurve = bezier_Ptr(new bezier_t(wps.begin(), wps.end())); |
||
604 |
quasiStaticResult.path_ = BezierPath::create( |
||
605 |
fullbody->device_, bezierCurve, previous.configuration_, |
||
606 |
next.configuration_, core::interval_t(0., 1)); |
||
607 |
quasiStaticSucces = true; |
||
608 |
#if !STAT_TIMINGS |
||
609 |
return quasiStaticResult; |
||
610 |
#endif |
||
611 |
} else { |
||
612 |
hppDout(notice, "UNREACHABLE in quasi-static"); |
||
613 |
// return Result(REACHABLE); // testing |
||
614 |
} |
||
615 |
} |
||
616 |
|||
617 |
hppStartBenchmark(IS_REACHABLE_DYNAMIC); |
||
618 |
hppStartBenchmark(COMPUTE_DOUBLE_DESCRIPTION); |
||
619 |
|||
620 |
// build ProblemData from states object and call solveOneStep() |
||
621 |
bezier_com_traj::ProblemData pData; |
||
622 |
bool successCone(true), successConeCurrent; |
||
623 |
// build contactPhases : |
||
624 |
bezier_com_traj::ContactData previousData, nextData, midData; |
||
625 |
std::pair<MatrixX3, VectorX> Ab = |
||
626 |
computeKinematicsConstraintsForState(fullbody, previous); |
||
627 |
previousData.Kin_ = Ab.first; |
||
628 |
previousData.kin_ = Ab.second; |
||
629 |
centroidal_dynamics::Equilibrium conePrevious = |
||
630 |
computeContactConeForState(fullbody, previous, successConeCurrent); |
||
631 |
successCone = successCone && successConeCurrent; |
||
632 |
previousData.contactPhase_ = &conePrevious; |
||
633 |
if (contactsBreak.size() > 0) { |
||
634 |
Ab = computeKinematicsConstraintsForState(fullbody, mid); |
||
635 |
midData.Kin_ = Ab.first; |
||
636 |
midData.kin_ = Ab.second; |
||
637 |
} |
||
638 |
centroidal_dynamics::Equilibrium coneMid = |
||
639 |
computeContactConeForState(fullbody, mid, successConeCurrent); |
||
640 |
successCone = successCone && successConeCurrent; |
||
641 |
midData.contactPhase_ = &coneMid; |
||
642 |
Ab = computeKinematicsConstraintsForState(fullbody, next); |
||
643 |
nextData.Kin_ = Ab.first; |
||
644 |
nextData.kin_ = Ab.second; |
||
645 |
centroidal_dynamics::Equilibrium coneNext = |
||
646 |
computeContactConeForState(fullbody, next, successConeCurrent); |
||
647 |
successCone = successCone && successConeCurrent; |
||
648 |
nextData.contactPhase_ = &coneNext; |
||
649 |
|||
650 |
hppStopBenchmark(COMPUTE_DOUBLE_DESCRIPTION); |
||
651 |
hppDisplayBenchmark(COMPUTE_DOUBLE_DESCRIPTION); |
||
652 |
|||
653 |
if (!successCone) { |
||
654 |
return Result(UNABLE_TO_COMPUTE); |
||
655 |
} |
||
656 |
|||
657 |
pData.contacts_.push_back(previousData); |
||
658 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) { |
||
659 |
hppDout(notice, "Contact break AND creation, create intermediate state"); |
||
660 |
pData.contacts_.push_back(midData); |
||
661 |
} |
||
662 |
pData.contacts_.push_back(nextData); |
||
663 |
pData.constraints_.flag_ = |
||
664 |
bezier_com_traj::INIT_POS | bezier_com_traj::INIT_VEL | |
||
665 |
bezier_com_traj::INIT_ACC | bezier_com_traj::END_ACC | |
||
666 |
bezier_com_traj::END_VEL | bezier_com_traj::END_POS; |
||
667 |
pData.constraints_.constraintAcceleration_ = true; |
||
668 |
pData.constraints_.maxAcceleration_ = 10.; |
||
669 |
pData.constraints_.reduce_h_ = 1e-3; |
||
670 |
// set init/goal values : |
||
671 |
pData.c0_ = com_previous; |
||
672 |
pData.c1_ = com_next; |
||
673 |
size_t id_velocity = fullbody->device_->configSize() - |
||
674 |
fullbody->device_->extraConfigSpace().dimension(); |
||
675 |
pData.dc0_ = previous.configuration_.segment<3>(id_velocity); |
||
676 |
pData.dc1_ = next.configuration_.segment<3>(id_velocity); |
||
677 |
pData.ddc0_ = |
||
678 |
previous.configuration_.segment<3>(id_velocity + 3); // unused for now |
||
679 |
pData.ddc1_ = next.configuration_.segment<3>(id_velocity + 3); |
||
680 |
// pData.dc0_ = fcl::Vec3f::Zero(); |
||
681 |
// pData.dc1_ = fcl::Vec3f::Zero(); |
||
682 |
pData.ddc0_ = fcl::Vec3f::Zero(); |
||
683 |
pData.ddc1_ = fcl::Vec3f::Zero(); |
||
684 |
hppDout(notice, "Build pData : "); |
||
685 |
hppDout(notice, "c0 = " << pData.c0_.transpose()); |
||
686 |
hppDout(notice, "c1 = " << pData.c1_.transpose()); |
||
687 |
hppDout(notice, "dc0 = " << pData.dc0_.transpose()); |
||
688 |
hppDout(notice, "dc1 = " << pData.dc1_.transpose()); |
||
689 |
hppDout(notice, "ddc0 = " << pData.ddc0_.transpose()); |
||
690 |
hppDout(notice, "ddc1 = " << pData.ddc1_.transpose()); |
||
691 |
assert((pData.contacts_.size() == 2 || pData.contacts_.size() == 3) && |
||
692 |
"Error in computation of contact constraints, must be only 2 or 3 " |
||
693 |
"phases."); |
||
694 |
|||
695 |
// compute initial guess : |
||
696 |
// average of all contact point for the state with the less contacts, z = |
||
697 |
// average of the CoM heigh between previous and next |
||
698 |
State lessContacts; |
||
699 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) |
||
700 |
lessContacts = mid; |
||
701 |
else if (contactsBreak.size() == 1) |
||
702 |
lessContacts = next; |
||
703 |
else if (contactsCreation.size() == 1) |
||
704 |
lessContacts = previous; |
||
705 |
else |
||
706 |
lessContacts = previous; |
||
707 |
|||
708 |
VectorX current_timings; |
||
709 |
double total_time = 0; |
||
710 |
bool timing_provided(false); |
||
711 |
int t_id = 1; |
||
712 |
#if !FULL_TIME_SAMPLING |
||
713 |
MatrixXX timings_matrix; |
||
714 |
#endif |
||
715 |
hppDout(notice, " timings provided size : " << timings.size()); |
||
716 |
if (timings.size() != pData.contacts_.size()) { |
||
717 |
// build timing vector |
||
718 |
// TODO : retrieve timing found by planning ?? how ?? (pass it as argument |
||
719 |
// or store it inside the states ?) |
||
720 |
hppDout(notice, "Contact break and creation. Use hardcoded timing matrice"); |
||
721 |
#if FULL_TIME_SAMPLING |
||
722 |
const double time_increment = 0.05; |
||
723 |
const double min_SS = 0.6; |
||
724 |
const double max_SS = 1.6; |
||
725 |
const double min_DS = 0.3; |
||
726 |
const double max_DS = 1.5; |
||
727 |
if (contactsBreak.size() == 1 && contactsCreation.size() == 1) { |
||
728 |
current_timings = VectorX(3); |
||
729 |
// current_timings<<0.6,0.4,0.6; //hrp2 |
||
730 |
// total_time = 1.6; |
||
731 |
current_timings << min_DS, min_SS, min_DS; // hrp2 |
||
732 |
} else { |
||
733 |
hppDout(notice, "Only two phases."); |
||
734 |
current_timings = VectorX(2); |
||
735 |
current_timings << 1., 1.; |
||
736 |
} |
||
737 |
#else |
||
738 |
timings_matrix = |
||
739 |
MatrixXX(18, 3); // contain the timings of the first 3 phases, the |
||
740 |
// total time and the discretization step |
||
741 |
timings_matrix << 0.6, 1.2, 0.6, 1., 1.2, 1., 0.8, 0.7, 0.8, 0.3, 0.6, 0.3, |
||
742 |
0.5, 0.6, 0.5, 0.6, 0.6, 0.6, 0.8, 0.6, 0.8, 0.3, 0.8, 0.3, 0.3, 0.7, |
||
743 |
0.3, 0.6, 0.8, 0.6, 1, 0.7, 1, // found with script |
||
744 |
1.5, 0.7, 1, 0.8, 0.8, 0.8, // script good |
||
745 |
1., 0.6, 1., 1.2, 0.6, 1.2, 1.5, 0.6, 1.5, 0.1, 0.2, 0.1, 0.2, 0.3, 0.2; |
||
746 |
current_timings = |
||
747 |
timings_matrix.block(0, 0, 1, pData.contacts_.size()).transpose(); |
||
748 |
#endif |
||
749 |
total_time = 0; |
||
750 |
for (size_t i = 0; i < pData.contacts_.size(); ++i) { |
||
751 |
total_time += current_timings[i]; |
||
752 |
} |
||
753 |
} else { |
||
754 |
hppDout(notice, "Timing vector is provided"); |
||
755 |
current_timings = VectorX(timings.size()); |
||
756 |
for (size_t i = 0; i < timings.size(); ++i) { |
||
757 |
current_timings[i] = timings[i]; |
||
758 |
total_time += timings[i]; |
||
759 |
} |
||
760 |
timing_provided = true; |
||
761 |
} |
||
762 |
|||
763 |
// pData.representation_ = bezier_com_traj::FORCE; |
||
764 |
|||
765 |
// loop over all possible timings : |
||
766 |
bool success(false); |
||
767 |
bool no_timings_left(false); |
||
768 |
bezier_com_traj::ResultDataCOMTraj resBezier; |
||
769 |
#if STAT_TIMINGS |
||
770 |
while (!no_timings_left) { |
||
771 |
#else |
||
772 |
while (!success && !no_timings_left) { |
||
773 |
#endif |
||
774 |
// call solveur : |
||
775 |
hppDout(notice, "Try with timings : " << current_timings.transpose()); |
||
776 |
hppDout(notice, "Call solveOneStep"); |
||
777 |
hppStartBenchmark(SOLVE_TRANSITION_ONE_STEP); |
||
778 |
if (numPointsPerPhases > 0) { |
||
779 |
hppDout(notice, "Call computeCOMTraj discretized"); |
||
780 |
resBezier = bezier_com_traj::computeCOMTrajFixedSize( |
||
781 |
pData, current_timings, numPointsPerPhases); |
||
782 |
} else { |
||
783 |
hppDout(notice, "Call computeCOMTraj continuous"); |
||
784 |
resBezier = bezier_com_traj::computeCOMTraj(pData, current_timings); |
||
785 |
} |
||
786 |
|||
787 |
hppStopBenchmark(SOLVE_TRANSITION_ONE_STEP); |
||
788 |
hppDisplayBenchmark(SOLVE_TRANSITION_ONE_STEP); |
||
789 |
|||
790 |
// wrap the result : |
||
791 |
if (resBezier.success_) { |
||
792 |
hppDout(notice, "REACHABLE"); |
||
793 |
res.status = REACHABLE; |
||
794 |
bezier_Ptr bezierCurve = bezier_Ptr(new bezier_t(resBezier.c_of_t_)); |
||
795 |
hppDout(notice, |
||
796 |
"Resulting bezier curve have timing : " << bezierCurve->max()); |
||
797 |
for (bezier_t::cit_point_t wpit = bezierCurve->waypoints().begin(); |
||
798 |
wpit != bezierCurve->waypoints().end(); ++wpit) { |
||
799 |
hppDout(notice, "with waypoint : " << (*wpit).transpose()); |
||
800 |
} |
||
801 |
// replace extra dof in next.configuration to fit the final velocity and |
||
802 |
// acceleration found : |
||
803 |
next.configuration_.segment<3>(id_velocity) = resBezier.dc1_; |
||
804 |
next.configuration_.segment<3>(id_velocity + 3) = resBezier.ddc1_; |
||
805 |
hppDout(notice, "new final configuration : " |
||
806 |
<< pinocchio::displayConfig(next.configuration_)); |
||
807 |
res.path_ = BezierPath::create( |
||
808 |
fullbody->device_, bezierCurve, previous.configuration_, |
||
809 |
next.configuration_, core::interval_t(0., total_time)); |
||
810 |
hppDout(notice, "position of the waypoint : " << resBezier.x.transpose()); |
||
811 |
hppDout(notice, "With timings : " << current_timings.transpose()); |
||
812 |
hppDout(notice, "total time = " << total_time); |
||
813 |
hppDout(notice, "new final velocity : " << resBezier.dc1_.transpose()); |
||
814 |
res.timings_ = current_timings; |
||
815 |
res.pathPerPhases_.push_back(BezierPath::create( |
||
816 |
fullbody->device_, bezierCurve, previous.configuration_, |
||
817 |
next.configuration_, core::interval_t(0., current_timings[0]))); |
||
818 |
res.pathPerPhases_.push_back(BezierPath::create( |
||
819 |
fullbody->device_, bezierCurve, previous.configuration_, |
||
820 |
next.configuration_, |
||
821 |
core::interval_t(current_timings[0], |
||
822 |
current_timings[0] + current_timings[1]))); |
||
823 |
if (current_timings.size() > 2) |
||
824 |
res.pathPerPhases_.push_back(BezierPath::create( |
||
825 |
fullbody->device_, bezierCurve, previous.configuration_, |
||
826 |
next.configuration_, |
||
827 |
core::interval_t(current_timings[0] + current_timings[1], |
||
828 |
total_time))); |
||
829 |
success = true; |
||
830 |
} else { |
||
831 |
hppDout(notice, "UNREACHABLE"); |
||
832 |
res.status = UNREACHABLE; |
||
833 |
} |
||
834 |
#if STAT_TIMINGS |
||
835 |
// print result in file : |
||
836 |
printTimingFile(file, current_timings, res.success(), quasiStaticSucces); |
||
837 |
#else |
||
838 |
(void)quasiStaticSucces; // silent warning |
||
839 |
#endif |
||
840 |
// build the new timing vector : |
||
841 |
|||
842 |
if (!timing_provided) { |
||
843 |
#if FULL_TIME_SAMPLING |
||
844 |
current_timings[0] += time_increment; |
||
845 |
if (current_timings[0] > max_DS) { |
||
846 |
current_timings[0] = min_DS; |
||
847 |
current_timings[1] += time_increment; |
||
848 |
if (current_timings[1] > max_SS) { |
||
849 |
if (current_timings.size() == 3) { |
||
850 |
current_timings[1] = min_SS; |
||
851 |
current_timings[2] += time_increment; |
||
852 |
if (current_timings[2] > max_DS) { |
||
853 |
no_timings_left = true; |
||
854 |
} |
||
855 |
} else { |
||
856 |
no_timings_left = true; |
||
857 |
} |
||
858 |
} |
||
859 |
} |
||
860 |
#else |
||
861 |
current_timings = |
||
862 |
timings_matrix.block(t_id, 0, 1, pData.contacts_.size()).transpose(); |
||
863 |
t_id++; |
||
864 |
if (t_id == timings_matrix.rows()) no_timings_left = true; |
||
865 |
#endif |
||
866 |
total_time = 0; |
||
867 |
for (size_t i = 0; i < pData.contacts_.size(); ++i) { |
||
868 |
total_time += current_timings[i]; |
||
869 |
} |
||
870 |
} else { |
||
871 |
no_timings_left = true; |
||
872 |
} |
||
873 |
} |
||
874 |
|||
875 |
hppStopBenchmark(IS_REACHABLE_DYNAMIC); |
||
876 |
hppDisplayBenchmark(IS_REACHABLE_DYNAMIC); |
||
877 |
|||
878 |
delete pData.contacts_[0].contactPhase_; |
||
879 |
delete pData.contacts_[1].contactPhase_; |
||
880 |
if (pData.contacts_.size() > 2) delete pData.contacts_[2].contactPhase_; |
||
881 |
|||
882 |
#if STAT_TIMINGS |
||
883 |
file.close(); |
||
884 |
return Result(REACHABLE); |
||
885 |
#endif |
||
886 |
|||
887 |
if (!success) { |
||
888 |
hppDout(notice, "No valid timings found, always UNREACHABLE"); |
||
889 |
} |
||
890 |
|||
891 |
if (success && tryQuasiStatic) { |
||
892 |
hppDout(notice, "ONLY REACHABLE IN DYNAMIC !!!"); |
||
893 |
} |
||
894 |
hppDout(notice, "Between configuration : r([" |
||
895 |
<< pinocchio::displayConfig(previous.configuration_) |
||
896 |
<< "])"); |
||
897 |
hppDout(notice, "and configuration : r([" |
||
898 |
<< pinocchio::displayConfig(next.configuration_) << "])"); |
||
899 |
|||
900 |
return res; |
||
901 |
} |
||
902 |
|||
903 |
} // namespace reachability |
||
904 |
} // namespace rbprm |
||
905 |
} // namespace hpp |
Generated by: GCOVR (Version 4.2) |