trajectory_spline_sampler.h
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2014, Fetch Robotics Inc.
5  * Copyright (c) 2013, Unbounded Robotics Inc.
6  * Copyright (c) 2009, Willow Garage, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Unbounded Robotics, Willow Garage nor the names
20  * of their contributors may be used to endorse or promote products
21  * derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *********************************************************************/
36 
37 // Portions are based on splines.h of arm_navigation
38 // Author: Michael Ferguson, Mrinal Kalakrishnan (splines.h)
39 
40 #ifndef ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_
41 #define ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_
42 
44 
45 namespace robot_controllers
46 {
47 
49 struct Spline
50 {
51  double coef[6];
52 };
53 
55 {
59 };
60 
62 static inline void generatePowers(int n, double x, double* powers)
63 {
64  powers[0] = 1.0;
65  for (int i=1; i<=n; i++)
66  {
67  powers[i] = powers[i-1]*x;
68  }
69 }
70 
82 static void QuinticSpline(double p0, double v0, double a0,
83  double p1, double v1, double a1,
84  double t, Spline& s)
85 {
86  if (t == 0.0)
87  {
88  s.coef[0] = p1;
89  s.coef[1] = v1;
90  s.coef[2] = 0.5*a1;
91  s.coef[3] = 0.0;
92  s.coef[4] = 0.0;
93  s.coef[5] = 0.0;
94  }
95  else
96  {
97  double T[6];
98  generatePowers(5, t, T);
99 
100  s.coef[0] = p0;
101  s.coef[1] = v0;
102  s.coef[2] = 0.5*a0;
103  s.coef[3] = (-20.0*p0 + 20.0*p1 - 3.0*a0*T[2] + a1*T[2] -
104  12.0*v0*T[1] - 8.0*v1*T[1]) / (2.0*T[3]);
105  s.coef[4] = (30.0*p0 - 30.0*p1 + 3.0*a0*T[2] - 2.0*a1*T[2] +
106  16.0*v0*T[1] + 14.0*v1*T[1]) / (2.0*T[4]);
107  s.coef[5] = (-12.0*p0 + 12.0*p1 - a0*T[2] + a1*T[2] -
108  6.0*v0*T[1] - 6.0*v1*T[1]) / (2.0*T[5]);
109  }
110 }
111 
115 static void sampleQuinticSpline(Spline& s, double t,
116  double& position, double& velocity, double& acceleration)
117 {
118  double T[6];
119  generatePowers(5, t, T);
120 
121  position = T[0]*s.coef[0] +
122  T[1]*s.coef[1] +
123  T[2]*s.coef[2] +
124  T[3]*s.coef[3] +
125  T[4]*s.coef[4] +
126  T[5]*s.coef[5];
127 
128  velocity = T[0]*s.coef[1] +
129  2.0*T[1]*s.coef[2] +
130  3.0*T[2]*s.coef[3] +
131  4.0*T[3]*s.coef[4] +
132  5.0*T[4]*s.coef[5];
133 
134  acceleration = 2.0*T[0]*s.coef[2] +
135  6.0*T[1]*s.coef[3] +
136  12.0*T[2]*s.coef[4] +
137  20.0*T[3]*s.coef[5];
138 }
139 
149 static void CubicSpline(double p0, double v0, double p1, double v1, double t, Spline& s)
150 {
151  if (t == 0.0)
152  {
153  s.coef[0] = p1;
154  s.coef[1] = v1;
155  s.coef[2] = 0.0;
156  s.coef[3] = 0.0;
157  }
158  else
159  {
160  double T[4];
161  generatePowers(3, t, T);
162 
163  s.coef[0] = p0;
164  s.coef[1] = v0;
165  s.coef[2] = (3.0 * p1 - 3.0 * p0 - 2.0 *v0*T[1] - v1*T[1]) / T[2];
166  s.coef[3] = (-2.0 * p1 + 2.0 * p0 + v0*T[1] + v1*T[1]) / T[3];
167  }
168 }
169 
173 static void sampleCubicSpline(Spline s, double t, double& position, double& velocity)
174 {
175  double T[4];
176  generatePowers(3, t, T);
177 
178  position = T[0]*s.coef[0] +
179  T[1]*s.coef[1] +
180  T[2]*s.coef[2] +
181  T[3]*s.coef[3];
182 
183  velocity = T[0]*s.coef[1] +
184  2.0*T[1]*s.coef[2] +
185  3.0*T[2]*s.coef[3];
186 }
187 
188 static void LinearSpline(double p0, double p1, double t, Spline& s)
189 {
190  s.coef[0] = p0;
191  s.coef[1] = p1 - p0;
192  s.coef[2] = t;
193 }
194 
195 static void sampleLinearSpline(Spline& s, double t, double& position)
196 {
197  position = s.coef[0] + (s.coef[1] * t/s.coef[2]);
198 }
199 
204 {
205  struct Segment
206  {
207  double start_time;
208  double end_time;
209  int type;
210  std::vector<Spline> splines;
211  };
212 
213 public:
215  SplineTrajectorySampler(const Trajectory& trajectory) :
216  trajectory_(trajectory)
217  {
218  // Check for invalid trajectory size
219  if (trajectory.size() == 0)
220  {
221  throw 0;
222  }
223 
224  // Check for number of joints
225  size_t num_joints = trajectory.points[0].q.size();
226 
227  // Trajectory length one is special
228  if (trajectory.size() == 1)
229  {
230  segments_.resize(1);
231  segments_[0].start_time = segments_[0].end_time = trajectory.points[0].time;
232 
233  // Set up spline
234  segments_[0].splines.resize(num_joints);
235  for (size_t j = 0; j < num_joints; ++j)
236  {
237  LinearSpline(trajectory.points[0].q[j],
238  trajectory.points[0].q[j],
239  0.0,
240  segments_[0].splines[j]);
241  }
242  segments_[0].type = LINEAR;
243  result.q.resize(num_joints);
244  }
245  else
246  {
247  // We put a segment in between each pair of points
248  segments_.resize(trajectory.size()-1);
249 
250  // Setup up the segments
251  for (size_t p = 0; p < segments_.size(); ++p)
252  {
253  // This segment is from p to p+1
254  segments_[p].start_time = trajectory.points[p].time;
255  segments_[p].end_time = trajectory.points[p+1].time;
256 
257  // Set up spline
258  segments_[p].splines.resize(num_joints);
259  if (trajectory.points[p].qdd.size() == trajectory.points[p].q.size())
260  {
261  result.q.resize(num_joints);
262  result.qd.resize(num_joints);
263  result.qdd.resize(num_joints);
264 
265  // Have accelerations, will use Quintic.
266  for (size_t j = 0; j < num_joints; ++j)
267  {
268  QuinticSpline(trajectory.points[p].q[j],
269  trajectory.points[p].qd[j],
270  trajectory.points[p].qdd[j],
271  trajectory.points[p+1].q[j],
272  trajectory.points[p+1].qd[j],
273  trajectory.points[p+1].qdd[j],
274  segments_[p].end_time - segments_[p].start_time,
275  segments_[p].splines[j]);
276  }
277  segments_[p].type = QUINTIC;
278  }
279  else if (trajectory.points[p].qd.size() == trajectory.points[p].q.size())
280  {
281  result.q.resize(num_joints);
282  result.qd.resize(num_joints);
283 
284  // Velocities + Positions, do Cubic.
285  for (size_t j = 0; j < num_joints; ++j)
286  {
287  CubicSpline(trajectory.points[p].q[j],
288  trajectory.points[p].qd[j],
289  trajectory.points[p+1].q[j],
290  trajectory.points[p+1].qd[j],
291  segments_[p].end_time - segments_[p].start_time,
292  segments_[p].splines[j]);
293  }
294  segments_[p].type = CUBIC;
295  }
296  else
297  {
298  result.q.resize(num_joints);
299 
300  // Lame -- only positions do linear
301  for (size_t j = 0; j < num_joints; ++j)
302  {
303  LinearSpline(trajectory.points[p].q[j],
304  trajectory.points[p+1].q[j],
305  segments_[p].end_time - segments_[p].start_time,
306  segments_[p].splines[j]);
307  }
308  segments_[p].type = LINEAR;
309  }
310  }
311  }
312  seg_ = -1;
313  }
314 
316  virtual TrajectoryPoint sample(double time)
317  {
318  // Which segment to sample from.
319  while ((seg_ + 1 < int(segments_.size())) &&
320  (segments_[seg_ + 1].start_time < time))
321  {
322  ++seg_;
323  }
324 
325  // Check beginning of trajectory, return empty trajectory point if not started.
326  if (seg_ == -1)
327  return TrajectoryPoint();
328 
329  // Check end of trajectory, restrict time.
330  if (time > end_time())
331  time = end_time();
332 
333  // Sample segment for each joint.
334  for (size_t i = 0; i < segments_[seg_].splines.size(); ++i)
335  {
336  if (segments_[seg_].type == QUINTIC)
337  {
338  sampleQuinticSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
339  result.q[i], result.qd[i], result.qdd[i]);
340  }
341  else if(segments_[seg_].type == CUBIC)
342  {
343  sampleCubicSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
344  result.q[i], result.qd[i]);
345  }
346  else
347  {
348  sampleLinearSpline(segments_[seg_].splines[i], time - segments_[seg_].start_time,
349  result.q[i]);
350  }
351  }
352 
353  result.time = time;
354  return result;
355  }
356 
358  virtual double end_time()
359  {
360  return segments_[segments_.size()-1].end_time;
361  }
362 
365  {
366  return trajectory_;
367  }
368 
369 private:
370  std::vector<Segment> segments_;
373  int seg_;
374 };
375 
376 } // namespace robot_controllers
377 
378 #endif // ROBOT_CONTROLLERS_TRAJECTORY_SPLINE_SAMPLER_H_
Basis for a Trajectory Point.
Definition: trajectory.h:51
result
static void LinearSpline(double p0, double p1, double t, Spline &s)
static void sampleCubicSpline(Spline s, double t, double &position, double &velocity)
Sample from the spline at time t.
std::vector< TrajectoryPoint > points
Definition: trajectory.h:61
std::vector< Spline > splines
spline type (to choose interpolation)
virtual double end_time()
Get the end time of our trajectory.
type
virtual Trajectory getTrajectory()
Get the trajectory that we are sampling from.
static void QuinticSpline(double p0, double v0, double a0, double p1, double v1, double a1, double t, Spline &s)
Create a quintic spline with between (p0,v0,a0) and (p1,v1,a1)
static void CubicSpline(double p0, double v0, double p1, double v1, double t, Spline &s)
Constructor for a cubic spline with between (p0,v0) and (p1,v1)
static void sampleQuinticSpline(Spline &s, double t, double &position, double &velocity, double &acceleration)
Sample from the spline at time t.
SplineTrajectorySampler(const Trajectory &trajectory)
Construct a trajectory sampler.
static void generatePowers(int n, double x, double *powers)
Helper function for splines.
virtual TrajectoryPoint sample(double time)
Sample from this trajectory.
static void sampleLinearSpline(Spline &s, double t, double &position)
Base class for samplers of trajectories.
Definition: trajectory.h:307


robot_controllers
Author(s): Michael Ferguson
autogenerated on Sun Sep 27 2020 03:22:39