quintic_spline_segment.h
Go to the documentation of this file.
1 // Copyright (C) 2013, PAL Robotics S.L.
3 // Copyright (c) 2008, Willow Garage, Inc.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of PAL Robotics S.L. nor the names of its
13 // contributors may be used to endorse or promote products derived from
14 // this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
28 
30 
31 #ifndef TRAJECTORY_INTERFACE_QUINTIC_SPLINE_SEGMENT_H
32 #define TRAJECTORY_INTERFACE_QUINTIC_SPLINE_SEGMENT_H
33 
34 #include <iterator>
35 #include <stdexcept>
36 
37 #include <boost/array.hpp>
38 #include <boost/foreach.hpp>
39 
41 
42 namespace trajectory_interface
43 {
44 
50 template<class ScalarType>
52 {
53 public:
54  typedef ScalarType Scalar;
55  typedef Scalar Time;
57 
65  : coefs_(),
66  duration_(static_cast<Scalar>(0)),
67  start_time_(static_cast<Scalar>(0))
68  {}
69 
76  QuinticSplineSegment(const Time& start_time,
77  const State& start_state,
78  const Time& end_time,
79  const State& end_state)
80  {
81  init(start_time, start_state, end_time, end_state);
82  }
83 
104  void init(const Time& start_time,
105  const State& start_state,
106  const Time& end_time,
107  const State& end_state);
108 
118  void sample(const Time& time, State& state) const
119  {
120  // Resize state data. Should be a no-op if appropriately sized
121  state.position.resize(coefs_.size());
122  state.velocity.resize(coefs_.size());
123  state.acceleration.resize(coefs_.size());
124 
125  // Sample each dimension
126  typedef typename std::vector<SplineCoefficients>::const_iterator ConstIterator;
127  for(ConstIterator coefs_it = coefs_.begin(); coefs_it != coefs_.end(); ++coefs_it)
128  {
129  const typename std::vector<Scalar>::size_type id = std::distance(coefs_.begin(), coefs_it);
130  sampleWithTimeBounds(*coefs_it,
131  duration_, (time - start_time_),
132  state.position[id], state.velocity[id], state.acceleration[id]);
133  }
134  }
135 
137  Time startTime() const {return start_time_;}
138 
140  Time endTime() const {return start_time_ + duration_;}
141 
143  unsigned int size() const {return coefs_.size();}
144 
145 private:
146  typedef boost::array<Scalar, 6> SplineCoefficients;
147 
152  std::vector<SplineCoefficients> coefs_;
153  Time duration_;
155 
156  // These methods are borrowed from the previous controller's implementation
157  // TODO: Clean their implementation, use the Horner algorithm for more numerically stable polynomial evaluation
158  static void generatePowers(int n, const Scalar& x, Scalar* powers);
159 
160  static void computeCoefficients(const Scalar& start_pos,
161  const Scalar& end_pos,
162  const Scalar& time,
163  SplineCoefficients& coefficients);
164 
165  static void computeCoefficients(const Scalar& start_pos, const Scalar& start_vel,
166  const Scalar& end_pos, const Scalar& end_vel,
167  const Scalar& time,
168  SplineCoefficients& coefficients);
169 
170  static void computeCoefficients(const Scalar& start_pos, const Scalar& start_vel, const Scalar& start_acc,
171  const Scalar& end_pos, const Scalar& end_vel, const Scalar& end_acc,
172  const Scalar& time,
173  SplineCoefficients& coefficients);
174 
175  static void sample(const SplineCoefficients& coefficients, const Scalar& time,
176  Scalar& position, Scalar& velocity, Scalar& acceleration);
177 
178  static void sampleWithTimeBounds(const SplineCoefficients& coefficients, const Scalar& duration, const Scalar& time,
179  Scalar& position, Scalar& velocity, Scalar& acceleration);
180 };
181 
182 template<class ScalarType>
184  const State& start_state,
185  const Time& end_time,
186  const State& end_state)
187 {
188  // Preconditions
189  if (end_time < start_time)
190  {
191  throw(std::invalid_argument("Quintic spline segment can't be constructed: end_time < start_time."));
192  }
193  if (start_state.position.empty() || end_state.position.empty())
194  {
195  throw(std::invalid_argument("Quintic spline segment can't be constructed: Endpoint positions can't be empty."));
196  }
197  if (start_state.position.size() != end_state.position.size())
198  {
199  throw(std::invalid_argument("Quintic spline segment can't be constructed: Endpoint positions size mismatch."));
200  }
201 
202  const unsigned int dim = start_state.position.size();
203  const bool has_velocity = !start_state.velocity.empty() && !end_state.velocity.empty();
204  const bool has_acceleration = !start_state.acceleration.empty() && !end_state.acceleration.empty();
205 
206  if (has_velocity && dim != start_state.velocity.size())
207  {
208  throw(std::invalid_argument("Quintic spline segment can't be constructed: Start state velocity size mismatch."));
209  }
210  if (has_velocity && dim != end_state.velocity.size())
211  {
212  throw(std::invalid_argument("Quintic spline segment can't be constructed: End state velocity size mismatch."));
213  }
214  if (has_acceleration && dim!= start_state.acceleration.size())
215  {
216  throw(std::invalid_argument("Quintic spline segment can't be constructed: Start state acceleration size mismatch."));
217  }
218  if (has_acceleration && dim != end_state.acceleration.size())
219  {
220  throw(std::invalid_argument("Quintic spline segment can't be constructed: End state acceleratios size mismatch."));
221  }
222 
223  // Time data
224  start_time_ = start_time;
225  duration_ = end_time - start_time;
226 
227  // Spline coefficients
228  coefs_.resize(dim);
229 
230  typedef typename std::vector<SplineCoefficients>::iterator Iterator;
231  if (!has_velocity)
232  {
233  // Linear interpolation
234  for(Iterator coefs_it = coefs_.begin(); coefs_it != coefs_.end(); ++coefs_it)
235  {
236  const typename std::vector<Scalar>::size_type id = std::distance(coefs_.begin(), coefs_it);
237 
238  computeCoefficients(start_state.position[id],
239  end_state.position[id],
240  duration_,
241  *coefs_it);
242  }
243  }
244  else if (!has_acceleration)
245  {
246  // Cubic interpolation
247  for(Iterator coefs_it = coefs_.begin(); coefs_it != coefs_.end(); ++coefs_it)
248  {
249  const typename std::vector<Scalar>::size_type id = std::distance(coefs_.begin(), coefs_it);
250 
251  computeCoefficients(start_state.position[id], start_state.velocity[id],
252  end_state.position[id], end_state.velocity[id],
253  duration_,
254  *coefs_it);
255  }
256  }
257  else
258  {
259  // Quintic interpolation
260  for(Iterator coefs_it = coefs_.begin(); coefs_it != coefs_.end(); ++coefs_it)
261  {
262  const typename std::vector<Scalar>::size_type id = std::distance(coefs_.begin(), coefs_it);
263 
264  computeCoefficients(start_state.position[id], start_state.velocity[id], start_state.acceleration[id],
265  end_state.position[id], end_state.velocity[id], end_state.acceleration[id],
266  duration_,
267  *coefs_it);
268  }
269  }
270 }
271 
272 template<class ScalarType>
274 {
275  powers[0] = 1.0;
276  for (int i=1; i<=n; ++i)
277  {
278  powers[i] = powers[i-1]*x;
279  }
280 }
281 
282 template<class ScalarType>
284 computeCoefficients(const Scalar& start_pos,
285  const Scalar& end_pos,
286  const Scalar& time,
287  SplineCoefficients& coefficients)
288 {
289  coefficients[0] = start_pos;
290  coefficients[1] = (time == 0.0) ? 0.0 : (end_pos - start_pos) / time;
291  coefficients[2] = 0.0;
292  coefficients[3] = 0.0;
293  coefficients[4] = 0.0;
294  coefficients[5] = 0.0;
295 }
296 
297 template<class ScalarType>
299 computeCoefficients(const Scalar& start_pos, const Scalar& start_vel,
300  const Scalar& end_pos, const Scalar& end_vel,
301  const Scalar& time,
302  SplineCoefficients& coefficients)
303 {
304  if (time == 0.0)
305  {
306  coefficients[0] = start_pos;
307  coefficients[1] = start_vel;
308  coefficients[2] = 0.0;
309  coefficients[3] = 0.0;
310  }
311  else
312  {
313  Scalar T[4];
314  generatePowers(3, time, T);
315 
316  coefficients[0] = start_pos;
317  coefficients[1] = start_vel;
318  coefficients[2] = (-3.0*start_pos + 3.0*end_pos - 2.0*start_vel*T[1] - end_vel*T[1]) / T[2];
319  coefficients[3] = (2.0*start_pos - 2.0*end_pos + start_vel*T[1] + end_vel*T[1]) / T[3];
320  }
321  coefficients[4] = 0.0;
322  coefficients[5] = 0.0;
323 }
324 
325 template<class ScalarType>
327 computeCoefficients(const Scalar& start_pos, const Scalar& start_vel, const Scalar& start_acc,
328  const Scalar& end_pos, const Scalar& end_vel, const Scalar& end_acc,
329  const Scalar& time,
330  SplineCoefficients& coefficients)
331 {
332  if (time == 0.0)
333  {
334  coefficients[0] = start_pos;
335  coefficients[1] = start_vel;
336  coefficients[2] = 0.5*start_acc;
337  coefficients[3] = 0.0;
338  coefficients[4] = 0.0;
339  coefficients[5] = 0.0;
340  }
341  else
342  {
343  Scalar T[6];
344  generatePowers(5, time, T);
345 
346  coefficients[0] = start_pos;
347  coefficients[1] = start_vel;
348  coefficients[2] = 0.5*start_acc;
349  coefficients[3] = (-20.0*start_pos + 20.0*end_pos - 3.0*start_acc*T[2] + end_acc*T[2] -
350  12.0*start_vel*T[1] - 8.0*end_vel*T[1]) / (2.0*T[3]);
351  coefficients[4] = (30.0*start_pos - 30.0*end_pos + 3.0*start_acc*T[2] - 2.0*end_acc*T[2] +
352  16.0*start_vel*T[1] + 14.0*end_vel*T[1]) / (2.0*T[4]);
353  coefficients[5] = (-12.0*start_pos + 12.0*end_pos - start_acc*T[2] + end_acc*T[2] -
354  6.0*start_vel*T[1] - 6.0*end_vel*T[1]) / (2.0*T[5]);
355  }
356 }
357 
358 template<class ScalarType>
360 sample(const SplineCoefficients& coefficients, const Scalar& time,
361  Scalar& position, Scalar& velocity, Scalar& acceleration)
362 {
363  // create powers of time:
364  Scalar t[6];
365  generatePowers(5, time, t);
366 
367  position = t[0]*coefficients[0] +
368  t[1]*coefficients[1] +
369  t[2]*coefficients[2] +
370  t[3]*coefficients[3] +
371  t[4]*coefficients[4] +
372  t[5]*coefficients[5];
373 
374  velocity = t[0]*coefficients[1] +
375  2.0*t[1]*coefficients[2] +
376  3.0*t[2]*coefficients[3] +
377  4.0*t[3]*coefficients[4] +
378  5.0*t[4]*coefficients[5];
379 
380  acceleration = 2.0*t[0]*coefficients[2] +
381  6.0*t[1]*coefficients[3] +
382  12.0*t[2]*coefficients[4] +
383  20.0*t[3]*coefficients[5];
384 }
385 
386 template<class ScalarType>
388 sampleWithTimeBounds(const SplineCoefficients& coefficients, const Scalar& duration, const Scalar& time,
389  Scalar& position, Scalar& velocity, Scalar& acceleration)
390 {
391  if (time < 0)
392  {
393  Scalar _;
394  sample(coefficients, 0.0, position, _, _);
395  velocity = 0;
396  acceleration = 0;
397  }
398  else if (time > duration)
399  {
400  Scalar _;
401  sample(coefficients, duration, position, _, _);
402  velocity = 0;
403  acceleration = 0;
404  }
405  else
406  {
407  sample(coefficients, time,
408  position, velocity, acceleration);
409  }
410 }
411 
412 } // namespace
413 
414 #endif // header guard
static void generatePowers(int n, const Scalar &x, Scalar *powers)
Class representing a multi-dimensional quintic spline segment with a start and end time...
std::vector< SplineCoefficients > coefs_
static void sampleWithTimeBounds(const SplineCoefficients &coefficients, const Scalar &duration, const Scalar &time, Scalar &position, Scalar &velocity, Scalar &acceleration)
QuinticSplineSegment(const Time &start_time, const State &start_state, const Time &end_time, const State &end_state)
Construct segment from start and end states (boundary conditions).
void init(const Time &start_time, const State &start_state, const Time &end_time, const State &end_state)
Initialize segment from start and end states (boundary conditions).
static void computeCoefficients(const Scalar &start_pos, const Scalar &end_pos, const Scalar &time, SplineCoefficients &coefficients)
void sample(const Time &time, State &state) const
Sample the segment at a specified time.
Multi-dof trajectory state containing position, velocity and acceleration data.


joint_trajectory_controller
Author(s): Adolfo Rodriguez Tsouroukdissian
autogenerated on Sat Apr 18 2020 03:58:18