From 686f698bea58dcc943fc63e7ff9cbe755a5f1cf0 Mon Sep 17 00:00:00 2001 From: Steve Tonneau <stonneau@laas.fr> Date: Wed, 5 Apr 2017 13:33:03 +0200 Subject: [PATCH] vel acc constraints for bezier curves --- include/spline/bezier_curve.h | 73 +++++++++++++++++++++++++++------- python/spline_python.cpp | 27 +++++++++++++ src/tests/spline_test/Main.cpp | 34 +++++++++++++++- 3 files changed, 119 insertions(+), 15 deletions(-) diff --git a/include/spline/bezier_curve.h b/include/spline/bezier_curve.h index 73fe61b..5285c4d 100644 --- a/include/spline/bezier_curve.h +++ b/include/spline/bezier_curve.h @@ -12,6 +12,7 @@ #include "curve_abc.h" #include "bernstein.h" +#include "curve_constraint.h" #include "MathDefs.h" @@ -34,7 +35,9 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> typedef Point point_t; typedef Time time_t; typedef Numeric num_t; + typedef curve_constraints<point_t> curve_constraints_t; typedef std::vector<point_t,Eigen::aligned_allocator<point_t> > t_point_t; + typedef typename t_point_t::const_iterator cit_point_t; typedef bezier_curve<Time, Numeric, Dim, Safe, Point > bezier_curve_t; /* Constructors - destructors */ @@ -49,18 +52,36 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> , size_(std::distance(PointsBegin, PointsEnd)) , degree_(size_-1) , bernstein_(spline::makeBernstein<num_t>(degree_)) - { + { assert(bernstein_.size() == size_); In it(PointsBegin); if(Safe && (size_<1 || minBound >= maxBound)) - { throw std::out_of_range("can't create bezier min bound is higher than max bound"); // TODO - } - for(; it != PointsEnd; ++it) - { - pts_.push_back(*it); - } - } + for(; it != PointsEnd; ++it) + pts_.push_back(*it); + } + + + ///\brief Constructor + /// This constructor will add 4 points (2 after the first one, 2 before the last one) + /// to ensure that velocity and acceleration constraints are respected + ///\param PointsBegin, PointsEnd : the points parametering the Bezier curve + ///\param constraints : constraints applying on start / end velocities and acceleration + /// + template<typename In> + bezier_curve(In PointsBegin, In PointsEnd, const curve_constraints_t& constraints, const time_t minBound=0, const time_t maxBound=1) + : minBound_(minBound) + , maxBound_(maxBound) + , size_(std::distance(PointsBegin, PointsEnd)+4) + , degree_(size_-1) + , bernstein_(spline::makeBernstein<num_t>(degree_)) + { + if(Safe && (size_<1 || minBound >= maxBound)) + throw std::out_of_range("can't create bezier min bound is higher than max bound"); + t_point_t updatedList = add_constraints<In>(PointsBegin, PointsEnd, constraints); + for(cit_point_t cit = updatedList.begin(); cit != updatedList.end(); ++cit) + pts_.push_back(*cit); + } ///\brief Destructor ~bezier_curve() @@ -86,8 +107,8 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> throw std::out_of_range("can't evaluate bezier curve, out of range"); // TODO } else - { - num_t dt = (1 - nT); + { + num_t dt = (1 - nT); switch(size_) { case 1 : @@ -106,7 +127,7 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> + 3 * pts_[2] * nT * nT * dt + pts_[3] * nT * nT *nT; default : - return evalBernstein(dt); + return evalBernstein(nT); break; } } @@ -154,7 +175,7 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> /// \param order : order of the derivative /// \param t : the time when to evaluate the spine /// \param return : the value x(t) - virtual point_t derivate(const time_t t, const std::size_t order) const + virtual point_t derivate(const time_t t, const std::size_t order) const { bezier_curve_t deriv =compute_derivate(order); return deriv(t); @@ -169,17 +190,41 @@ struct bezier_curve : public curve_abc<Time, Numeric, Dim, Safe, Point> typename t_point_t::const_iterator pts_it = pts_.begin(); for(typename std::vector<Bern<Numeric> >::const_iterator cit = bernstein_.begin(); cit !=bernstein_.end(); ++cit, ++pts_it) - { res += cit->operator()(u) * (*pts_it); - } return res; } const t_point_t& waypoints() const {return pts_;} + private: + template<typename In> + t_point_t add_constraints(In PointsBegin, In PointsEnd, const curve_constraints_t& constraints) + { + t_point_t res; + point_t P0, P1, P2, P_n_2, P_n_1, PN; + P0 = *PointsBegin; PN = *(PointsEnd-1); + P1 = P0+ constraints.init_vel / degree_; + P_n_1 = PN -constraints.end_vel / degree_; + P2 = constraints.init_acc / (degree_ * (degree_-1)) + 2* P1 - P0; + P_n_2 = constraints.end_acc / (degree_ * (degree_-1)) + 2* P_n_1 - PN; + + res.push_back(P0); + res.push_back(P1); + res.push_back(P2); + + for(In it = PointsBegin+1; it != PointsEnd-1; ++it) + res.push_back(*it); + + res.push_back(P_n_2); + res.push_back(P_n_1); + res.push_back(PN); + return res; + } + /*Operations*/ /*Helpers*/ + public: virtual time_t min() const{return minBound_;} virtual time_t max() const{return maxBound_;} /*Helpers*/ diff --git a/python/spline_python.cpp b/python/spline_python.cpp index 2762f7d..3dfeb50 100644 --- a/python/spline_python.cpp +++ b/python/spline_python.cpp @@ -38,6 +38,7 @@ typedef std::vector<waypoint_t, Eigen::aligned_allocator<point_t> > t_waypoint_t typedef spline::spline_deriv_constraint <real, real, 3, true, point_t, t_point_t> spline_deriv_constraint_t; typedef spline::curve_constraints<point_t> curve_constraints_t; +typedef spline::curve_constraints<point6_t> curve_constraints6_t; /*** TEMPLATE SPECIALIZATION FOR PYTHON ****/ EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(bezier_t) @@ -72,6 +73,19 @@ bezier_t* wrapBezierConstructorBounds(const point_list_t& array, const real lb, return new bezier_t(asVector.begin(), asVector.end(), lb, ub); } +bezier_t* wrapBezierConstructorConstraints(const point_list_t& array, const curve_constraints_t& constraints) +{ + t_point_t asVector = vectorFromEigenArray<point_list_t, t_point_t>(array); + return new bezier_t(asVector.begin(), asVector.end(), constraints); +} + + +bezier_t* wrapBezierConstructorConstraintsBounds(const point_list_t& array, const curve_constraints_t& constraints, const real lb, const real ub) +{ + t_point_t asVector = vectorFromEigenArray<point_list_t, t_point_t>(array); + return new bezier_t(asVector.begin(), asVector.end(), constraints, lb, ub); +} + bezier6_t* wrapBezierConstructor6(const point_list6_t& array) { t_point6_t asVector = vectorFromEigenArray<point_list6_t, t_point6_t>(array); @@ -85,6 +99,19 @@ bezier6_t* wrapBezierConstructorBounds6(const point_list6_t& array, const real l return new bezier6_t(asVector.begin(), asVector.end(), lb, ub); } +bezier6_t* wrapBezierConstructor6Constraints(const point_list6_t& array, const curve_constraints6_t& constraints) +{ + t_point6_t asVector = vectorFromEigenArray<point_list6_t, t_point6_t>(array); + return new bezier6_t(asVector.begin(), asVector.end(), constraints); +} + + +bezier6_t* wrapBezierConstructorBounds6Constraints(const point_list6_t& array, const curve_constraints6_t& constraints, const real lb, const real ub) +{ + t_point6_t asVector = vectorFromEigenArray<point_list6_t, t_point6_t>(array); + return new bezier6_t(asVector.begin(), asVector.end(), constraints, lb, ub); +} + spline_curve_t* wrapSplineConstructor(const coeff_t& array) { return new spline_curve_t(array, 0., 1.); diff --git a/src/tests/spline_test/Main.cpp b/src/tests/spline_test/Main.cpp index 2f2cd2d..6579c1a 100644 --- a/src/tests/spline_test/Main.cpp +++ b/src/tests/spline_test/Main.cpp @@ -60,7 +60,7 @@ void ComparePoints(const Eigen::VectorXd& pt1, const Eigen::VectorXd& pt2, const if((pt1-pt2).norm() > margin && !notequal) { error = true; - std::cout << errmsg << pt1 << " ; " << pt2 << std::endl; + std::cout << errmsg << pt1.transpose() << " ; " << pt2.transpose() << std::endl; } } @@ -247,6 +247,37 @@ void BezierDerivativeCurveTest(bool& error) ComparePoints(point_t::Zero(), cf3.derivate(0.,100), errMsg, error); } +void BezierDerivativeCurveConstraintTest(bool& error) +{ + std::string errMsg("In test BezierDerivativeCurveConstraintTest ; unexpected result for x "); + point_t a(1,2,3); + point_t b(2,3,4); + point_t c(3,4,5); + + bezier_curve_t::curve_constraints_t constraints; + constraints.init_vel = point_t(-1,-1,-1); + constraints.init_acc = point_t(-2,-2,-2); + constraints.end_vel = point_t(-10,-10,-10); + constraints.end_acc = point_t(-20,-20,-20); + + std::vector<point_t> params; + params.push_back(a); + params.push_back(b); + + params.push_back(c); + bezier_curve_t cf3(params.begin(), params.end(), constraints); + + assert(cf3.degree_ == params.size() + 3); + assert(cf3.size_ == params.size() + 4); + + ComparePoints(a, cf3(0), errMsg, error); + ComparePoints(c, cf3(1), errMsg, error); + ComparePoints(constraints.init_vel, cf3.derivate(0.,1), errMsg, error); + ComparePoints(constraints.end_vel , cf3.derivate(1.,1), errMsg, error); + ComparePoints(constraints.init_acc, cf3.derivate(0.,2), errMsg, error); + ComparePoints(constraints.end_vel, cf3.derivate(1.,1), errMsg, error); + ComparePoints(constraints.end_acc, cf3.derivate(1.,2), errMsg, error); +} /*Exact Cubic Function tests*/ @@ -599,6 +630,7 @@ int main(int /*argc*/, char** /*argv[]*/) EffectorSplineRotationWayPointRotationTest(error); BezierCurveTest(error); BezierDerivativeCurveTest(error); + BezierDerivativeCurveConstraintTest(error); if(error) { std::cout << "There were some errors\n"; -- GitLab