39 #include <rclcpp/logger.hpp>
40 #include <rclcpp/logging.hpp>
43 static const double VLIMIT = 1.0;
44 static const double ALIMIT = 1.0;
48 static const rclcpp::Logger LOGGER =
49 rclcpp::get_logger(
"moveit_trajectory_processing.iterative_spline_parameterization");
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);
74 std::vector<double>& time_diff);
81 const double max_velocity_scaling_factor,
82 const double max_acceleration_scaling_factor)
const
84 if (trajectory.
empty())
90 RCLCPP_ERROR(LOGGER,
"It looks like the planner did not set "
91 "the group the plan was computed for");
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;
100 unsigned int num_joints =
group->getVariableCount();
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)
107 RCLCPP_DEBUG(LOGGER,
"A max_velocity_scaling_factor of 0.0 was specified, defaulting to %f instead.",
108 velocity_scaling_factor);
112 RCLCPP_WARN(LOGGER,
"Invalid max_velocity_scaling_factor %f specified, defaulting to %f instead.",
113 max_velocity_scaling_factor, velocity_scaling_factor);
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)
119 RCLCPP_DEBUG(LOGGER,
"A max_acceleration_scaling_factor of 0.0 was specified, defaulting to %f instead.",
120 acceleration_scaling_factor);
124 RCLCPP_WARN(LOGGER,
"Invalid max_acceleration_scaling_factor %f specified, defaulting to %f instead.",
125 max_acceleration_scaling_factor, acceleration_scaling_factor);
137 moveit::core::RobotStatePtr p0, p1;
142 for (
unsigned int j = 0; j < num_joints; ++j)
145 (9 * p0->getVariablePosition(idx[j]) + 1 * p1->getVariablePosition(idx[j])) / 10);
153 for (
unsigned int j = 0; j < num_joints; ++j)
156 (1 * p0->getVariablePosition(idx[j]) + 9 * p1->getVariablePosition(idx[j])) / 10);
167 std::vector<SingleJointTrajectory> t2(num_joints);
169 for (
unsigned int j = 0; j < num_joints; ++j)
172 t2[j].positions_.resize(num_points, 0.0);
173 for (
unsigned int i = 0; i < num_points; ++i)
175 t2[j].positions_[i] = trajectory.
getWayPointPtr(i)->getVariablePosition(idx[j]);
179 t2[j].velocities_.resize(num_points, 0.0);
182 t2[j].velocities_[0] = trajectory.
getWayPointPtr(0)->getVariableVelocity(idx[j]);
184 t2[j].velocities_[num_points - 1] = trajectory.
getWayPointPtr(num_points - 1)->getVariableVelocity(idx[j]);
187 t2[j].accelerations_.resize(num_points, 0.0);
188 t2[j].initial_acceleration_ = 0.0;
189 t2[j].final_acceleration_ = 0.0;
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_;
201 t2[j].min_velocity_ = -VLIMIT;
206 if (t2[j].min_velocity_ == 0.0)
207 t2[j].min_velocity_ = -t2[j].max_velocity_;
209 t2[j].max_velocity_ *= velocity_scaling_factor;
210 t2[j].min_velocity_ *= velocity_scaling_factor;
212 t2[j].max_acceleration_ = ALIMIT;
213 t2[j].min_acceleration_ = -ALIMIT;
218 if (t2[j].min_acceleration_ == 0.0)
219 t2[j].min_acceleration_ = -t2[j].max_acceleration_;
221 t2[j].max_acceleration_ *= acceleration_scaling_factor;
222 t2[j].min_acceleration_ *= acceleration_scaling_factor;
225 if (t2[j].max_velocity_ <= 0.0 || t2[j].max_acceleration_ <= 0.0)
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_);
233 if (t2[j].min_velocity_ >= 0.0 || t2[j].min_acceleration_ >= 0.0)
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_);
246 RCLCPP_ERROR(LOGGER,
"number of waypoints %d, needs to be greater than 3.\n", num_points);
249 for (
unsigned int j = 0; j < num_joints; ++j)
251 if (t2[j].velocities_[0] > t2[j].max_velocity_ || t2[j].velocities_[0] < t2[j].min_velocity_)
253 RCLCPP_ERROR(LOGGER,
"Initial velocity %f out of bounds\n", t2[j].velocities_[0]);
256 else if (t2[j].velocities_[num_points - 1] > t2[j].max_velocity_ ||
257 t2[j].velocities_[num_points - 1] < t2[j].min_velocity_)
259 RCLCPP_ERROR(LOGGER,
"Final velocity %f out of bounds\n", t2[j].velocities_[num_points - 1]);
262 else if (t2[j].accelerations_[0] > t2[j].max_acceleration_ || t2[j].accelerations_[0] < t2[j].min_acceleration_)
264 RCLCPP_ERROR(LOGGER,
"Initial acceleration %f out of bounds\n", t2[j].accelerations_[0]);
267 else if (t2[j].accelerations_[num_points - 1] > t2[j].max_acceleration_ ||
268 t2[j].accelerations_[num_points - 1] < t2[j].min_acceleration_)
270 RCLCPP_ERROR(LOGGER,
"Final acceleration %f out of bounds\n", t2[j].accelerations_[num_points - 1]);
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_);
288 std::vector<double> time_factor(num_points - 1, 1.00);
289 for (
unsigned j = 0; j < num_joints; ++j)
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_);
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)
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_);
309 atfactor = (atfactor - 1.0) / 16.0 + 1.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);
321 for (
unsigned i = 0; i < num_points - 1; ++i)
322 time_diff[i] *= time_factor[i];
329 for (
unsigned int i = 1; i < num_points; ++i)
331 for (
unsigned int i = 0; i < num_points; ++i)
333 for (
unsigned int j = 0; j < num_joints; ++j)
335 trajectory.
getWayPointPtr(i)->setVariableVelocity(idx[j], t2[j].velocities_[i]);
336 trajectory.
getWayPointPtr(i)->setVariableAcceleration(idx[j], t2[j].accelerations_[i]);
340 if (add_points_ && (i == 1 || i == num_points - 2))
342 for (
unsigned int j = 0; j < num_joints; ++j)
343 trajectory.
getWayPointPtr(i)->setVariablePosition(idx[j], t2[j].positions_[i]);
353 const std::unordered_map<std::string, double>& ,
354 const std::unordered_map<std::string, double>& )
const
356 RCLCPP_ERROR(LOGGER,
"ISTP does not support this version of computeTimeStamps. Try TOTG instead?");
394 static void fit_cubic_spline(
const int n,
const double dt[],
const double x[],
double x1[],
double x2[])
397 const double x1_i = x1[0], x1_f = x1[n - 1];
402 double *
c = x1, *
d = x2;
404 d[0] = 3.0 * ((
x[1] -
x[0]) / dt[0] - x1_i) / dt[0];
405 for (i = 1; i <= n - 2; ++i)
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;
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;
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];
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;
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)
445 fit_cubic_spline(n, dt,
x, x1, x2);
447 double b0 = x2[n - 1];
451 fit_cubic_spline(n, dt,
x, x1, x2);
453 double b2 = x2[n - 1];
457 x[1] =
x[0] + ((
x[2] -
x[0]) / (a2 - a0)) * (x2_i - a0);
459 x[n - 2] =
x[n - 3] + ((
x[n - 1] -
x[n - 3]) / (b2 - b0)) * (x2_f - b0);
467 static void init_times(
const int n,
double dt[],
const double x[],
const double max_velocity,
const double min_velocity)
470 for (i = 0; i < n - 1; ++i)
473 double dx =
x[i + 1] -
x[i];
475 time = (dx / max_velocity);
477 time = (dx / min_velocity);
478 time += std::numeric_limits<double>::epsilon();
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)
513 fit_cubic_spline(n, dt,
x, x1, x2);
516 for (i = 0; i < n - 1; ++i)
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)
529 for (i = 0; i < n - 1; ++i)
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)
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)
554 double tfactor2 = 1.00;
556 for (i = 0; i < n; ++i)
559 tfactor = x1[i] / max_velocity;
560 if (tfactor2 < tfactor)
562 tfactor = x1[i] / min_velocity;
563 if (tfactor2 < tfactor)
568 tfactor = sqrt(fabs(x2[i] / max_acceleration));
569 if (tfactor2 < tfactor)
574 tfactor = sqrt(fabs(x2[i] / min_acceleration));
575 if (tfactor2 < tfactor)
585 std::vector<double>& time_diff)
590 const unsigned int num_joints =
group->getVariableCount();
592 double gtfactor = 1.0;
593 for (
unsigned int j = 0; j < num_joints; ++j)
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)
603 for (
unsigned int i = 0; i < num_points - 1; ++i)
604 time_diff[i] *= gtfactor;
606 for (
unsigned int j = 0; j < num_joints; ++j)
608 fit_cubic_spline(num_points, &time_diff[0], &t2[j].positions_[0], &t2[j].velocities_[0], &t2[j].accelerations_[0]);
Definition of a kinematic model. This class is not thread safe, however multiple instances can be cre...
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a specific variable. Throw an exception of variable is not found.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
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.
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
RobotTrajectory & unwind()
moveit::core::RobotStatePtr & getWayPointPtr(std::size_t index)
RobotTrajectory & insertWayPoint(std::size_t index, const moveit::core::RobotState &state, double dt)
std::size_t getWayPointCount() const
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
IterativeSplineParameterization(bool add_points=true)
void globalAdjustment(std::vector< SingleJointTrajectory > &t2, robot_trajectory::RobotTrajectory &trajectory, std::vector< double > &time_diff)
bool acceleration_bounded_
double initial_acceleration_
std::vector< double > accelerations_
std::vector< double > positions_
std::vector< double > velocities_
double final_acceleration_