simple-time-parameterization.cc 6.58 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Copyright (c) 2017, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-core.
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/core/path-optimization/simple-time-parameterization.hh>

19
20
#include <limits>

21
22
23
24
25
26
27
28
#include <pinocchio/multibody/model.hpp>
#include <hpp/pinocchio/configuration.hh>
#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/liegroup.hh>
#include <hpp/core/interpolated-path.hh>
#include <hpp/core/path-vector.hh>
#include <hpp/core/problem.hh>
#include <hpp/core/straight-path.hh>
29
#include <hpp/core/time-parameterization/polynomial.hh>
30
31
32
33

namespace hpp {
  namespace core {
    namespace pathOptimization {
34
35
36
37
38
39
40
41
42
43
44
      using timeParameterization::Polynomial;

      namespace {
        TimeParameterizationPtr_t computeTimeParameterizationFirstOrder (
            const value_type& s0, const value_type& s1, const value_type& B,
            value_type& T) 
        {
          vector_t a(2);
          T = (s1 - s0) / B;
          a[0] = s0;
          a[1] = B;
45
46
          hppDout (info, "Time parametrization returned " << a.transpose()
              << ", " << T);
47
48
49
50
51
52
53
54
          return TimeParameterizationPtr_t (new Polynomial (a));
        }

        TimeParameterizationPtr_t computeTimeParameterizationThirdOrder (
            const value_type& s0, const value_type& s1, const value_type& B,
            value_type& T) 
        {
          vector_t a(4);
55
          T = 3 * (s1 - s0) / (2 * B);
56
57
58
59
          a[0] = s0;
          a[1] = 0;
          a[2] = 3 * (s1 - s0) / (T * T);
          a[3] = - 2 * a[2] / (3 * T);
60
61
          hppDout (info, "Time parametrization returned " << a.transpose()
              << ", " << T);
62
63
          return TimeParameterizationPtr_t (new Polynomial (a));
        }
64
65
66
67
68
69
70
71
72
73
74

        void checkTimeParameterization (const TimeParameterizationPtr_t tp,
            const bool velocity, const interval_t sr, const value_type B, const value_type T)
        {
          using std::fabs;
          const value_type thr = Eigen::NumTraits<value_type>::dummy_precision();
          if (   fabs(tp->value(0) - sr.first) >= thr
              || fabs(tp->value(T) - sr.second) >= thr) {
            throw std::logic_error("Boundaries of TimeParameterization are not correct.");
          }
          if (velocity
75
76
77
              && (fabs(tp->derivative(0)) > thr
              ||  fabs(tp->derivative(T)) > thr
              ||  fabs(tp->derivative(T/2) - B) > thr)
78
             ) {
79
80
81
82
83
84
85
86
            HPP_THROW(std::logic_error,
                "Derivative of TimeParameterization are not correct:"
                << "\ntp->derivative(0) = " << tp->derivative(0)
                << "\ntp->derivative(T) = " << tp->derivative(T)
                << "\ntp->derivative(T/2) - B = " << tp->derivative(T/2) - B
                << "\nT = " << T
                << "\nB = " << B
                );
87
88
          }
        }
89
90
      }

91
92
93
94
95
96
97
98
      SimpleTimeParameterizationPtr_t SimpleTimeParameterization::create (const Problem& problem)
      {
        SimpleTimeParameterizationPtr_t ptr (new SimpleTimeParameterization(problem));
        return ptr;
      }

      PathVectorPtr_t SimpleTimeParameterization::optimize (const PathVectorPtr_t& path)
      {
99
100
        const value_type infinity = std::numeric_limits<value_type>::infinity();

101
        const value_type safety = problem().getParameter("SimpleTimeParameterization/safety", (value_type)1);
102
        const bool velocity = problem().getParameter("SimpleTimeParameterization/velocity", false);
103
104
105
106
107
108

        // Retrieve velocity limits
        const DevicePtr_t& robot = problem().robot();
        vector_t ub ( robot->model().velocityLimit),
                 lb (-robot->model().velocityLimit),
                 cb ((ub + lb) / 2);
Joseph Mirabel's avatar
Joseph Mirabel committed
109
110
        assert (cb.size() + robot->extraConfigSpace().dimension()
            == robot->numberDof());
111
112
113
114
115

        // The velocity must be in [lb, ub]
        ub = cb + safety * (ub - cb);
        lb = cb + safety * (lb - cb);

116
        // When ub or lb are NaN, set them to infinity.
117
118
        ub = (ub.array() == ub.array()).select(ub,  infinity);
        lb = (lb.array() == lb.array()).select(lb, -infinity);
119

120
121
122
123
124
125
126
127
128
129
130
131
132
        hppDout (info, "Lower velocity bound :" << lb.transpose());
        hppDout (info, "Upper velocity bound :" << ub.transpose());

        if (   ( ub.array() <= 0 ).any()
            && ( lb.array() >= 0 ).any())
          throw std::invalid_argument ("The case where zero is not an admissible velocity is not implemented.");

        PathVectorPtr_t input = PathVector::create(
            path->outputSize(), path->outputDerivativeSize());
        PathVectorPtr_t output = PathVector::create(
            path->outputSize(), path->outputDerivativeSize());
        path->flatten(input);

133
134
        vector_t v (robot->numberDof());
        vector_t v_inv (robot->numberDof());
135
136
        for (std::size_t i = 0; i < input->numberPaths(); ++i) {
          PathPtr_t p = input->pathAtRank(i);
137
          interval_t paramRange = p->paramRange();
138
139
140
141
142
143
144

          // Compute B
          p->velocityBound (v, paramRange.first, paramRange.second);
          v_inv = (v.array() == 0).select(infinity, v.cwiseInverse());
          const value_type B = std::min(
              ( ub.cwiseProduct(v_inv)).minCoeff(),
              (-lb.cwiseProduct(v_inv)).minCoeff());
145
          assert (B > 0);
146
147
148
149
150
151
152
153
154

          // Compute the polynom and total time
          value_type T;
          TimeParameterizationPtr_t tp;
          if (velocity)
            tp = computeTimeParameterizationThirdOrder (paramRange.first, paramRange.second, B, T);
          else
            tp = computeTimeParameterizationFirstOrder (paramRange.first, paramRange.second, B, T);

155
156
          checkTimeParameterization (tp, velocity, paramRange, B, T);

157
158
          PathPtr_t pp = p->copy();
          pp->timeParameterization (tp, interval_t (0, T));
159
160

          output->appendPath (pp);
161
162
163
164
165
166
167
168
169
        }
        return output;
      }

      SimpleTimeParameterization::SimpleTimeParameterization (const Problem& problem):
        PathOptimizer(problem) {}
    } // namespace pathOptimization
  } // namespace core
} // namespace hpp