14 #include "../../include/ecl/manipulators/waypoint.hpp" 15 #include "../../include/ecl/manipulators/trajectory.hpp" 39 unsigned int n = waypoints.size() - 1;
46 result = validateWaypoints(5);
51 result = initialiseWaypointDurations();
59 for (
unsigned int j = 0; j < dimension(); ++j)
61 spline_functions[j].resize(3, NULL);
69 bool splines_constrained =
false;
70 while (!splines_constrained)
72 tension_splines = generateTensionSplines(tension, 0.0);
77 splines_constrained =
true;
81 for (
unsigned int i = 1; i < domain.
size() - 1; ++i)
83 for (
unsigned int j = 0; j < dimension(); ++j)
85 double accel = fabs(tension_splines[j].dderivative(domain[i]));
93 if (accel > max_accelerations[j])
95 splines_constrained =
false;
96 double slope_before = fabs(
97 (waypoints[i].angles()[j] - waypoints[i - 1].angles()[j]) / waypoints[i - 1].duration());
98 double slope_after = fabs(
99 (waypoints[i + 1].angles()[j] - waypoints[i].angles()[j]) / waypoints[i].duration());
102 if (slope_before > slope_after)
104 waypoints[i - 1].duration(waypoints[i - 1].duration() * 1.1);
108 waypoints[i].duration(waypoints[i].duration() * 1.1);
121 if (!waypoints[0].rates_configured())
125 if (!waypoints[n].rates_configured())
133 double leading_quintic_time = 0.0;
134 bool quintic_constrained =
false;
135 while (!quintic_constrained)
137 quintic_constrained =
true;
138 for (
unsigned int i = 1; i <= 5; ++i)
140 double t = i * waypoints[0].duration() / 10;
142 tension_splines = generateTensionSplines(tension, t);
143 for (
unsigned int j = 0; j < dimension(); ++j)
146 double y_dot = tension_splines[j].derivative(2 * t);
147 double y = tension_splines[j](2 * t);
149 double y_0 = waypoints[0].angles()[j];
150 double y_0_dot = waypoints[0].rates()[j];
151 leading_quintics[j] = QuinticPolynomial::Interpolation(0.0, y_0, y_0_dot, 0.0, 2 * t, y, y_dot, 0.0);
167 < fabs(max_accelerations[j]))
169 < fabs(max_accelerations[j])))
171 if (j == dimension() - 1)
173 leading_quintic_time = 2 * t;
175 quintic_constrained =
true;
183 quintic_constrained =
false;
188 if (!quintic_constrained)
191 waypoints[0].duration(waypoints[0].duration() * 1.1);
200 double trailing_quintic_time_0 = 0.0;
201 double trailing_quintic_time_f = 0.0;
202 quintic_constrained =
false;
203 while (!quintic_constrained)
205 quintic_constrained =
true;
206 tension_splines = generateTensionSplines(tension, leading_quintic_time / 2);
207 for (
unsigned int i = 1; i <= 5; ++i)
209 double t = i * waypoints[n - 1].duration() / 10;
210 double t_f = tension_splines[0].domain().
back();
211 for (
unsigned int j = 0; j < dimension(); ++j)
213 double y_dot = tension_splines[j].derivative(t_f - t);
214 double y = tension_splines[j](t_f - t);
215 double y_f = waypoints[n].angles()[j];
216 double y_f_dot = waypoints[n].rates()[j];
217 trailing_quintics[j] = QuinticPolynomial::Interpolation(t_f - t, y, y_dot, 0.0, t_f + t, y_f, y_f_dot, 0.0);
233 < fabs(max_accelerations[j]))
235 < fabs(max_accelerations[j])))
237 if (j == dimension() - 1)
239 trailing_quintic_time_0 = tension_splines[j].domain().
back() - t;
240 trailing_quintic_time_f = tension_splines[j].domain().
back() + t;
242 quintic_constrained =
true;
250 quintic_constrained =
false;
255 if (!quintic_constrained)
257 waypoints[n - 1].duration(waypoints[n - 1].duration() * 1.1);
271 trajectory_duration = trailing_quintic_time_f;
272 for (
unsigned int j = 0; j < dimension(); ++j)
278 trailing_quintics[j]);
284 if (!validateWaypoints(2))
287 "Not all the waypoint maximum rates have been specified correctly (must be > 0.0).");
289 if (!initialiseWaypointDurations())
298 for (
unsigned int j = 0; j < dimension(); ++j)
300 spline_functions[j].resize(1, NULL);
307 bool splines_constrained =
false;
308 int n = waypoints.size() - 1;
309 while (!splines_constrained)
313 splines = generateLinearSplines();
314 splines_constrained =
true;
315 #ifdef DEBUG_LINEAR_INTERPOLATION 316 std::cout <<
"Linear Interpolation: spline generation success" << std::endl;
326 #ifdef DEBUG_LINEAR_INTERPOLATION 327 std::cout <<
"Linear Interpolation: spline generation failed trying to create pre-pseudo, stretching first segment" << std::endl;
329 waypoints[0].duration(waypoints[0].duration() * 1.1);
331 else if (e.
data() == 1)
333 #ifdef DEBUG_LINEAR_INTERPOLATION 334 std::cout <<
"Linear Interpolation: spline generation failed, stretching at corner " << e.
data() << std::endl;
336 waypoints[0].duration(waypoints[0].duration() * 1.1);
338 else if (e.
data() >= n + 1)
340 #ifdef DEBUG_LINEAR_INTERPOLATION 341 std::cout <<
"Linear Interpolation: spline generation failed, stretching at corner " << e.
data() << std::endl;
343 waypoints[n - 1].duration(waypoints[n - 1].duration() * 1.1);
345 else if (e.
data() >= n + 2)
348 waypoints[n - 1].duration(waypoints[n - 1].duration() * 1.1);
349 #ifdef DEBUG_LINEAR_INTERPOLATION 350 std::cout <<
"Linear Interpolation: spline generation failed trying to create post-pseudo, stretching last segment" << std::endl;
355 #ifdef DEBUG_LINEAR_INTERPOLATION 356 std::cout <<
"Linear Interpolation: spline generation failed, stretching at corner " << e.
data() << std::endl;
358 waypoints[e.
data() - 2].duration(waypoints[e.
data() - 2].duration() * 1.05);
359 waypoints[e.
data() - 1].duration(waypoints[e.
data() - 1].duration() * 1.05);
367 trajectory_duration = splines[0].domain().
back() - splines[0].domain().
front();
368 for (
unsigned int j = 0; j < dimension(); ++j)
382 double t_f = spline_functions[joint][spline_functions[joint].size() - 1]->domain()[1];
385 for (i = 0; i < spline_functions[joint].size(); ++i)
387 if (time <= spline_functions[joint][i]->domain()[1])
389 return (*(spline_functions[joint][i]))(time);
393 return (*(spline_functions[joint][spline_functions[joint].
size() - 1]))(t_f);
400 double t_f = spline_functions[joint][spline_functions[joint].size() - 1]->domain()[1];
403 for (i = 0; i < spline_functions[joint].size(); ++i)
405 if (time <= spline_functions[joint][i]->domain()[1])
407 return spline_functions[joint][i]->derivative(time);
412 return spline_functions[joint][spline_functions[joint].size() - 1]->derivative(t_f);
419 double t_f = spline_functions[joint][spline_functions[joint].size() - 1]->domain()[1];
422 for (i = 0; i < spline_functions[joint].size(); ++i)
424 if (time <= spline_functions[joint][i]->domain()[1])
426 return spline_functions[joint][i]->dderivative(time);
431 return spline_functions[joint][spline_functions[joint].size() - 1]->dderivative(t_f);
441 unsigned int n = waypoints.size() - 1;
442 if (n + 1 < min_no_waypoints)
447 for (
unsigned int i = 0; i < n; ++i)
449 for (
unsigned int j = 0; j < waypoints[i].nominalRates().size(); ++j)
451 if (waypoints[i].nominalRates()[j] <= 0.0)
463 unsigned int n = waypoints.size() - 1;
470 for (
unsigned int i = 0; i < n; ++i)
472 double max_duration = 0.0;
473 for (
unsigned int j = 0; j < dimension(); ++j)
475 double distance = fabs(waypoints[i + 1].angles()[j] - waypoints[i].angles()[j]);
476 if (waypoints[i].nominalRates()[j] != 0.0)
478 double segment_duration = distance / waypoints[i].nominalRates()[j];
479 if (segment_duration > max_duration)
481 max_duration = segment_duration;
485 if (max_duration > waypoints[i].duration())
487 waypoints[i].duration(max_duration);
489 if (waypoints[i].duration() == 0.0)
499 for (
unsigned int joint = 0; joint < dimension(); ++joint)
501 for (
unsigned int function = 0;
function < spline_functions[joint].size(); ++
function)
503 if (spline_functions[joint][
function] != NULL)
505 delete spline_functions[joint][
function];
506 spline_functions[joint][
function] = NULL;
509 spline_functions[joint].clear();
515 double total_time = 0.0;
517 for (
unsigned int i = 0; i < waypoints.size() - 1; ++i)
519 total_time += waypoints[i].duration();
523 trajectory_duration = total_time;
534 unsigned int n = waypoints.size() - 1;
542 if (!waypoints[0].rates_configured())
546 if (!waypoints[n].rates_configured())
579 std::vector<LinearFunction> initial_tangents;
580 std::vector<double> initial_angles, initial_rates;
581 for (
unsigned int j = 0; j < dimension(); ++j)
583 initial_angles.push_back(waypoints[0].angles()[j]);
584 initial_rates.push_back(waypoints[0].rates()[j]);
585 initial_tangents.push_back(LinearFunction::PointSlopeForm(0, initial_angles[j], initial_rates[j]));
587 std::vector<CartesianPoint2d, Eigen::aligned_allocator<CartesianPoint2d> > pseudo_points(dimension());
588 std::vector<LinearFunction> nominal_rate_lines(dimension());
590 double t_pullback = 0.001;
591 double t_pullback_max_ = waypoints[0].duration();
592 double t_pre_intersect_duration = 0.0;
593 bool acceleration_constraint_broken =
true;
594 while (acceleration_constraint_broken && (t_pullback <= t_pullback_max_))
598 t_pre_intersect_duration = t_pullback_max_ / 2;
599 for (
unsigned int j = 0; j < dimension(); ++j)
601 LinearFunction nominal_rate_line = LinearFunction::PointSlopeForm(
602 t_pullback, initial_angles[j], -1 *
ecl::psign(initial_rates[j]) * waypoints[0].nominalRates()[j]);
603 CartesianPoint2d pseudo_point = LinearFunction::Intersection(initial_tangents[j], nominal_rate_line);
604 if (pseudo_point.x() < t_pre_intersect_duration)
606 t_pre_intersect_duration = pseudo_point.x();
608 nominal_rate_lines[j] = nominal_rate_line;
610 acceleration_constraint_broken =
false;
611 for (
unsigned int j = 0; j < dimension(); ++j)
613 CartesianPoint2d pseudo_point(t_pre_intersect_duration, initial_tangents[j](t_pre_intersect_duration));
615 double pseudo_point_duration = t_pullback + waypoints[0].duration() - t_pre_intersect_duration;
618 for (
unsigned int i = 1; i <= 5; ++i)
620 double t_l = t_pre_intersect_duration - i * t_pre_intersect_duration / 5.0;
621 double t_r = t_pre_intersect_duration + i * pseudo_point_duration / 10.0;
622 LinearFunction segment = LinearFunction::Interpolation(pseudo_point.x(), pseudo_point.y(),
623 t_pullback + waypoints[0].duration(),
624 waypoints[1].angles()[j]);
625 double y_0 = initial_tangents[j](t_l);
626 double y_0_dot = initial_tangents[j].
derivative(t_l);
627 double y = segment(t_r);
629 QuinticPolynomial quintic = QuinticPolynomial::Interpolation(t_l, y_0, y_0_dot, 0.0, t_r, y, y_dot, 0.0);
630 if ((fabs(CubicPolynomial::Maximum(t_l, t_r, quintic.
derivative().derivative())) < fabs(max_accelerations[j]))
631 && (fabs(CubicPolynomial::Minimum(t_l, t_r, quintic.
derivative().derivative())) < fabs(max_accelerations[j])))
633 acceleration_constraint_broken =
false;
638 #ifdef DEBUG_LINEAR_INTERPOLATION 639 std::cout <<
"Linear Interpolation: pre psuedo point failed with acceleration checks [" << t_pre_intersect_duration <<
"][" << t_pullback <<
"]" << std::endl;
641 acceleration_constraint_broken =
true;
645 t_pullback = t_pullback * 2;
647 if (acceleration_constraint_broken)
651 pre_pseudo_waypoint.
duration(t_pullback + waypoints[0].duration() - t_pre_intersect_duration);
652 for (
unsigned int j = 0; j < dimension(); ++j)
654 pre_pseudo_waypoint.
angles()[j] = initial_tangents[j](t_pre_intersect_duration);
656 #ifdef DEBUG_LINEAR_INTERPOLATION 657 std::cout <<
"Linear Interpolation: pre psuedo point done!" << std::endl;
658 std::cout <<
" : angles " << pre_pseudo_waypoint.
angles() << std::endl;
659 std::cout <<
" : pre pseudo duration " << t_pre_intersect_duration << std::endl;
660 std::cout <<
" : modified first waypoint duration " << pre_pseudo_waypoint.
duration() << std::endl;
666 std::vector<double> final_angles, final_rates;
667 for (
unsigned int j = 0; j < dimension(); ++j)
669 final_angles.push_back(waypoints[n].angles()[j]);
670 final_rates.push_back(waypoints[n].rates()[j]);
671 nominal_rate_lines[j] = LinearFunction::PointSlopeForm(
672 0, final_angles[j], -1 *
ecl::psign(final_rates[j]) * waypoints[n - 1].nominalRates()[j]);
674 std::vector<LinearFunction> final_tangents(dimension());
676 double t_pullforward = 0.001;
677 double t_pullforward_max_ = waypoints[n - 1].duration();
678 double t_post_intersect_duration = 0.0;
679 acceleration_constraint_broken =
true;
680 while (acceleration_constraint_broken && (t_pullforward <= t_pullforward_max_))
683 t_post_intersect_duration = 0.0;
684 for (
unsigned int j = 0; j < dimension(); ++j)
686 LinearFunction final_tangent = LinearFunction::PointSlopeForm(t_pullforward, final_angles[j], final_rates[j]);
687 final_tangents[j] = final_tangent;
688 CartesianPoint2d pseudo_point = LinearFunction::Intersection(final_tangents[j], nominal_rate_lines[j]);
689 if (pseudo_point.x() > t_post_intersect_duration)
691 t_post_intersect_duration = pseudo_point.x();
695 acceleration_constraint_broken =
false;
696 for (
unsigned int j = 0; j < dimension(); ++j)
698 CartesianPoint2d pseudo_point(t_post_intersect_duration, final_tangents[j](t_post_intersect_duration));
699 double pseudo_point_duration = t_pullforward - t_post_intersect_duration;
700 for (
unsigned int i = 1; i <= 5; ++i)
702 double t_l = t_post_intersect_duration - i * (waypoints[n - 1].duration() + t_post_intersect_duration) / 10.0;
703 double t_r = t_post_intersect_duration + i * pseudo_point_duration / 5.0;
704 LinearFunction segment = LinearFunction::Interpolation(-waypoints[n - 1].duration(),
705 waypoints[n - 1].angles()[j], pseudo_point.x(),
707 double y_0 = segment(t_l);
709 double y = final_tangents[j](t_r);
710 double y_dot = final_tangents[j].derivative(t_r);
711 QuinticPolynomial quintic = QuinticPolynomial::Interpolation(t_l, y_0, y_0_dot, 0.0, t_r, y, y_dot, 0.0);
712 if ((fabs(CubicPolynomial::Maximum(t_l, t_r, quintic.
derivative().derivative())) < fabs(max_accelerations[j]))
713 && (fabs(CubicPolynomial::Minimum(t_l, t_r, quintic.
derivative().derivative())) < fabs(max_accelerations[j])))
715 acceleration_constraint_broken =
false;
720 #ifdef DEBUG_LINEAR_INTERPOLATION 721 std::cout <<
"Linear Interpolation: post psuedo point failed with acceleration checks [" << t_post_intersect_duration <<
"][" << t_pullforward <<
"]" << std::endl;
723 acceleration_constraint_broken =
true;
727 t_pullforward = t_pullforward * 2;
729 if (acceleration_constraint_broken)
733 post_pseudo_waypoint.
duration(t_pullforward - t_post_intersect_duration);
734 for (
unsigned int j = 0; j < dimension(); ++j)
736 post_pseudo_waypoint.
angles()[j] = final_tangents[j](t_post_intersect_duration);
738 #ifdef DEBUG_LINEAR_INTERPOLATION 739 std::cout <<
"Linear Interpolation: post psuedo point done!" << std::endl;
740 std::cout <<
" : angles " << post_pseudo_waypoint.
angles() << std::endl;
741 std::cout <<
" : modified last point duration " << waypoints[n-1].duration() + t_post_intersect_duration << std::endl;
742 std::cout <<
" : post pseudo duration " << post_pseudo_waypoint.
duration() << std::endl;
750 waypoint_times[0] = 0.0;
751 waypoint_times[1] = t_pre_intersect_duration;
752 waypoint_times[2] = t_pre_intersect_duration + pre_pseudo_waypoint.
duration();
753 for (
unsigned int i = 2; i < n; ++i)
755 waypoint_times[i + 1] = waypoint_times[i] + waypoints[i - 1].duration();
757 waypoint_times[n + 1] = waypoint_times[n] + waypoints[n - 1].duration() + t_post_intersect_duration;
758 waypoint_times[n + 2] = waypoint_times[n + 1] + post_pseudo_waypoint.
duration();
760 #ifdef DEBUG_LINEAR_INTERPOLATION 761 std::cout <<
"Linear Interpolation: waypoint time estimates before interpolation: " << waypoint_times << std::endl;
764 for (
unsigned int j = 0; j < dimension(); ++j)
769 values[0] = waypoints[0].angles()[j];
770 values[1] = pre_pseudo_waypoint.
angles()[j];
771 for (
unsigned int i = 2; i <= n; ++i)
773 values[i] = waypoints[i - 1].angles()[j];
775 values[n + 1] = post_pseudo_waypoint.
angles()[j];
776 values[n + 2] = waypoints[n].angles()[j];
777 #ifdef DEBUG_LINEAR_INTERPOLATION 778 std::cout <<
"Linear Interpolation: values[" << j <<
"]: " << values << std::endl;
793 #ifdef DEBUG_LINEAR_INTERPOLATION 794 for (
unsigned int j = 0; j < dimension(); ++j)
796 std::cout <<
"Linear Interpolation: discretised domain [" << j <<
"]: " << splines[j].domain() << std::endl;
806 unsigned int n = waypoints.size() - 1;
809 waypoint_times[0] = initial_time;
810 for (
unsigned int i = 1; i < n + 1; ++i)
812 waypoint_times[i] = waypoint_times[i - 1] + waypoints[i - 1].duration();
815 for (
unsigned int j = 0; j < dimension(); ++j)
817 for (
unsigned int i = 0; i < n + 1; ++i)
819 values[i] = waypoints[i].angles()[j];
823 return tension_splines;
static blueprints::C2TensionSpline Natural(const Array< double > &x_set, const Array< double > &y_set, const double &tau) ecl_assert_throw_decl(StandardException)
Primary template for waypoints.
#define ecl_assert_throw(expression, exception)
Parameter< double > duration
Timestamp for this waypoint.
Array< double > & angles()
Handle to the joint angle array.
const Data & data() const
ecl_geometry_PUBLIC int size(const Trajectory2D &trajectory)
int psign(const Scalar &x)
static SmoothLinearSpline Interpolation(const Array< double > &x_data, const Array< double > &y_data, double a_max)
Primary template for manipulator trajectories.
WayPoint specialisation with joint (motor) angle storage format.
ecl_geometry_PUBLIC double distance(const Pose2D &pose, const Trajectory2D &trajectory)
Polynomial< N-1 > derivative() const