moveit2
The MoveIt Motion Planning Framework for ROS 2.
iterative_spline_parameterization.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Ken Anderson
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Ken Anderson */
36 
39 #include <rclcpp/logger.hpp>
40 #include <rclcpp/logging.hpp>
41 #include <vector>
42 
43 static const double VLIMIT = 1.0; // default if not specified in model
44 static const double ALIMIT = 1.0; // default if not specified in model
45 
46 namespace trajectory_processing
47 {
48 static const rclcpp::Logger LOGGER =
49  rclcpp::get_logger("moveit_trajectory_processing.iterative_spline_parameterization");
50 
51 static void fit_cubic_spline(const int n, const double dt[], const double x[], double x1[], double x2[]);
52 static void adjust_two_positions(const int n, const double dt[], double x[], double x1[], double x2[],
53  const double x2_i, const double x2_f);
54 static void init_times(const int n, double dt[], const double x[], const double max_velocity, const double min_velocity);
55 static double global_adjustment_factor(const int n, double x1[], double x2[], const double max_velocity,
56  const double min_velocity, const double max_acceleration,
57  const double min_acceleration);
58 
59 // The path of a single joint: positions, velocities, and accelerations
61 {
62  std::vector<double> positions_; // joint's position at time[x]
63  std::vector<double> velocities_;
64  std::vector<double> accelerations_;
67  double min_velocity_;
68  double max_velocity_;
71 };
72 
73 void globalAdjustment(std::vector<SingleJointTrajectory>& t2, robot_trajectory::RobotTrajectory& trajectory,
74  std::vector<double>& time_diff);
75 
76 IterativeSplineParameterization::IterativeSplineParameterization(bool add_points) : add_points_(add_points)
77 {
78 }
79 
81  const double max_velocity_scaling_factor,
82  const double max_acceleration_scaling_factor) const
83 {
84  if (trajectory.empty())
85  return true;
86 
87  const moveit::core::JointModelGroup* group = trajectory.getGroup();
88  if (!group)
89  {
90  RCLCPP_ERROR(LOGGER, "It looks like the planner did not set "
91  "the group the plan was computed for");
92  return false;
93  }
94  const moveit::core::RobotModel& rmodel = group->getParentModel();
95  const std::vector<int>& idx = group->getVariableIndexList();
96  const std::vector<std::string>& vars = group->getVariableNames();
97  double velocity_scaling_factor = 1.0;
98  double acceleration_scaling_factor = 1.0;
99  unsigned int num_points = trajectory.getWayPointCount();
100  unsigned int num_joints = group->getVariableCount();
101 
102  // Set scaling factors
103  if (max_velocity_scaling_factor > 0.0 && max_velocity_scaling_factor <= 1.0)
104  velocity_scaling_factor = max_velocity_scaling_factor;
105  else if (max_velocity_scaling_factor == 0.0)
106  {
107  RCLCPP_DEBUG(LOGGER, "A max_velocity_scaling_factor of 0.0 was specified, defaulting to %f instead.",
108  velocity_scaling_factor);
109  }
110  else
111  {
112  RCLCPP_WARN(LOGGER, "Invalid max_velocity_scaling_factor %f specified, defaulting to %f instead.",
113  max_velocity_scaling_factor, velocity_scaling_factor);
114  }
115  if (max_acceleration_scaling_factor > 0.0 && max_acceleration_scaling_factor <= 1.0)
116  acceleration_scaling_factor = max_acceleration_scaling_factor;
117  else if (max_acceleration_scaling_factor == 0.0)
118  {
119  RCLCPP_DEBUG(LOGGER, "A max_acceleration_scaling_factor of 0.0 was specified, defaulting to %f instead.",
120  acceleration_scaling_factor);
121  }
122  else
123  {
124  RCLCPP_WARN(LOGGER, "Invalid max_acceleration_scaling_factor %f specified, defaulting to %f instead.",
125  max_acceleration_scaling_factor, acceleration_scaling_factor);
126  }
127  // No wrapped angles.
128  trajectory.unwind();
129 
130  if (add_points_)
131  {
132  // Insert 2nd and 2nd-last points
133  // (required to force acceleration to specified values at endpoints)
134  if (trajectory.getWayPointCount() >= 2)
135  {
136  moveit::core::RobotState point = trajectory.getWayPoint(1);
137  moveit::core::RobotStatePtr p0, p1;
138 
139  // 2nd point is 90% of p0, and 10% of p1
140  p0 = trajectory.getWayPointPtr(0);
141  p1 = trajectory.getWayPointPtr(1);
142  for (unsigned int j = 0; j < num_joints; ++j)
143  {
144  point.setVariablePosition(idx[j],
145  (9 * p0->getVariablePosition(idx[j]) + 1 * p1->getVariablePosition(idx[j])) / 10);
146  }
147  trajectory.insertWayPoint(1, point, 0.0);
148  num_points++;
149 
150  // 2nd-last point is 10% of p0, and 90% of p1
151  p0 = trajectory.getWayPointPtr(num_points - 2);
152  p1 = trajectory.getWayPointPtr(num_points - 1);
153  for (unsigned int j = 0; j < num_joints; ++j)
154  {
155  point.setVariablePosition(idx[j],
156  (1 * p0->getVariablePosition(idx[j]) + 9 * p1->getVariablePosition(idx[j])) / 10);
157  }
158  trajectory.insertWayPoint(num_points - 1, point, 0.0);
159  num_points++;
160  }
161  }
162 
163  // JointTrajectory indexes in [point][joint] order.
164  // We need [joint][point] order to solve efficiently,
165  // so convert form here.
166 
167  std::vector<SingleJointTrajectory> t2(num_joints);
168 
169  for (unsigned int j = 0; j < num_joints; ++j)
170  {
171  // Copy positions
172  t2[j].positions_.resize(num_points, 0.0);
173  for (unsigned int i = 0; i < num_points; ++i)
174  {
175  t2[j].positions_[i] = trajectory.getWayPointPtr(i)->getVariablePosition(idx[j]);
176  }
177 
178  // Initialize velocities
179  t2[j].velocities_.resize(num_points, 0.0);
180  // Copy initial/final velocities if specified
181  if (trajectory.getWayPointPtr(0)->hasVelocities())
182  t2[j].velocities_[0] = trajectory.getWayPointPtr(0)->getVariableVelocity(idx[j]);
183  if (trajectory.getWayPointPtr(num_points - 1)->hasVelocities())
184  t2[j].velocities_[num_points - 1] = trajectory.getWayPointPtr(num_points - 1)->getVariableVelocity(idx[j]);
185 
186  // Initialize accelerations
187  t2[j].accelerations_.resize(num_points, 0.0);
188  t2[j].initial_acceleration_ = 0.0;
189  t2[j].final_acceleration_ = 0.0;
190  // Copy initial/final accelerations if specified
191  if (trajectory.getWayPointPtr(0)->hasAccelerations())
192  t2[j].initial_acceleration_ = trajectory.getWayPointPtr(0)->getVariableAcceleration(idx[j]);
193  t2[j].accelerations_[0] = t2[j].initial_acceleration_;
194  if (trajectory.getWayPointPtr(num_points - 1)->hasAccelerations())
195  t2[j].final_acceleration_ = trajectory.getWayPointPtr(num_points - 1)->getVariableAcceleration(idx[j]);
196  t2[j].accelerations_[num_points - 1] = t2[j].final_acceleration_;
197 
198  // Set bounds based on model, or default limits
199  const moveit::core::VariableBounds& bounds = rmodel.getVariableBounds(vars[j]);
200  t2[j].max_velocity_ = VLIMIT;
201  t2[j].min_velocity_ = -VLIMIT;
202  if (bounds.velocity_bounded_)
203  {
204  t2[j].max_velocity_ = bounds.max_velocity_;
205  t2[j].min_velocity_ = bounds.min_velocity_;
206  if (t2[j].min_velocity_ == 0.0)
207  t2[j].min_velocity_ = -t2[j].max_velocity_;
208  }
209  t2[j].max_velocity_ *= velocity_scaling_factor;
210  t2[j].min_velocity_ *= velocity_scaling_factor;
211 
212  t2[j].max_acceleration_ = ALIMIT;
213  t2[j].min_acceleration_ = -ALIMIT;
214  if (bounds.acceleration_bounded_)
215  {
216  t2[j].max_acceleration_ = bounds.max_acceleration_;
217  t2[j].min_acceleration_ = bounds.min_acceleration_;
218  if (t2[j].min_acceleration_ == 0.0)
219  t2[j].min_acceleration_ = -t2[j].max_acceleration_;
220  }
221  t2[j].max_acceleration_ *= acceleration_scaling_factor;
222  t2[j].min_acceleration_ *= acceleration_scaling_factor;
223 
224  // Error out if bounds don't make sense
225  if (t2[j].max_velocity_ <= 0.0 || t2[j].max_acceleration_ <= 0.0)
226  {
227  RCLCPP_ERROR(LOGGER,
228  "Joint %d max velocity %f and max acceleration %f must be greater than zero "
229  "or a solution won't be found.\n",
230  j, t2[j].max_velocity_, t2[j].max_acceleration_);
231  return false;
232  }
233  if (t2[j].min_velocity_ >= 0.0 || t2[j].min_acceleration_ >= 0.0)
234  {
235  RCLCPP_ERROR(LOGGER,
236  "Joint %d min velocity %f and min acceleration %f must be less than zero "
237  "or a solution won't be found.\n",
238  j, t2[j].min_velocity_, t2[j].min_acceleration_);
239  return false;
240  }
241  }
242 
243  // Error check
244  if (num_points < 4)
245  {
246  RCLCPP_ERROR(LOGGER, "number of waypoints %d, needs to be greater than 3.\n", num_points);
247  return false;
248  }
249  for (unsigned int j = 0; j < num_joints; ++j)
250  {
251  if (t2[j].velocities_[0] > t2[j].max_velocity_ || t2[j].velocities_[0] < t2[j].min_velocity_)
252  {
253  RCLCPP_ERROR(LOGGER, "Initial velocity %f out of bounds\n", t2[j].velocities_[0]);
254  return false;
255  }
256  else if (t2[j].velocities_[num_points - 1] > t2[j].max_velocity_ ||
257  t2[j].velocities_[num_points - 1] < t2[j].min_velocity_)
258  {
259  RCLCPP_ERROR(LOGGER, "Final velocity %f out of bounds\n", t2[j].velocities_[num_points - 1]);
260  return false;
261  }
262  else if (t2[j].accelerations_[0] > t2[j].max_acceleration_ || t2[j].accelerations_[0] < t2[j].min_acceleration_)
263  {
264  RCLCPP_ERROR(LOGGER, "Initial acceleration %f out of bounds\n", t2[j].accelerations_[0]);
265  return false;
266  }
267  else if (t2[j].accelerations_[num_points - 1] > t2[j].max_acceleration_ ||
268  t2[j].accelerations_[num_points - 1] < t2[j].min_acceleration_)
269  {
270  RCLCPP_ERROR(LOGGER, "Final acceleration %f out of bounds\n", t2[j].accelerations_[num_points - 1]);
271  return false;
272  }
273  }
274 
275  // Initialize times
276  // start with valid velocities, then expand intervals
277  // epsilon to prevent divide-by-zero
278  std::vector<double> time_diff(trajectory.getWayPointCount() - 1, std::numeric_limits<double>::epsilon());
279  for (unsigned int j = 0; j < num_joints; ++j)
280  init_times(num_points, &time_diff[0], &t2[j].positions_[0], t2[j].max_velocity_, t2[j].min_velocity_);
281 
282  // Stretch intervals until close to the bounds
283  while (1)
284  {
285  int loop = 0;
286 
287  // Calculate the interval stretches due to acceleration
288  std::vector<double> time_factor(num_points - 1, 1.00);
289  for (unsigned j = 0; j < num_joints; ++j)
290  {
291  // Move points to satisfy initial/final acceleration
292  if (add_points_)
293  {
294  adjust_two_positions(num_points, &time_diff[0], &t2[j].positions_[0], &t2[j].velocities_[0],
295  &t2[j].accelerations_[0], t2[j].initial_acceleration_, t2[j].final_acceleration_);
296  }
297 
298  fit_cubic_spline(num_points, &time_diff[0], &t2[j].positions_[0], &t2[j].velocities_[0], &t2[j].accelerations_[0]);
299  for (unsigned i = 0; i < num_points; ++i)
300  {
301  const double acc = t2[j].accelerations_[i];
302  double atfactor = 1.0;
303  if (acc > t2[j].max_acceleration_)
304  atfactor = sqrt(acc / t2[j].max_acceleration_);
305  if (acc < t2[j].min_acceleration_)
306  atfactor = sqrt(acc / t2[j].min_acceleration_);
307  if (atfactor > 1.01) // within 1%
308  loop = 1;
309  atfactor = (atfactor - 1.0) / 16.0 + 1.0; // 1/16th
310  if (i > 0)
311  time_factor[i - 1] = std::max(time_factor[i - 1], atfactor);
312  if (i < num_points - 1)
313  time_factor[i] = std::max(time_factor[i], atfactor);
314  }
315  }
316 
317  if (loop == 0)
318  break; // finished
319 
320  // Stretch
321  for (unsigned i = 0; i < num_points - 1; ++i)
322  time_diff[i] *= time_factor[i];
323  }
324 
325  // Final adjustment forces the trajectory within bounds
326  globalAdjustment(t2, trajectory, time_diff);
327 
328  // Convert back to JointTrajectory form
329  for (unsigned int i = 1; i < num_points; ++i)
330  trajectory.setWayPointDurationFromPrevious(i, time_diff[i - 1]);
331  for (unsigned int i = 0; i < num_points; ++i)
332  {
333  for (unsigned int j = 0; j < num_joints; ++j)
334  {
335  trajectory.getWayPointPtr(i)->setVariableVelocity(idx[j], t2[j].velocities_[i]);
336  trajectory.getWayPointPtr(i)->setVariableAcceleration(idx[j], t2[j].accelerations_[i]);
337  }
338 
339  // Only update position of additionally inserted points (at second and next-to-last position)
340  if (add_points_ && (i == 1 || i == num_points - 2))
341  {
342  for (unsigned int j = 0; j < num_joints; ++j)
343  trajectory.getWayPointPtr(i)->setVariablePosition(idx[j], t2[j].positions_[i]);
344  trajectory.getWayPointPtr(i)->update();
345  }
346  }
347 
348  return true;
349 }
350 
352  robot_trajectory::RobotTrajectory& /*trajectory*/,
353  const std::unordered_map<std::string, double>& /*velocity_limits*/,
354  const std::unordered_map<std::string, double>& /*acceleration_limits*/) const
355 {
356  RCLCPP_ERROR(LOGGER, "ISTP does not support this version of computeTimeStamps. Try TOTG instead?");
357  return false;
358 }
359 
361 
362 /*
363  Fit a 'clamped' cubic spline over a series of points.
364  A cubic spline ensures continuous function across positions,
365  1st derivative (velocities), and 2nd derivative (accelerations).
366  'Clamped' means the first derivative at the endpoints is specified.
367 
368  Fitting a cubic spline involves solving a series of linear equations.
369  The general form for each segment is:
370  (tj-t_(j-1))*x"_(j-1) + 2*(t_(j+1)-t_(j-1))*x"j + (t_(j+1)-tj)*x"_j+1) =
371  (x_(j+1)-xj)/(t_(j+1)-tj) - (xj-x_(j-1))/(tj-t_(j-1))
372  And the first and last segment equations are clamped to specified values: x1_i and x1_f.
373 
374  Represented in matrix form:
375  [ 2*(t1-t0) (t1-t0) 0 ][x0"] [(x1-x0)/(t1-t0) - t1_i ]
376  [ t1-t0 2*(t2-t0) t2-t1 ][x1"] [(x2-x1)/(t2-t1) - (x1-x0)/(t1-t0)]
377  [ t2-t1 2*(t3-t1) t3-t2 ][x2"] = 6 * [(x3-x2)/(t3/t2) - (x2-x1)/(t2-t1)]
378  [ ... ... ... ][...] [... ]
379  [ 0 tN-t_(N-1) 2*(tN-t_(N-1)) ][xN"] [t1_f - (xN-x_(N-1))/(tN-t_(N-1)) ]
380 
381  This matrix is tridiagonal, which can be solved solved in O(N) time
382  using the tridiagonal algorithm.
383  There is a forward propagation pass followed by a backsubstitution pass.
384 
385  n is the number of points
386  dt contains the time difference between each point (size=n-1)
387  x contains the positions (size=n)
388  x1 contains the 1st derivative (velocities) (size=n)
389  x1[0] and x1[n-1] MUST be specified.
390  x2 contains the 2nd derivative (accelerations) (size=n)
391  x1 and x2 are filled in by the algorithm.
392 */
393 
394 static void fit_cubic_spline(const int n, const double dt[], const double x[], double x1[], double x2[])
395 {
396  int i;
397  const double x1_i = x1[0], x1_f = x1[n - 1];
398 
399  // Tridiagonal alg - forward sweep
400  // x1 and x2 used to store the temporary coefficients c and d
401  // (will get overwritten during backsubstitution)
402  double *c = x1, *d = x2;
403  c[0] = 0.5;
404  d[0] = 3.0 * ((x[1] - x[0]) / dt[0] - x1_i) / dt[0];
405  for (i = 1; i <= n - 2; ++i)
406  {
407  const double dt2 = dt[i - 1] + dt[i];
408  const double a = dt[i - 1] / dt2;
409  const double denom = 2.0 - a * c[i - 1];
410  c[i] = (1.0 - a) / denom;
411  d[i] = 6.0 * ((x[i + 1] - x[i]) / dt[i] - (x[i] - x[i - 1]) / dt[i - 1]) / dt2;
412  d[i] = (d[i] - a * d[i - 1]) / denom;
413  }
414  const double denom = dt[n - 2] * (2.0 - c[n - 2]);
415  d[n - 1] = 6.0 * (x1_f - (x[n - 1] - x[n - 2]) / dt[n - 2]);
416  d[n - 1] = (d[n - 1] - dt[n - 2] * d[n - 2]) / denom;
417 
418  // Tridiagonal alg - backsubstitution sweep
419  // 2nd derivative
420  x2[n - 1] = d[n - 1];
421  for (i = n - 2; i >= 0; i--)
422  x2[i] = d[i] - c[i] * x2[i + 1];
423 
424  // 1st derivative
425  x1[0] = x1_i;
426  for (i = 1; i < n - 1; ++i)
427  x1[i] = (x[i + 1] - x[i]) / dt[i] - (2 * x2[i] + x2[i + 1]) * dt[i] / 6.0;
428  x1[n - 1] = x1_f;
429 }
430 
431 /*
432  Modify the value of x[1] and x[N-2]
433  so that 2nd derivative starts and ends at specified value.
434  This involves fitting the spline twice,
435  then solving for the specified value.
436 
437  x2_i and x2_f are the (initial and final) 2nd derivative at 0 and N-1
438 */
439 
440 static void adjust_two_positions(const int n, const double dt[], double x[], double x1[], double x2[],
441  const double x2_i, const double x2_f)
442 {
443  x[1] = x[0];
444  x[n - 2] = x[n - 3];
445  fit_cubic_spline(n, dt, x, x1, x2);
446  double a0 = x2[0];
447  double b0 = x2[n - 1];
448 
449  x[1] = x[2];
450  x[n - 2] = x[n - 1];
451  fit_cubic_spline(n, dt, x, x1, x2);
452  double a2 = x2[0];
453  double b2 = x2[n - 1];
454 
455  // we can solve this with linear equation (use two-point form)
456  if (a2 != a0)
457  x[1] = x[0] + ((x[2] - x[0]) / (a2 - a0)) * (x2_i - a0);
458  if (b2 != b0)
459  x[n - 2] = x[n - 3] + ((x[n - 1] - x[n - 3]) / (b2 - b0)) * (x2_f - b0);
460 }
461 
462 /*
463  Find time required to go max velocity on each segment.
464  Increase a segment's time interval if the current time isn't long enough.
465 */
466 
467 static void init_times(const int n, double dt[], const double x[], const double max_velocity, const double min_velocity)
468 {
469  int i;
470  for (i = 0; i < n - 1; ++i)
471  {
472  double time;
473  double dx = x[i + 1] - x[i];
474  if (dx >= 0.0)
475  time = (dx / max_velocity);
476  else
477  time = (dx / min_velocity);
478  time += std::numeric_limits<double>::epsilon(); // prevent divide-by-zero
479 
480  if (dt[i] < time)
481  dt[i] = time;
482  }
483 }
484 
485 #if 0 // unused function
486 /*
487  Fit a spline, then check each interval to see if bounds are met.
488  If all bounds met (no time adjustments made), return 0.
489  If bounds not met (time adjustments made), slightly increase the
490  surrounding time intervals and return 1.
491 
492  n is the number of points
493  dt contains the time difference between each point (size=n-1)
494  x contains the positions (size=n)
495  x1 contains the 1st derivative (velocities) (size=n)
496  x1[0] and x1[n-1] MUST be specified.
497  x2 contains the 2nd derivative (accelerations) (size=n)
498  max_velocity is the max velocity for this joint.
499  min_velocity is the min velocity for this joint.
500  max_acceleration is the max acceleration for this joint.
501  min_acceleration is the min acceleration for this joint.
502  tfactor is the time adjustment (multiplication) factor.
503  x1 and x2 are filled in by the algorithm.
504 */
505 
506 static int fit_spline_and_adjust_times(const int n, double dt[], const double x[], double x1[], double x2[],
507  const double max_velocity, const double min_velocity,
508  const double max_acceleration, const double min_acceleration,
509  const double tfactor)
510 {
511  int i, ret = 0;
512 
513  fit_cubic_spline(n, dt, x, x1, x2);
514 
515  // Instantaneous velocity is calculated at each point
516  for (i = 0; i < n - 1; ++i)
517  {
518  const double vel = x1[i];
519  const double vel2 = x1[i + 1];
520  if (vel > max_velocity || vel < min_velocity || vel2 > max_velocity || vel2 < min_velocity)
521  {
522  dt[i] *= tfactor;
523  ret = 1;
524  }
525  }
526  // Instantaneous acceleration is calculated at each point
527  if (ret == 0)
528  {
529  for (i = 0; i < n - 1; ++i)
530  {
531  const double acc = x2[i];
532  const double acc2 = x2[i + 1];
533  if (acc > max_acceleration || acc < min_acceleration || acc2 > max_acceleration || acc2 < min_acceleration)
534  {
535  dt[i] *= tfactor;
536  ret = 1;
537  }
538  }
539  }
540 
541  return ret;
542 }
543 #endif
544 
545 // return global expansion multiplicative factor required
546 // to force within bounds.
547 // Assumes that the spline is already fit
548 // (fit_cubic_spline must have been called before this).
549 static double global_adjustment_factor(const int n, double x1[], double x2[], const double max_velocity,
550  const double min_velocity, const double max_acceleration,
551  const double min_acceleration)
552 {
553  int i;
554  double tfactor2 = 1.00;
555 
556  for (i = 0; i < n; ++i)
557  {
558  double tfactor;
559  tfactor = x1[i] / max_velocity;
560  if (tfactor2 < tfactor)
561  tfactor2 = tfactor;
562  tfactor = x1[i] / min_velocity;
563  if (tfactor2 < tfactor)
564  tfactor2 = tfactor;
565 
566  if (x2[i] >= 0)
567  {
568  tfactor = sqrt(fabs(x2[i] / max_acceleration));
569  if (tfactor2 < tfactor)
570  tfactor2 = tfactor;
571  }
572  else
573  {
574  tfactor = sqrt(fabs(x2[i] / min_acceleration));
575  if (tfactor2 < tfactor)
576  tfactor2 = tfactor;
577  }
578  }
579 
580  return tfactor2;
581 }
582 
583 // Expands the entire trajectory to fit exactly within bounds
584 void globalAdjustment(std::vector<SingleJointTrajectory>& t2, robot_trajectory::RobotTrajectory& trajectory,
585  std::vector<double>& time_diff)
586 {
587  const moveit::core::JointModelGroup* group = trajectory.getGroup();
588 
589  const unsigned int num_points = trajectory.getWayPointCount();
590  const unsigned int num_joints = group->getVariableCount();
591 
592  double gtfactor = 1.0;
593  for (unsigned int j = 0; j < num_joints; ++j)
594  {
595  double tfactor;
596  tfactor = global_adjustment_factor(num_points, &t2[j].velocities_[0], &t2[j].accelerations_[0], t2[j].max_velocity_,
597  t2[j].min_velocity_, t2[j].max_acceleration_, t2[j].min_acceleration_);
598  if (tfactor > gtfactor)
599  gtfactor = tfactor;
600  }
601 
602  // printf("# Global adjustment: %0.4f%%\n", 100.0 * (gtfactor - 1.0));
603  for (unsigned int i = 0; i < num_points - 1; ++i)
604  time_diff[i] *= gtfactor;
605 
606  for (unsigned int j = 0; j < num_joints; ++j)
607  {
608  fit_cubic_spline(num_points, &time_diff[0], &t2[j].positions_[0], &t2[j].velocities_[0], &t2[j].accelerations_[0]);
609  }
610 }
611 } // namespace trajectory_processing
Definition of a kinematic model. This class is not thread safe, however multiple instances can be cre...
Definition: robot_model.h:76
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a specific variable. Throw an exception of variable is not found.
Definition: robot_model.h:433
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.h:90
void setVariablePosition(const std::string &variable, double value)
Set the position of a single variable. An exception is thrown if the variable name is not known.
Definition: robot_state.h:188
Maintain a sequence of waypoints and the time durations between these waypoints.
RobotTrajectory & setWayPointDurationFromPrevious(std::size_t index, double value)
const moveit::core::JointModelGroup * getGroup() const
moveit::core::RobotStatePtr & getWayPointPtr(std::size_t index)
RobotTrajectory & insertWayPoint(std::size_t index, const moveit::core::RobotState &state, double dt)
const moveit::core::RobotState & getWayPoint(std::size_t index) const
bool computeTimeStamps(robot_trajectory::RobotTrajectory &trajectory, const double max_velocity_scaling_factor=1.0, const double max_acceleration_scaling_factor=1.0) const override
x
Definition: pick.py:64
a
Definition: plan.py:54
d
Definition: setup.py:4
void globalAdjustment(std::vector< SingleJointTrajectory > &t2, robot_trajectory::RobotTrajectory &trajectory, std::vector< double > &time_diff)