GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/projection/projection.cc Lines: 50 368 13.6 %
Date: 2024-02-02 12:21:48 Branches: 50 824 6.1 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2017 CNRS
3
// Authors: Steve Tonneau
4
//
5
// This file is part of hpp-rbprm
6
// hpp-core is free software: you can redistribute it
7
// and/or modify it under the terms of the GNU Lesser General Public
8
// License as published by the Free Software Foundation, either version
9
// 3 of the License, or (at your option) any later version.
10
//
11
// hpp-core is distributed in the hope that it will be
12
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
// General Lesser Public License for more details.  You should have
15
// received a copy of the GNU Lesser General Public License along with
16
// hpp-core  If not, see
17
// <http://www.gnu.org/licenses/>.
18
19
#include <hpp/constraints/relative-com.hh>
20
#include <hpp/constraints/symbolic-calculus.hh>
21
#include <hpp/constraints/symbolic-function.hh>
22
#include <hpp/pinocchio/joint.hh>
23
#include <hpp/rbprm/interpolation/interpolation-constraints.hh>
24
#include <hpp/rbprm/projection/projection.hh>
25
26
#ifdef PROFILE
27
#include "hpp/rbprm/rbprm-profiler.hh"
28
#endif
29
30
namespace hpp {
31
namespace rbprm {
32
namespace projection {
33
34
const double epsilon = 10e-4;
35
36
ProjectionReport::ProjectionReport(const ProjectionReport& from)
37
    : success_(from.success_), result_(from.result_), status_(from.status_) {
38
  // NOTHING
39
}
40
41
102
std::vector<bool> setMaintainRotationConstraints() {
42
102
  std::vector<bool> res;
43

408
  for (std::size_t i = 0; i < 3; ++i) res.push_back(true);
44
102
  return res;
45
}
46
47
102
void CreateContactConstraints(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
48
                              const hpp::rbprm::State& currentState,
49
                              core::ConfigProjectorPtr_t proj) {
50
204
  pinocchio::DevicePtr_t device = fullBody->device_;
51
204
  std::vector<bool> cosntraintsR = setMaintainRotationConstraints();
52
204
  std::vector<std::string> fixed = currentState.fixedContacts(currentState);
53
510
  for (std::vector<std::string>::const_iterator cit = fixed.begin();
54
918
       cit != fixed.end(); ++cit) {
55
408
    const std::string& effector = *cit;
56
816
    RbPrmLimbPtr_t limb = fullBody->GetLimbs().at(effector);
57
408
    const fcl::Vec3f& ppos = currentState.contactPositions_.at(effector);
58
    const pinocchio::Frame effectorFrame =
59

816
        device->getFrameByName(limb->effector_.name());
60
816
    pinocchio::JointPtr_t effectorJoint = effectorFrame.joint();
61
62
816
    std::vector<bool> mask;
63
408
    mask.push_back(true);
64
408
    mask.push_back(true);
65
408
    mask.push_back(true);
66

408
    pinocchio::Transform3f localFrame(1), globalFrame(1);
67
408
    globalFrame.translation(ppos);
68
    const constraints::DifferentiableFunctionPtr_t& function =
69

1224
        constraints::Position::create(
70
            effector, device, effectorJoint,
71

816
            effectorFrame.pinocchio().placement * localFrame, globalFrame,
72
816
            mask);
73
408
    constraints::ComparisonTypes_t comp(function->outputDerivativeSize(),
74
1224
                                        constraints::EqualToZero);
75

408
    proj->add(constraints::Implicit::create(function, comp));
76
77
    /*proj->add(constraints::Implicit::create (
78
                            constraints:::Position::create("",device,
79
                                                          effectorJoint,fcl::Vec3f(0,0,0),
80
       ppos)));*/
81
408
    if (limb->contactType_ == hpp::rbprm::_6_DOF) {
82
      pinocchio::Transform3f rotation(1);
83
      rotation.rotation(
84
          currentState.contactRotation_.at(effector) *
85
          effectorFrame.pinocchio().placement.rotation().transpose());
86
      const constraints::DifferentiableFunctionPtr_t& function_ =
87
          constraints::Orientation::create("", device, effectorJoint, rotation,
88
                                           cosntraintsR);
89
      constraints::ComparisonTypes_t comp_(function_->outputDerivativeSize(),
90
                                           constraints::EqualToZero);
91
      proj->add(constraints::Implicit::create(function_, comp_));
92
93
      // const fcl::Matrix3f& rotation =
94
      // currentState.contactRotation_.at(effector);
95
      /*proj->add(constraints::Implicit::create
96
         (constraints::deprecated::Orientation::create("", device,
97
                                                                        effectorJoint,
98
                                                                        rotation,
99
                                                                        cosntraintsR)));*/
100
    }
101
  }
102
102
}
103
104
void CreateRootPosConstraint(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
105
                             const fcl::Vec3f& target,
106
                             core::ConfigProjectorPtr_t proj) {
107
  pinocchio::Transform3f position(1);
108
  position.translation(target);
109
  const constraints::DifferentiableFunctionPtr_t& function =
110
      constraints::Position::create("", fullBody->device_,
111
                                    fullBody->device_->rootJoint(),
112
                                    pinocchio::Transform3f(1), position);
113
  constraints::ComparisonTypes_t comp(function->outputDerivativeSize(),
114
                                      constraints::EqualToZero);
115
  proj->add(constraints::Implicit::create(function, comp));
116
}
117
118
typedef constraints::PointCom PointCom;
119
typedef constraints::CalculusBaseAbstract<PointCom::ValueType_t,
120
                                          PointCom::JacobianType_t>
121
    s_t;
122
typedef constraints::SymbolicFunction<s_t> PointComFunction;
123
typedef constraints::SymbolicFunction<s_t>::Ptr_t PointComFunctionPtr_t;
124
125
102
void CreateComPosConstraint(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
126
                            const fcl::Vec3f& target,
127
                            core::ConfigProjectorPtr_t proj) {
128
204
  pinocchio::DevicePtr_t device = fullBody->device_;
129
  pinocchio::CenterOfMassComputationPtr_t comComp =
130
204
      pinocchio::CenterOfMassComputation::create(device);
131

102
  comComp->add(device->rootJoint());
132
102
  comComp->compute();
133
  PointComFunctionPtr_t comFunc = PointComFunction::create(
134

306
      "COM-constraint", device, PointCom::create(comComp));
135
204
  constraints::ComparisonTypes_t equals(3, constraints::Equality);
136
  constraints::ImplicitPtr_t comEq =
137

204
      constraints::Implicit::create(comFunc, equals);
138
102
  proj->add(comEq);
139

102
  proj->rightHandSide(comEq, target);
140
102
}
141
142
void CreatePosturalTaskConstraint(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
143
                                  core::ConfigProjectorPtr_t proj) {
144
  // hppDout(notice,"create postural task, in projection.cc, ref config =
145
  // "<<pinocchio::displayConfig(fullBody->referenceConfig()));
146
  std::vector<bool> mask(fullBody->device_->numberDof(), false);
147
  // mask : 0 for the freeflyer and the extraDoFs :
148
  for (size_t i = 0; i < 3; i++) {
149
    mask[i] = false;
150
  }
151
  for (size_type i = fullBody->device_->numberDof() - 7;
152
       i < fullBody->device_->numberDof(); i++) {
153
    mask[i] = false;
154
  }
155
156
  /*for(size_t i = 3 ; i <= 9 ; i++){
157
    mask[i] = true;
158
  }*/
159
  // mask[5] = false; // z root rotation ????
160
161
  Configuration_t weight(fullBody->device_->numberDof());
162
  if (fullBody->postureWeights().size() == fullBody->device_->numberDof()) {
163
    weight = fullBody->postureWeights();
164
  } else {
165
    for (size_type i = 0; i < fullBody->device_->numberDof(); ++i)
166
      weight[i] = 1.;
167
  }
168
169
  // normalize weight array :
170
  /*value_type moy =0;
171
  int num_active = 0;
172
  for (size_type i = 0 ; i < weight.size() ; i++){
173
    if(mask[i]){
174
      moy += weight[i];
175
      num_active++;
176
    }
177
  }
178
  moy = moy/num_active;
179
  for (size_type i = 0 ; i < weight.size() ; i++)
180
    weight[i] = weight[i]/moy;
181
182
  */
183
184
  std::ostringstream oss;
185
  for (size_type i = 0; i < weight.size(); ++i) {
186
    oss << weight[i] << ",";
187
  }
188
  // hppDout(notice,"weight postural task = "<<oss.str());
189
190
  // constraints::ConfigurationConstraintPtr_t postFunc =
191
  // constraints::ConfigurationConstraint::create("Postural_Task",fullBody->device_,fullBody->referenceConfig(),weight,mask);
192
  constraints::ConfigurationConstraintPtr_t postFunc =
193
      constraints::ConfigurationConstraint::create(
194
          "Postural_Task", fullBody->device_, fullBody->referenceConfig(),
195
          weight);
196
  ComparisonTypes_t comps;
197
  comps.push_back(constraints::Equality);
198
  const constraints::ImplicitPtr_t posturalTask =
199
      constraints::Implicit::create(postFunc, comps);
200
  proj->add(posturalTask, 1);
201
  // proj->updateRightHandSide();
202
}
203
204
ProjectionReport projectToRootPosition(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
205
                                       const fcl::Vec3f& target,
206
                                       const hpp::rbprm::State& currentState) {
207
  ProjectionReport res;
208
  core::ConfigProjectorPtr_t proj =
209
      core::ConfigProjector::create(fullBody->device_, "proj", 1e-4, 100);
210
  CreateContactConstraints(fullBody, currentState, proj);
211
  CreateRootPosConstraint(fullBody, target, proj);
212
  pinocchio::Configuration_t configuration = currentState.configuration_;
213
  res.success_ = proj->apply(configuration);
214
  res.result_ = currentState;
215
  res.result_.configuration_ = configuration;
216
  return res;
217
}
218
219
typedef std::vector<pinocchio::JointPtr_t> T_Joint;
220
221
T_Joint getJointsFromLimbs(const rbprm::T_Limb limbs) {
222
  T_Joint res;
223
  for (rbprm::CIT_Limb cit = limbs.begin(); cit != limbs.end(); ++cit)
224
    res.push_back(cit->second->limb_);
225
  return res;
226
}
227
228
bool not_a_limb(pinocchio::JointPtr_t cJoint, T_Joint limbs) {
229
  for (T_Joint::const_iterator cit = limbs.begin(); cit != limbs.end(); ++cit) {
230
    if (cJoint->name() == (*cit)->name()) return false;
231
  }
232
  return true;
233
}
234
235
void LockFromRootRec(pinocchio::JointPtr_t cJoint,
236
                     const std::vector<pinocchio::JointPtr_t>& jointLimbs,
237
                     pinocchio::ConfigurationIn_t targetRootConfiguration,
238
                     core::ConfigProjectorPtr_t& projector) {
239
  if (not_a_limb(cJoint, jointLimbs)) {
240
    core::size_type rankInConfiguration = (cJoint->rankInConfiguration());
241
    projector->add(core::LockedJoint::create(
242
        cJoint, LiegroupElement(targetRootConfiguration.segment(
243
                                    rankInConfiguration, cJoint->configSize()),
244
                                cJoint->configurationSpace())));
245
    // if (cJoint->numberChildJoints() !=1)
246
    //    return;
247
    for (std::size_t i = 0; i < cJoint->numberChildJoints(); ++i)
248
      LockFromRootRec(cJoint->childJoint(i), jointLimbs,
249
                      targetRootConfiguration, projector);
250
  }
251
}
252
253
void LockFromRoot(hpp::pinocchio::DevicePtr_t device,
254
                  const rbprm::T_Limb& limbs,
255
                  pinocchio::ConfigurationIn_t targetRootConfiguration,
256
                  core::ConfigProjectorPtr_t& projector) {
257
  std::vector<pinocchio::JointPtr_t> jointLimbs = getJointsFromLimbs(limbs);
258
  pinocchio::JointPtr_t cJoint = device->rootJoint();
259
  LockFromRootRec(cJoint, jointLimbs, targetRootConfiguration, projector);
260
}
261
262
ProjectionReport projectToRootConfiguration(
263
    hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
264
    const pinocchio::ConfigurationIn_t conf,
265
    const hpp::rbprm::State& currentState, const Vector3 offset) {
266
  ProjectionReport res;
267
  core::ConfigProjectorPtr_t proj =
268
      core::ConfigProjector::create(fullBody->device_, "proj", 1e-4, 100);
269
  CreateContactConstraints(fullBody, currentState, proj);
270
  if (offset == Vector3::Zero())
271
    LockFromRoot(fullBody->device_, fullBody->GetLimbs(), conf, proj);
272
  else {
273
    const std::string rootJointName("root_joint");
274
    const fcl::Vec3f ppos = conf.head<3>();
275
    const pinocchio::Frame effectorFrame =
276
        fullBody->device_->getFrameByName(rootJointName);
277
    pinocchio::JointPtr_t effectorJoint = effectorFrame.joint();
278
279
    std::vector<bool> mask;
280
    mask.push_back(true);
281
    mask.push_back(true);
282
    mask.push_back(true);
283
    pinocchio::Transform3f localFrame(1), globalFrame(1);
284
    localFrame.translation(offset);
285
    globalFrame.translation(ppos);
286
    const constraints::DifferentiableFunctionPtr_t& function =
287
        constraints::Position::create(
288
            rootJointName, fullBody->device_, effectorJoint,
289
            effectorFrame.pinocchio().placement * localFrame, globalFrame,
290
            mask);
291
    constraints::ComparisonTypes_t comp(function->outputDerivativeSize(),
292
                                        constraints::EqualToZero);
293
    proj->add(constraints::Implicit::create(function, comp));
294
  }
295
  pinocchio::Configuration_t configuration = currentState.configuration_;
296
  res.success_ = proj->apply(configuration);
297
  res.result_ = currentState;
298
  res.result_.configuration_ = configuration;
299
  return res;
300
}
301
302
ProjectionReport setCollisionFree(
303
    hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
304
    const core::CollisionValidationPtr_t& validation,
305
    const std::string& limbName, const hpp::rbprm::State& currentState) {
306
  ProjectionReport res;
307
  res.result_ = currentState;
308
  pinocchio::Configuration_t configuration = currentState.configuration_;
309
  hpp::core::ValidationReportPtr_t valRep(
310
      new hpp::core::CollisionValidationReport);
311
  if (validation->validate(configuration, valRep)) {
312
    res.result_.configuration_ = configuration;
313
    res.success_ = true;
314
    hppDout(notice,
315
            "Found collision free conf : current configuration was already "
316
            "valid !");
317
    return res;
318
  }
319
320
  RbPrmLimbPtr_t limb = fullBody->GetLimb(limbName);
321
  sampling::T_Sample& samples = limb->sampleContainer_.samples_;
322
  for (sampling::SampleVector_t::const_iterator cit = samples.begin();
323
       cit != samples.end(); ++cit) {
324
    sampling::Load(*cit, configuration);
325
    hppDout(notice,
326
            "Set collision free : static value = " << cit->staticValue_);
327
    if (validation->validate(configuration, valRep)) {
328
      res.result_.configuration_ = configuration;
329
      res.success_ = true;
330
      hppDout(notice, "Found collision free conf !");
331
      return res;
332
    }
333
  }
334
  return res;
335
}
336
337
std::vector<bool> setRotationConstraints() {
338
  std::vector<bool> res;
339
  for (std::size_t i = 0; i < 3; ++i) {
340
    res.push_back(true);
341
  }
342
  return res;
343
}
344
345
std::vector<bool> setTranslationConstraints() {
346
  std::vector<bool> res;
347
  for (std::size_t i = 0; i < 3; ++i) {
348
    res.push_back(true);
349
  }
350
  return res;
351
}
352
ProjectionReport projectEffector(hpp::core::ConfigProjectorPtr_t proj,
353
                                 const hpp::rbprm::RbPrmFullBodyPtr_t& body,
354
                                 const std::string& limbId,
355
                                 const hpp::rbprm::RbPrmLimbPtr_t& limb,
356
                                 core::CollisionValidationPtr_t validation,
357
                                 pinocchio::ConfigurationOut_t configuration,
358
                                 const fcl::Matrix3f& rotationTarget,
359
                                 std::vector<bool> rotationFilter,
360
                                 const fcl::Vec3f& positionTarget,
361
                                 const fcl::Vec3f& normal,
362
                                 const hpp::rbprm::State& current) {
363
  // hppDout(notice,"Project effector : ");
364
  ProjectionReport rep;
365
  // Add constraints to resolve Ik
366
  rep.success_ = false;
367
  rep.result_ = current;
368
  // Add constraints to resolve Ik
369
  hppDout(notice, "Project effector to position : " << positionTarget);
370
  if (body->usePosturalTaskContactCreation()) rotationFilter[2] = false;
371
372
  const pinocchio::Frame effectorFrame =
373
      body->device_->getFrameByName(limb->effector_.name());
374
  pinocchio::JointPtr_t effectorJoint = effectorFrame.joint();
375
  Transform3f localFrame(1), globalFrame(1);
376
  localFrame = effectorFrame.pinocchio().placement * localFrame;
377
  globalFrame.translation(positionTarget);
378
  const constraints::DifferentiableFunctionPtr_t& function =
379
      constraints::Position::create("", body->device_, effectorJoint,
380
                                    localFrame, globalFrame,
381
                                    setTranslationConstraints());
382
  constraints::ComparisonTypes_t comp(function->outputDerivativeSize(),
383
                                      constraints::EqualToZero);
384
  proj->add(constraints::Implicit::create(function, comp));
385
  if (limb->contactType_ == hpp::rbprm::_6_DOF) {
386
    // localFrame.rotation(effectorFrame.pinocchio().placement.rotation() *
387
    // rotationTarget.transpose());
388
    globalFrame.rotation(rotationTarget);
389
    const constraints::DifferentiableFunctionPtr_t& function_ =
390
        constraints::Orientation::create("", body->device_, effectorJoint,
391
                                         localFrame, globalFrame,
392
                                         rotationFilter);
393
    constraints::ComparisonTypes_t comp_(function_->outputDerivativeSize(),
394
                                         constraints::EqualToZero);
395
    proj->add(constraints::Implicit::create(function_, comp_));
396
  }
397
398
  if (body->usePosturalTaskContactCreation()) {
399
    CreatePosturalTaskConstraint(body, proj);
400
    proj->errorThreshold(1e-3);
401
    proj->maxIterations(1000);
402
    proj->lastIsOptional(true);
403
  }
404
405
#ifdef PROFILE
406
  RbPrmProfiler& watch = getRbPrmProfiler();
407
  watch.start("ik");
408
#endif
409
  if (proj->apply(configuration)) {
410
    hppDout(notice, "apply contact constraints");
411
#ifdef PROFILE
412
    watch.stop("ik");
413
#endif
414
#ifdef PROFILE
415
    RbPrmProfiler& watch = getRbPrmProfiler();
416
    watch.start("collision");
417
#endif
418
    hpp::core::ValidationReportPtr_t valRep(
419
        new hpp::core::CollisionValidationReport);
420
    if (validation->validate(configuration, valRep)) {
421
      hppDout(notice, "No collision !");
422
#ifdef PROFILE
423
      watch.stop("collision");
424
#endif
425
      hppDout(notice, "Projection successfull, add new contact info :");
426
      body->device_->currentConfiguration(configuration);
427
      body->device_->computeForwardKinematics();
428
      State tmp(current);
429
      tmp.contacts_[limbId] = true;
430
      tmp.contactPositions_[limbId] =
431
          limb->effector_.currentTransformation().translation();
432
      tmp.contactRotation_[limbId] =
433
          limb->effector_.currentTransformation().rotation();
434
      tmp.contactNormals_[limbId] = normal;
435
      tmp.contactOrder_.push(limbId);
436
      tmp.configuration_ = configuration;
437
      ++tmp.nbContacts;
438
      rep.success_ = true;
439
      rep.result_ = tmp;
440
    } else {
441
#ifdef PROFILE
442
      watch.stop("collision");
443
#endif
444
      hppDout(notice,
445
              "state in collison after projection, report : " << *valRep);
446
      hppDout(notice, "state in collision : r(["
447
                          << pinocchio::displayConfig(configuration) << "])");
448
    }
449
  } else {
450
#ifdef PROFILE
451
    watch.stop("ik");
452
#endif
453
    hppDout(notice, "unable to apply contact constraints");
454
  }
455
  return rep;
456
}
457
458
fcl::Transform3f computeProjectionMatrix(
459
    const hpp::rbprm::RbPrmFullBodyPtr_t& body,
460
    const hpp::rbprm::RbPrmLimbPtr_t& limb,
461
    const pinocchio::ConfigurationIn_t configuration, const fcl::Vec3f& normal,
462
    const fcl::Vec3f& position, const fcl::Matrix3f& rotation) {
463
  // hppDout(notice,"computeProjection matrice : normal =
464
  // "<<normal.transpose());
465
  body->device_->currentConfiguration(configuration);
466
  body->device_->computeForwardKinematics();
467
  // the normal is given by the normal of the contacted object
468
  // hppDout(notice,"effector rot :
469
  // \n"<<limb->effector_.currentTransformation().rotation());
470
  // hppDout(notice,"limb normal : "<<limb->normal_.transpose());
471
  const fcl::Vec3f z =
472
      limb->effector_.currentTransformation().rotation() * limb->normal_;
473
  fcl::Matrix3f rot;
474
  hppDout(notice, "in computeProjectionMatrix, desired rotation = \n"
475
                      << rotation);
476
  if (rotation.isZero(0)) {
477
    // hppDout(notice,"z = "<<z.transpose());
478
    const fcl::Matrix3f alignRotation = tools::GetRotationMatrix(z, normal);
479
    // hppDout(notice,"alignRotation : \n"<<alignRotation);
480
    rot = alignRotation * limb->effector_.currentTransformation().rotation();
481
  } else {
482
    rot = rotation;
483
  }
484
  // hppDout(notice,"rotation : \n"<<rotation);
485
  fcl::Vec3f posOffset = position - rot * limb->offset_;
486
  posOffset = posOffset + normal * epsilon;
487
  hppDout(notice, "in computeProjectionMatrix, rotation used = \n" << rot);
488
  return fcl::Transform3f(rot, posOffset);
489
}
490
491
ProjectionReport projectToObstacle(
492
    core::ConfigProjectorPtr_t proj, const hpp::rbprm::RbPrmFullBodyPtr_t& body,
493
    const std::string& limbId, const hpp::rbprm::RbPrmLimbPtr_t& limb,
494
    core::CollisionValidationPtr_t validation,
495
    pinocchio::ConfigurationOut_t configuration,
496
    const hpp::rbprm::State& current, const fcl::Vec3f& normal,
497
    const fcl::Vec3f& position,
498
    const fcl::Matrix3f& rotation = fcl::Matrix3f::Zero()) {
499
  fcl::Transform3f pM = computeProjectionMatrix(body, limb, configuration,
500
                                                normal, position, rotation);
501
  return projectEffector(proj, body, limbId, limb, validation, configuration,
502
                         pM.getRotation(), setRotationConstraints(),
503
                         pM.getTranslation(), normal, current);
504
}
505
506
// are p1 and p2 on the same side of the line AB ?
507
bool SameSide(const fcl::Vec3f& p1, const fcl::Vec3f& p2, const fcl::Vec3f& a,
508
              const fcl::Vec3f& b) {
509
  fcl::Vec3f cp1 = (b - a).cross(p1 - a);
510
  fcl::Vec3f cp2 = (b - a).cross(p2 - a);
511
  return cp1.dot(cp2) >= 0;
512
}
513
514
// is p inside ABC ?
515
bool PointInTriangle(const fcl::Vec3f& p, const fcl::Vec3f& a,
516
                     const fcl::Vec3f& b, const fcl::Vec3f& c) {
517
  return SameSide(p, a, b, c) && SameSide(p, b, a, c) && SameSide(p, c, a, b);
518
}
519
520
double clamp(const double& val, const double& lo, const double& hi) {
521
  return std::min(std::max(val, lo), hi);
522
}
523
524
fcl::Vec3f closestPointInTriangle(const fcl::Vec3f& sourcePosition,
525
                                  const fcl::Vec3f& t0, const fcl::Vec3f& t1,
526
                                  const fcl::Vec3f& t2,
527
                                  const double epsilon = 0.) {
528
  hppDout(notice, "closestPointInTriangle : t0 = "
529
                      << t0.transpose() << " ; t1 = " << t1.transpose()
530
                      << " ; t2 = " << t2.transpose());
531
  const fcl::Vec3f edge0 = t1 - t0;
532
  const fcl::Vec3f edge1 = t2 - t0;
533
  const fcl::Vec3f v0 = t0 - sourcePosition;
534
535
  double a = edge0.dot(edge0);
536
  double b = edge0.dot(edge1);
537
  double c = edge1.dot(edge1);
538
  double d = edge0.dot(v0);
539
  double e = edge1.dot(v0);
540
541
  double det = a * c - b * b;
542
  double s = b * e - c * d;
543
  double t = b * d - a * e;
544
545
  if (s + t < det) {
546
    if (s < 0.f) {
547
      if (t < 0.f) {
548
        if (d < 0.f) {
549
          s = clamp(-d / a, 0.f, 1.f);
550
          t = 0.f;
551
        } else {
552
          s = 0.f;
553
          t = clamp(-e / c, 0.f, 1.f);
554
        }
555
      } else {
556
        s = 0.f;
557
        t = clamp(-e / c, 0.f, 1.f);
558
      }
559
    } else if (t < 0.f) {
560
      s = clamp(-d / a, 0.f, 1.f);
561
      t = 0.f;
562
    } else {
563
      double invDet = 1.f / det;
564
      s *= invDet;
565
      t *= invDet;
566
    }
567
  } else {
568
    if (s < 0.f) {
569
      double tmp0 = b + d;
570
      double tmp1 = c + e;
571
      if (tmp1 > tmp0) {
572
        double numer = tmp1 - tmp0;
573
        double denom = a - 2 * b + c;
574
        s = clamp(numer / denom, 0.f, 1.f);
575
        t = 1 - s;
576
      } else {
577
        t = clamp(-e / c, 0.f, 1.f);
578
        s = 0.f;
579
      }
580
    } else if (t < 0.f) {
581
      if (a + d > b + e) {
582
        double numer = c + e - b - d;
583
        double denom = a - 2 * b + c;
584
        s = clamp(numer / denom, 0.f, 1.f);
585
        t = 1 - s;
586
      } else {
587
        s = clamp(-e / c, 0.f, 1.f);
588
        t = 0.f;
589
      }
590
    } else {
591
      double numer = c + e - b - d;
592
      double denom = a - 2 * b + c;
593
      s = clamp(numer / denom, 0.f, 1.f);
594
      t = 1.f - s;
595
    }
596
  }
597
598
  fcl::Vec3f res = t0 + s * edge0 + t * edge1;
599
  return res + (res - sourcePosition).normalized() * epsilon;
600
}
601
602
ProjectionReport projectSampleToObstacle(
603
    const hpp::rbprm::RbPrmFullBodyPtr_t& body, const std::string& limbId,
604
    const hpp::rbprm::RbPrmLimbPtr_t& limb,
605
    const sampling::OctreeReport& report,
606
    core::CollisionValidationPtr_t validation,
607
    pinocchio::ConfigurationOut_t configuration,
608
    const hpp::rbprm::State& current) {
609
  sampling::Load(*report.sample_, configuration);
610
  fcl::Vec3f normal = report.normal_;
611
  normal.normalize();
612
  // value_type epsilon = 0.01;
613
  // hppDout(notice,"contact normal = "<<normal);
614
  Transform3f rootT;
615
  if (body->GetLimb(limbId)->limb_->parentJoint())
616
    rootT =
617
        body->GetLimb(limbId)->limb_->parentJoint()->currentTransformation();
618
  else
619
    rootT = body->GetLimb(limbId)->limb_->currentTransformation();
620
  // compute the orthogonal projection of the end effector on the plan :
621
  const fcl::Vec3f pEndEff = (rootT.act(
622
      report.sample_
623
          ->effectorPosition_));  // compute absolute position (in world frame)
624
  fcl::Vec3f pos =
625
      pEndEff - (normal.dot(pEndEff - report.v1_)) *
626
                    normal;  // orthogonal projection on the obstacle surface
627
  hppDout(notice,
628
          "project sample to obstacle : orthogonal projection = " << pos);
629
  // make sure contact pos is actually on triangle, and take 1 cm margin ...
630
  // hppDout(notice,"projectSampleToObstacle,                              pos =
631
  // "<<pos.transpose());
632
  pos = closestPointInTriangle(pEndEff, report.v1_, report.v2_, report.v3_, 0.);
633
  hppDout(
634
      notice,
635
      "project sample to obstacle : after project inside triangle = " << pos);
636
  // pos += normal*epsilon;
637
  // hppDout(notice,"project sample to obstacle : after epsilon = "<<pos);
638
  // hppDout(notice,"projectSampleToObstacle, pos after projection in triangle =
639
  // "<<pos.transpose()); hppDout(notice,"Effector position :
640
  // "<<report.sample_->effectorPosition_); hppDout(notice,"pEndEff =
641
  // ["<<pEndEff[0]<<","<<pEndEff[1]<<","<<pEndEff[2]<<"]"); hppDout(notice,"pos
642
  // = ["<<pos[0]<<","<<pos[1]<<","<<pos[2]<<"]");
643
  core::ConfigProjectorPtr_t proj =
644
      core::ConfigProjector::create(body->device_, "proj", 1e-4, 100);
645
  hpp::tools::LockJointRec(limb->limb_->name(), body->device_->rootJoint(),
646
                           proj);
647
  return projectToObstacle(proj, body, limbId, limb, validation, configuration,
648
                           current, normal, pos);
649
}
650
651
ProjectionReport projectStateToObstacle(
652
    const hpp::rbprm::RbPrmFullBodyPtr_t& body, const std::string& limbId,
653
    const hpp::rbprm::RbPrmLimbPtr_t& limb, const hpp::rbprm::State& current,
654
    const fcl::Vec3f& normal, const fcl::Vec3f& position, bool lockOtherJoints,
655
    const fcl::Matrix3f& rotation) {
656
  // core::CollisionValidationPtr_t dummy =
657
  // core::CollisionValidation::create(body->device_);
658
  return projectStateToObstacle(body, limbId, limb, current, normal, position,
659
                                body->GetCollisionValidation(), lockOtherJoints,
660
                                rotation);
661
}
662
663
ProjectionReport projectStateToObstacle(
664
    const hpp::rbprm::RbPrmFullBodyPtr_t& body, const std::string& limbId,
665
    const hpp::rbprm::RbPrmLimbPtr_t& limb, const hpp::rbprm::State& current,
666
    const fcl::Vec3f& normal, const fcl::Vec3f& position,
667
    core::CollisionValidationPtr_t validation, bool lockOtherJoints,
668
    const fcl::Matrix3f& rotation) {
669
  hpp::rbprm::State state = current;
670
  state.RemoveContact(limbId);
671
  pinocchio::Configuration_t configuration = current.configuration_;
672
  core::ConfigProjectorPtr_t proj =
673
      core::ConfigProjector::create(body->device_, "proj", 1e-4, 1000);
674
  interpolation::addContactConstraints(body, body->device_, proj, state,
675
                                       state.fixedContacts(state));
676
  if (lockOtherJoints) {  // lock all joints expect the ones of the moving limb
677
    hpp::tools::LockJointRec(limb->limb_->name(), body->device_->rootJoint(),
678
                             proj);
679
  }
680
  // get current normal orientation
681
  return projectToObstacle(proj, body, limbId, limb, validation, configuration,
682
                           state, normal, position, rotation);
683
}
684
685
102
ProjectionReport projectToComPosition(hpp::rbprm::RbPrmFullBodyPtr_t fullBody,
686
                                      const fcl::Vec3f& target,
687
                                      const hpp::rbprm::State& currentState) {
688
102
  ProjectionReport res;
689
  core::ConfigProjectorPtr_t proj =
690

306
      core::ConfigProjector::create(fullBody->device_, "proj", 1e-4, 1000);
691
102
  CreateContactConstraints(fullBody, currentState, proj);
692
102
  CreateComPosConstraint(fullBody, target, proj);
693
  /* CreatePosturalTaskConstraint(fullBody,proj);
694
   proj->lastIsOptional(true);
695
   proj->numOptimize(500);
696
   proj->lastAsCost(false);
697
   proj->errorThreshold(1e-3);*/
698
699
204
  pinocchio::Configuration_t configuration = currentState.configuration_;
700

102
  res.success_ = proj->apply(configuration);
701
102
  res.result_ = currentState;
702
102
  res.result_.configuration_ = configuration;
703
204
  return res;
704
}
705
706
std::vector<std::string> extractEffectorsName(const rbprm::T_Limb& limbs) {
707
  std::vector<std::string> res;
708
  for (rbprm::T_Limb::const_iterator cit = limbs.begin(); cit != limbs.end();
709
       ++cit)
710
    res.push_back(cit->first);
711
  return res;
712
}
713
714
ProjectionReport projectToColFreeComPosition(
715
    hpp::rbprm::RbPrmFullBodyPtr_t fullBody, const fcl::Vec3f& target,
716
    const hpp::rbprm::State& currentState) {
717
  ProjectionReport res, tmp;
718
  core::ConfigProjectorPtr_t proj =
719
      core::ConfigProjector::create(fullBody->device_, "proj", 1e-3, 1000);
720
  CreateContactConstraints(fullBody, currentState, proj);
721
  CreateComPosConstraint(fullBody, target, proj);
722
  CreatePosturalTaskConstraint(fullBody, proj);
723
  proj->lastIsOptional(true);
724
  // proj->numOptimize(500);
725
  proj->maxIterations(500);
726
  // proj->lastAsCost(true);
727
  proj->errorThreshold(1e-2);
728
729
  pinocchio::Configuration_t configuration = currentState.configuration_;
730
  res.success_ = proj->apply(configuration);
731
  res.result_ = currentState;
732
  res.result_.configuration_ = configuration;
733
  hppDout(notice,
734
          "Project to col free, first projection done : " << res.success_);
735
  hppDout(notice,
736
          "projected state : " << pinocchio::displayConfig(configuration));
737
  if (res.success_) {
738
    std::vector<std::string> effNames(
739
        extractEffectorsName(fullBody->GetLimbs()));
740
    std::vector<std::string> freeLimbs =
741
        rbprm::freeEffectors(currentState, effNames.begin(), effNames.end());
742
    for (std::vector<std::string>::const_iterator cit = freeLimbs.begin();
743
         cit != freeLimbs.end() && res.success_; ++cit) {
744
      hppDout(notice, "free effector in projection : " << *cit);
745
      tmp = projection::setCollisionFree(
746
          fullBody, fullBody->GetLimbCollisionValidation().at(*cit), *cit,
747
          res.result_);
748
      if (!tmp.success_) res.success_ = false;
749
    }
750
  }
751
  hppDout(notice,
752
          "project to col free, set coll free success = " << res.success_);
753
  if (res.success_) {
754
    res.success_ = proj->apply(configuration);
755
    res.result_.configuration_ = configuration;
756
    if (res.success_) {
757
      ValidationReportPtr_t report(
758
          ValidationReportPtr_t(new CollisionValidationReport));
759
      res.success_ =
760
          fullBody->GetCollisionValidation()->validate(configuration, report);
761
      hppDout(notice, "project to col free, collision test : " << res.success_);
762
      if (!res.success_) {
763
        CollisionValidationReportPtr_t repCast =
764
            dynamic_pointer_cast<CollisionValidationReport>(report);
765
        hppDout(notice, "collision between " << repCast->object1->name()
766
                                             << " and "
767
                                             << repCast->object2->name());
768
      }
769
    }
770
  }
771
  return res;
772
}
773
774
}  // namespace projection
775
}  // namespace rbprm
776
}  // namespace hpp