simple-time-parameterization.cc 9.69 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
      using timeParameterization::Polynomial;

      namespace {
        TimeParameterizationPtr_t computeTimeParameterizationFirstOrder (
            const value_type& s0, const value_type& s1, const value_type& B,
39
            value_type& T)
40
41
42
43
44
        {
          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
          return TimeParameterizationPtr_t (new Polynomial (a));
        }

        TimeParameterizationPtr_t computeTimeParameterizationThirdOrder (
            const value_type& s0, const value_type& s1, const value_type& B,
52
            value_type& T)
53
54
        {
          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
        TimeParameterizationPtr_t computeTimeParameterizationFifthOrder (
            const value_type& s0, const value_type& s1, const value_type& B,
67
            const value_type& C, value_type& T)
68
69
        {
          vector_t a(6);
70
71
72
73
74
75
76
77
78
          if (C > 0) {
            T = std::max(
                15 * (s1 - s0) / (8 * B)                     , // Velocity limit
                sqrt((10./std::sqrt(3))) * sqrt((s1 - s0) / C) // Acceleration limit
                );
          } else {
            T = 15 * (s1 - s0) / (8 * B);
          }

79
80
81
82
83
84
85
86
87
88
89
90
91
92
          value_type Tpow = T*T*T;
          a[0] = s0;
          a[1] = 0;
          a[2] = 0;
          a[3] =  10 * (s1 - s0) / Tpow;
          Tpow *= T;
          a[4] = -15 * (s1 - s0) / Tpow;
          Tpow *= T;
          a[5] =   6 * (s1 - s0) / Tpow;
          hppDout (info, "Time parametrization returned " << a.transpose()
              << ", " << T);
          return TimeParameterizationPtr_t (new Polynomial (a));
        }

93
        void checkTimeParameterization (const TimeParameterizationPtr_t tp,
94
            const size_type order, const interval_t sr, const value_type B, const value_type& C, const value_type T)
95
96
        {
          using std::fabs;
97
          const value_type thr = std::sqrt(Eigen::NumTraits<value_type>::dummy_precision());
98
99
100
101
          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.");
          }
102
          if (order >= 1
103
104
              && (fabs(tp->derivative(0, 1)) > thr
              ||  fabs(tp->derivative(T, 1)) > thr
105
              ||  ((C <= 0) && fabs(tp->derivative(T/2, 1) - B) > thr))
106
             ) {
107
108
            HPP_THROW(std::logic_error,
                "Derivative of TimeParameterization are not correct:"
109
110
111
                << "\ntp->derivative(0, 1) = " << tp->derivative(0, 1)
                << "\ntp->derivative(T, 1) = " << tp->derivative(T, 1)
                << "\ntp->derivative(T/2, 1) - B = " << tp->derivative(T/2, 1) - B
112
113
                << "\nT = " << T
                << "\nB = " << B
114
                << "\nC = " << C
115
                );
116
          }
117
118
119
120
121
122
123
124
125
126
127
          if (order >= 2
              && (fabs(tp->derivative(0, 2)) > thr
              ||  fabs(tp->derivative(T, 2)) > thr)
             ) {
            HPP_THROW(std::logic_error,
                "Derivative of TimeParameterization are not correct:"
                << "\ntp->derivative(0, 2) = " << tp->derivative(0, 2)
                << "\ntp->derivative(T, 2) = " << tp->derivative(T, 2)
                << "\nT = " << T
                );
          }
128
        }
129
130
      }

131
132
133
134
135
136
137
138
      SimpleTimeParameterizationPtr_t SimpleTimeParameterization::create (const Problem& problem)
      {
        SimpleTimeParameterizationPtr_t ptr (new SimpleTimeParameterization(problem));
        return ptr;
      }

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

141
142
        const value_type safety = problem().getParameter("SimpleTimeParameterization/safety").floatValue();
        const size_type order = problem().getParameter("SimpleTimeParameterization/order").intValue();
143
144
145
146
        const value_type maxAcc = problem().getParameter("SimpleTimeParameterization/maxAcceleration").floatValue();
        if (order <= 1 && maxAcc) {
          throw std::invalid_argument ("Maximum acceleration cannot be set when order is <= to 1. Please set parameter SimpleTimeParameterization/maxAcceleration to a negative value.");
        }
147
148
149
150
151
152

        // 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
153
154
        assert (cb.size() + robot->extraConfigSpace().dimension()
            == robot->numberDof());
155
156
157
158
159

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

160
        // When ub or lb are NaN, set them to infinity.
161
162
        ub = (ub.array() == ub.array()).select(ub,  infinity);
        lb = (lb.array() == lb.array()).select(lb, -infinity);
163

164
165
166
167
168
169
170
171
172
173
174
175
176
        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);

177
178
        vector_t v (robot->numberDof());
        vector_t v_inv (robot->numberDof());
179
180
        for (std::size_t i = 0; i < input->numberPaths(); ++i) {
          PathPtr_t p = input->pathAtRank(i);
181
          interval_t paramRange = p->paramRange();
182
183
184
185
186
187
188

          // 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());
189
          assert (B > 0);
190
191
192
193

          // Compute the polynom and total time
          value_type T;
          TimeParameterizationPtr_t tp;
194
195
196
197
198
199
200
201
          switch (order) {
            case 0:
              tp = computeTimeParameterizationFirstOrder (paramRange.first, paramRange.second, B, T);
              break;
            case 1:
              tp = computeTimeParameterizationThirdOrder (paramRange.first, paramRange.second, B, T);
              break;
            case 2:
202
              tp = computeTimeParameterizationFifthOrder (paramRange.first, paramRange.second, B, maxAcc, T);
203
204
205
206
207
              break;
            default:
              throw std::invalid_argument ("Parameter SimpleTimeParameterization/order should be in { 0, 1, 2 }");
              break;
          }
208

209
          checkTimeParameterization (tp, order, paramRange, B, maxAcc, T);
210

211
212
          PathPtr_t pp = p->copy();
          pp->timeParameterization (tp, interval_t (0, T));
213
214

          output->appendPath (pp);
215
216
217
218
219
220
        }
        return output;
      }

      SimpleTimeParameterization::SimpleTimeParameterization (const Problem& problem):
        PathOptimizer(problem) {}
221
222
223
224
225
226
227
228
229
230
231
232

      // ----------- Declare parameters ------------------------------------- //

      HPP_START_PARAMETER_DECLARATION(SimpleTimeParameterization)
      Problem::declareParameter(ParameterDescription (Parameter::FLOAT,
            "SimpleTimeParameterization/safety",
            "A scaling factor for the joint bounds.",
            Parameter(1.)));
      Problem::declareParameter(ParameterDescription (Parameter::INT,
            "SimpleTimeParameterization/order",
            "The desired continuity order.",
            Parameter((size_type)0)));
233
234
235
236
      Problem::declareParameter(ParameterDescription (Parameter::FLOAT,
            "SimpleTimeParameterization/maxAcceleration",
            "The maximum acceleration for each degree of freedom. Not considered if negative.",
            Parameter((value_type)-1)));
237
      HPP_END_PARAMETER_DECLARATION(SimpleTimeParameterization)
238
239
240
    } // namespace pathOptimization
  } // namespace core
} // namespace hpp