GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/hpp/rbprm/interpolation/time-constraint-helper.inl Lines: 0 125 0.0 %
Date: 2024-02-02 12:21:48 Branches: 0 166 0.0 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2014 CNRS
3
// Authors: Steve Tonneau (steve.tonneau@laas.fr)
4
//
5
// This file is part of hpp-rbprm.
6
// hpp-rbprm 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-rbprm 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
#ifndef HPP_RBPRM_TIME_CONSTRAINT_HELPER_UTILS_HH
20
#define HPP_RBPRM_TIME_CONSTRAINT_HELPER_UTILS_HH
21
22
#include <hpp/constraints/generic-transformation.hh>
23
#include <hpp/core/bi-rrt-planner.hh>
24
#include <hpp/core/constraint-set.hh>
25
#include <hpp/core/path-optimization/partial-shortcut.hh>
26
#include <hpp/core/path-optimization/random-shortcut.hh>
27
#include <hpp/core/problem-target/goal-configurations.hh>
28
#include <hpp/core/roadmap.hh>
29
#include <hpp/core/steering-method/straight.hh>
30
#include <hpp/rbprm/interpolation/limb-rrt-shooter.hh>
31
#include <hpp/rbprm/interpolation/time-constraint-path-validation.hh>
32
#include <hpp/rbprm/interpolation/time-constraint-utils.hh>
33
#include <hpp/rbprm/interpolation/time-dependant.hh>
34
// #include <hpp/constraints/position.hh>
35
// #include <hpp/constraints/orientation.hh>
36
#include <hpp/constraints/locked-joint.hh>
37
#include <hpp/core/config-projector.hh>
38
#include <hpp/core/path-vector.hh>
39
#include <hpp/core/subchain-path.hh>
40
#include <hpp/pinocchio/joint.hh>
41
// #include <hpp/pinocchio/object-factory.hh>
42
#include <hpp/constraints/relative-com.hh>
43
#include <hpp/constraints/symbolic-calculus.hh>
44
#include <hpp/constraints/symbolic-function.hh>
45
#include <hpp/pinocchio/configuration.hh>
46
#include <hpp/rbprm/tools.hh>
47
#include <vector>
48
namespace hpp {
49
using namespace core;
50
namespace rbprm {
51
namespace interpolation {
52
53
namespace {
54
inline std::vector<bool> setMaintainRotationConstraints() {
55
  std::vector<bool> res;
56
  for (std::size_t i = 0; i < 3; ++i) res.push_back(true);
57
  return res;
58
}
59
}  // namespace
60
61
template <class Path_T, class ShooterFactory_T, typename ConstraintFactory_T>
62
void TimeConstraintHelper<Path_T, ShooterFactory_T,
63
                          ConstraintFactory_T>::InitConstraints() {
64
  core::ConstraintSetPtr_t cSet =
65
      core::ConstraintSet::create(rootProblem_->robot(), "");
66
  cSet->addConstraint(proj_);
67
  rootProblem_->constraints(cSet);
68
}
69
70
template <class Path_T, class ShooterFactory_T, typename ConstraintFactory_T>
71
void TimeConstraintHelper<Path_T, ShooterFactory_T, ConstraintFactory_T>::
72
    SetConfigShooter(const hpp::rbprm::State& from,
73
                     const hpp::rbprm::State& to) {
74
  rootProblem_->configurationShooter(
75
      shooterFactory_(fullbody_, refPath_, fullBodyDevice_->configSize() - 1,
76
                      from, to, steeringMethod_->tds_, proj_));
77
}
78
79
namespace {
80
inline std::vector<std::string> extractEffectorsName(
81
    const rbprm::T_Limb& limbs) {
82
  std::vector<std::string> res;
83
  for (rbprm::T_Limb::const_iterator cit = limbs.begin(); cit != limbs.end();
84
       ++cit) {
85
    res.push_back(cit->first);
86
  }
87
  return res;
88
}
89
90
inline void DisableUnNecessaryCollisions(core::Problem& problem,
91
                                         rbprm::RbPrmLimbPtr_t limb) {
92
  // TODO should we really disable collisions for other bodies ?
93
  tools::RemoveNonLimbCollisionRec<core::Problem>(
94
      problem.robot()->rootJoint(),
95
      //"all",
96
      limb->limb_->name(), problem.collisionObstacles(), problem);
97
98
  if (limb->disableEndEffectorCollision_) {
99
    hpp::tools::RemoveEffectorCollision<core::Problem>(
100
        problem, problem.robot()->getJointByName(limb->effector_.name()),
101
        problem.collisionObstacles());
102
  }
103
}
104
105
inline void DisableUnNecessaryCollisions(
106
    core::Problem& problem, const std::vector<std::string>& variations,
107
    const rbprm::T_Limb& limbs) {
108
  std::vector<std::string> jointNamesVariations;
109
  for (std::vector<std::string>::const_iterator cit = variations.begin();
110
       cit != variations.end(); ++cit) {
111
    rbprm::RbPrmLimbPtr_t limb = limbs.at(*cit);
112
    jointNamesVariations.push_back(limb->limb_->name());
113
    if (limb->disableEndEffectorCollision_) {
114
      hpp::tools::RemoveEffectorCollision<core::Problem>(
115
          problem, problem.robot()->getJointByName(limb->effector_.name()),
116
          problem.collisionObstacles());
117
    }
118
  }
119
  // TODO should we really disable collisions for other bodies ?
120
  tools::RemoveNonLimbCollisionRec<core::Problem>(
121
      problem.robot()->rootJoint(), jointNamesVariations,
122
      problem.collisionObstacles(), problem);
123
}
124
125
inline core::PathPtr_t generateRootPath(const core::Problem& problem,
126
                                        const State& from, const State& to) {
127
  core::Configuration_t startRootConf(from.configuration_);
128
  core::Configuration_t endRootConf(to.configuration_);
129
  return (*(problem.steeringMethod()))(startRootConf, endRootConf);
130
}
131
}  // namespace
132
133
template <class Path_T, class Shooter_T, typename ConstraintFactory_T>
134
PathVectorPtr_t
135
TimeConstraintHelper<Path_T, Shooter_T, ConstraintFactory_T>::Run(
136
    const State& from, const State& to, const size_t maxIterations) {
137
  PathVectorPtr_t res;
138
  SetPathValidation(*this);
139
  const rbprm::T_Limb& limbs = fullbody_->GetLimbs();
140
  // get limbs that moved
141
  std::vector<std::string> variations =
142
      to.allVariations(from, extractEffectorsName(limbs));
143
  if (!variations.empty()) {
144
    DisableUnNecessaryCollisions(*rootProblem_, variations, limbs);
145
  }
146
  // TODO IS THIS REDUNDANT ?
147
  /*for(rbprm::CIT_Limb lit = limbs.begin(); lit != limbs.end(); ++lit)
148
  {
149
      if(lit->second->disableEndEffectorCollision_ &&
150
  std::find(variations.begin(), variations.end(), lit->second->limb_->name()) ==
151
  variations.end())
152
      {
153
          hpp::tools::RemoveEffectorCollision<core::Problem>(rootProblem_,
154
                                                             rootProblem_->robot()->getJointByName(lit->second->effector_->name()),
155
                                                             rootProblem_->collisionObstacles());
156
      }
157
  }*/
158
  SetConfigShooter(from, to);
159
160
  ConfigurationPtr_t start = TimeConfigFromDevice(*this, from, 0.);
161
  ConfigurationPtr_t end = TimeConfigFromDevice(*this, to, 1.);
162
  hppDout(notice, "Run : start config = r([" << pinocchio::displayConfig(*start)
163
                                             << "])");
164
  hppDout(notice,
165
          "Run : end   config = r([" << pinocchio::displayConfig(*end) << "])");
166
167
  rootProblem_->initConfig(start);
168
  BiRRTPlannerPtr_t planner = BiRRTPlanner::create(rootProblem_);
169
  // ProblemTargetPtr_t target = problemTarget::GoalConfigurations::create
170
  // (planner);
171
  ProblemTargetPtr_t target =
172
      problemTarget::GoalConfigurations::create(rootProblem_);
173
  rootProblem_->target(target);
174
  rootProblem_->addGoalConfig(end);
175
  InitConstraints();
176
  if (maxIterations > 0) planner->maxIterations(maxIterations);
177
  hppDout(notice, "Max iterations : " << maxIterations);
178
  boost::posix_time::ptime timeStart(
179
      boost::posix_time::microsec_clock::universal_time());
180
  try {
181
    res = planner->solve();
182
    hppDout(notice,
183
            "TimeConstraintHelper : solved in "
184
                << ((boost::posix_time::microsec_clock::universal_time() -
185
                     timeStart)
186
                        .total_milliseconds())
187
                << " ms");
188
    hppDout(notice, "With a roadmap of " << planner->roadmap()->nodes().size()
189
                                         << " nodes");
190
  } catch (std::runtime_error e) {
191
    hppDout(notice,
192
            "TimeConstraintHelper : planner returned an error : " << e.what());
193
    res = PathVectorPtr_t();
194
  } catch (core::projection_error e) {
195
    hppDout(notice, "TimeConstraintHelper : Projection error : " << e.what());
196
    res = PathVectorPtr_t();
197
  }
198
199
  rootProblem_->resetGoalConfigs();
200
  return res;
201
}
202
203
namespace {
204
template <class Helper_T>
205
PathVectorPtr_t optimize(Helper_T& helper, PathVectorPtr_t partialPath,
206
                         const std::size_t numOptimizations) {
207
  core::pathOptimization::RandomShortcutPtr_t rs =
208
      core::pathOptimization::RandomShortcut::create(helper.rootProblem_);
209
  for (std::size_t j = 0; j < numOptimizations; ++j) {
210
    hppDout(notice, "Optimize random shortucut, iter : " << j);
211
    partialPath = rs->optimize(partialPath);
212
  }
213
  core::pathOptimization::PartialShortcutPtr_t rs2 =
214
      core::pathOptimization::PartialShortcut::create(helper.rootProblem_);
215
  for (std::size_t j = 0; j < numOptimizations; ++j) {
216
    hppDout(notice, "Optimize partial shortcut, iter : " << j);
217
    partialPath = rs2->optimize(partialPath);
218
  }
219
  return partialPath;
220
}
221
222
inline std::size_t checkPath(const std::size_t& distance, bool valid[]) {
223
  std::size_t numValid(distance);
224
  for (std::size_t i = 0; i < distance; ++i) {
225
    if (!valid[i]) {
226
      numValid = i;
227
      break;
228
    }
229
  }
230
  // if (numValid==0)
231
  //     throw std::runtime_error("No path found at state 0");
232
  /*else */ if (numValid != distance) {
233
    std::cout << "No path found at state " << numValid << std::endl;
234
  }
235
  return numValid;
236
}
237
238
inline PathPtr_t ConcatenateAndResizePath(PathVectorPtr_t res[],
239
                                          std::size_t numValid,
240
                                          const bool keepExtraDof,
241
                                          hpp::pinocchio::DevicePtr_t device) {
242
  PathVectorPtr_t completePath = res[0];
243
  for (std::size_t i = 1; i < numValid; ++i) {
244
    completePath->concatenate(res[i]);
245
  }
246
  PathVectorPtr_t flat = core::PathVector::create(
247
      completePath->outputSize(), completePath->outputDerivativeSize());
248
  completePath->flatten(
249
      flat);  // assure that there is no pathVector inside a pathVector
250
  hppDout(notice,
251
          "end of interpolateStatesFromPath, number of paths in pathVector : "
252
              << flat->numberPaths());
253
  if (keepExtraDof) {
254
    return flat;
255
  } else {
256
    // reducing path (remove last value of the configuration)
257
    core::segment_t interval(0, flat->initial().rows() - 1);
258
    core::segments_t intervals;
259
    intervals.push_back(interval);
260
    core::segments_t velIntervals(1,
261
                                  core::segment_t(0, device->numberDof() - 1));
262
    PathVectorPtr_t reducedPV = core::PathVector::create(
263
        flat->outputSize() - 1, flat->outputDerivativeSize() - 1);
264
    for (std::size_t pid = 0; pid < flat->numberPaths(); ++pid) {
265
      reducedPV->appendPath(core::SubchainPath::create(
266
          flat->pathAtRank(pid), intervals, velIntervals));
267
    }
268
    return reducedPV;
269
  }
270
}
271
}  // namespace
272
273
struct GenPath {
274
  GenPath(const core::Problem& problem) : problem_(problem) {}
275
  ~GenPath() {}
276
  PathPtr_t operator()(const CIT_State& from, const CIT_State& to) const {
277
    return interpolation::generateRootPath(problem_, *from, *to);
278
  }
279
  const core::Problem& problem_;
280
};
281
282
struct ExtractPath {
283
  ExtractPath(PathPtr_t refPath) : refPath_(refPath) {}
284
  ~ExtractPath() {}
285
  PathPtr_t operator()(const CIT_StateFrame& from, CIT_StateFrame& to) const {
286
    return refPath_->extract(core::interval_t(from->first, to->first));
287
  }
288
  PathPtr_t refPath_;
289
};
290
291
inline const State& get(const CIT_StateFrame& from) { return from->second; }
292
293
inline const State& get(const CIT_State& from) { return *from; }
294
295
template <class Helper_T, class StateIterator_T, class ShooterFactory_T,
296
          typename ConstraintFactory_T, class PathGetter_T>
297
PathPtr_t interpolateStatesFromPathGetter(
298
    RbPrmFullBodyPtr_t fullbody, core::ProblemPtr_t referenceProblem,
299
    const ShooterFactory_T& shooterFactory,
300
    const ConstraintFactory_T& constraintFactory,
301
    const PathGetter_T& pathGetter, const StateIterator_T& startState,
302
    const StateIterator_T& endState, const std::size_t numOptimizations,
303
    const bool keepExtraDof = false,
304
    const pinocchio::value_type error_treshold = 0.001,
305
    const size_t maxIterations = 0) {
306
  hppDout(notice, "Begin interpolateStatesFromPathGetter :");
307
  pinocchio::Computation_t flag = fullbody->device_->computationFlag();
308
  pinocchio::Computation_t newflag = static_cast<pinocchio::Computation_t>(
309
      pinocchio::JOINT_POSITION | pinocchio::JACOBIAN | pinocchio::COM);
310
  fullbody->device_->controlComputation(newflag);
311
  PathVectorPtr_t res[100];
312
  bool valid[100];
313
  std::size_t distance = std::distance(startState, endState);
314
  assert(distance < 100);
315
  // treat each interpolation between two states separatly
316
  // in a different thread
317
  hppDout(notice, "InterpolateStates from path : distance = " << distance);
318
  std::size_t numValid;
319
  do {
320
#pragma omp parallel for
321
    for (std::size_t i = 0; i < distance; ++i) {
322
      StateIterator_T a, b;
323
      a = (startState + i);
324
      b = (startState + i + 1);
325
      Helper_T helper(fullbody, shooterFactory, constraintFactory,
326
                      referenceProblem, pathGetter(a, b),
327
                      error_treshold);  // 0.1 : error
328
      helper.SetConstraints(get(a), get(b));
329
      hppDout(notice, "Start helper.run :");
330
      PathVectorPtr_t partialPath = helper.Run(get(a), get(b), maxIterations);
331
      hppDout(notice, "helper.run done.");
332
      if (partialPath) {
333
        res[i] = optimize(helper, partialPath, numOptimizations);
334
        valid[i] = true;
335
      } else {
336
        hppDout(notice,
337
                "InterpolateStates : helper.run returned an empty path");
338
        valid[i] = false;
339
      }
340
    }
341
    numValid = checkPath(distance, valid);
342
  } while (numValid < distance);
343
344
  fullbody->device_->controlComputation(flag);
345
  return ConcatenateAndResizePath(res, numValid, keepExtraDof,
346
                                  fullbody->device_);
347
}
348
349
template <class Helper_T, class ShooterFactory_T, typename ConstraintFactory_T>
350
PathPtr_t interpolateStatesFromPath(
351
    RbPrmFullBodyPtr_t fullbody, core::ProblemPtr_t referenceProblem,
352
    const ShooterFactory_T& shooterFactory,
353
    const ConstraintFactory_T& constraintFactory, const PathPtr_t refPath,
354
    const CIT_StateFrame& startState, const CIT_StateFrame& endState,
355
    const std::size_t numOptimizations, const bool keepExtraDof,
356
    const value_type error_treshold, const size_t maxIterations) {
357
  ExtractPath extractPath(refPath);
358
  return interpolateStatesFromPathGetter<Helper_T, CIT_StateFrame,
359
                                         ShooterFactory_T, ConstraintFactory_T,
360
                                         ExtractPath>(
361
      fullbody, referenceProblem, shooterFactory, constraintFactory,
362
      extractPath, startState, endState, numOptimizations, keepExtraDof,
363
      error_treshold, maxIterations);
364
}
365
366
template <class Helper_T, class ShooterFactory_T, typename ConstraintFactory_T,
367
          typename StateConstIterator>
368
PathPtr_t interpolateStates(
369
    RbPrmFullBodyPtr_t fullbody, core::ProblemPtr_t referenceProblem,
370
    const ShooterFactory_T& shooterFactory,
371
    const ConstraintFactory_T& constraintFactory,
372
    const StateConstIterator& startState, const StateConstIterator& endState,
373
    const std::size_t numOptimizations, const bool keepExtraDof,
374
    const value_type error_treshold, const size_t maxIterations) {
375
  GenPath genPath(*referenceProblem);
376
  return interpolateStatesFromPathGetter<Helper_T, StateConstIterator,
377
                                         ShooterFactory_T, ConstraintFactory_T,
378
                                         GenPath>(
379
      fullbody, referenceProblem, shooterFactory, constraintFactory, genPath,
380
      startState, endState, numOptimizations, keepExtraDof, error_treshold,
381
      maxIterations);
382
}
383
384
}  // namespace interpolation
385
}  // namespace rbprm
386
}  // namespace hpp
387
388
#endif  // HPP_RBPRM_TIME_CONSTRAINT_HELPER_UTILS_HH