9 #ifndef _CLASS_BEZIERCURVE
10 #define _CLASS_BEZIERCURVE
30 template <
typename Time = double,
typename Numeric =
Time,
bool Safe =
false,
31 typename Point = Eigen::Matrix<Numeric, Eigen::Dynamic, 1> >
34 typedef Eigen::Matrix<Numeric, Eigen::Dynamic, 1>
vector_x_t;
39 typedef std::vector<point_t, Eigen::aligned_allocator<point_t> >
t_point_t;
61 template <
typename In>
64 : dim_(PointsBegin->size()),
68 size_(std::distance(PointsBegin, PointsEnd)),
72 if (bernstein_.size() != size_) {
73 throw std::invalid_argument(
"Invalid size of polynomial");
76 if (Safe && (size_ < 1 || T_max_ <= T_min_)) {
77 throw std::invalid_argument(
"can't create bezier min bound is higher than max bound");
79 for (; it != PointsEnd; ++it) {
80 if(Safe &&
static_cast<size_t>(it->size()) != dim_)
81 throw std::invalid_argument(
"All the control points must have the same dimension.");
82 control_points_.push_back(*it);
96 template <
typename In>
99 : dim_(PointsBegin->size()),
103 size_(std::distance(PointsBegin, PointsEnd) + 4),
107 if (Safe && (size_ < 1 || T_max_ <= T_min_)) {
108 throw std::invalid_argument(
"can't create bezier min bound is higher than max bound");
110 t_point_t updatedList = add_constraints<In>(PointsBegin, PointsEnd, constraints);
111 for (
cit_point_t cit = updatedList.begin(); cit != updatedList.end(); ++cit) {
112 if(Safe &&
static_cast<size_t>(cit->size()) != dim_)
113 throw std::invalid_argument(
"All the control points must have the same dimension.");
114 control_points_.push_back(*cit);
120 T_min_(other.T_min_),
121 T_max_(other.T_max_),
122 mult_T_(other.mult_T_),
124 degree_(other.degree_),
125 bernstein_(other.bernstein_),
126 control_points_(other.control_points_) {}
139 if (Safe & !(T_min_ <= t && t <= T_max_)) {
140 throw std::invalid_argument(
"can't evaluate bezier curve, time t is out of range");
143 return mult_T_ * control_points_[0];
145 return evalHorner(t);
158 bool equal = curves::isApprox<num_t>(T_min_, other.
min()) && curves::isApprox<num_t>(T_max_, other.
max()) &&
159 dim_ == other.
dim() && degree_ == other.
degree() && size_ == other.size_ &&
160 curves::isApprox<Numeric>(mult_T_, other.mult_T_) && bernstein_ == other.bernstein_;
161 if (!equal)
return false;
162 for (
size_t i = 0; i < size_; ++i) {
163 if (!control_points_.at(i).isApprox(other.control_points_.at(i), prec))
return false;
169 const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision())
const {
191 for (
typename t_point_t::const_iterator pit = control_points_.begin(); pit != control_points_.end() - 1; ++pit) {
192 derived_wp.push_back((
num_t)degree_ * (*(pit + 1) - (*pit)));
194 if (derived_wp.empty()) {
195 derived_wp.push_back(point_t::Zero(dim_));
197 bezier_curve_t deriv(derived_wp.begin(), derived_wp.end(), T_min_, T_max_, mult_T_ * (1. / (T_max_ - T_min_)));
220 point_t current_sum = point_t::Zero(dim_);
223 n_wp.push_back(current_sum);
224 for (
typename t_point_t::const_iterator pit = control_points_.begin(); pit != control_points_.end(); ++pit) {
226 n_wp.push_back(current_sum / new_degree);
228 bezier_curve_t integ(n_wp.begin(), n_wp.end(), T_min_, T_max_, mult_T_ * (T_max_ - T_min_));
250 const Numeric u = (t - T_min_) / (T_max_ - T_min_);
251 point_t res = point_t::Zero(dim_);
252 typename t_point_t::const_iterator control_points_it = control_points_.begin();
253 for (
typename std::vector<
Bern<Numeric> >::const_iterator cit = bernstein_.begin(); cit != bernstein_.end();
254 ++cit, ++control_points_it) {
255 res += cit->operator()(u) * (*control_points_it);
257 return res * mult_T_;
273 const Numeric u = (t - T_min_) / (T_max_ - T_min_);
274 typename t_point_t::const_iterator control_points_it = control_points_.begin();
279 point_t tmp = (*control_points_it) * u_op;
281 for (
unsigned int i = 1; i < degree_; i++, ++control_points_it) {
283 bc = bc * ((
num_t)(degree_ - i + 1)) / i;
284 tmp = (tmp + tn * bc * (*control_points_it)) * u_op;
286 return (tmp + tn * u * (*control_points_it)) * mult_T_;
289 const t_point_t& waypoints()
const {
return control_points_; }
291 const point_t waypointAtIndex(
const std::size_t index)
const {
293 if (index < control_points_.size()) {
294 waypoint = control_points_[index];
307 const Numeric u = (t - T_min_) / (T_max_ - T_min_);
308 t_point_t pts = deCasteljauReduction(waypoints(), u);
309 while (pts.size() > 1) {
310 pts = deCasteljauReduction(pts, u);
312 return pts[0] * mult_T_;
316 const Numeric u = (t - T_min_) / (T_max_ - T_min_);
317 return deCasteljauReduction(waypoints(), u);
330 if (u < 0 || u > 1) {
331 throw std::out_of_range(
"In deCasteljau reduction : u is not in [0;1]");
333 if (pts.size() == 1) {
338 for (
cit_point_t cit = pts.begin(); cit != (pts.end() - 1); ++cit) {
339 new_pts.push_back((1 - u) * (*cit) + u * (*(cit + 1)));
348 std::pair<bezier_curve_t, bezier_curve_t>
split(
const Numeric t)
const {
350 if (fabs(t - T_max_) < MARGIN) {
351 throw std::runtime_error(
"can't split curve, interval range is equal to original curve");
353 t_point_t wps_first(size_), wps_second(size_);
354 const Numeric u = (t - T_min_) / (T_max_ - T_min_);
356 wps_first[0] = casteljau_pts.front();
357 wps_second[degree_] = casteljau_pts.back();
359 while (casteljau_pts.size() > 1) {
360 casteljau_pts = deCasteljauReduction(casteljau_pts, u);
361 wps_first[id] = casteljau_pts.front();
362 wps_second[degree_ - id] = casteljau_pts.back();
365 bezier_curve_t c_first(wps_first.begin(), wps_first.end(), T_min_, t, mult_T_);
366 bezier_curve_t c_second(wps_second.begin(), wps_second.end(), t, T_max_, mult_T_);
367 return std::make_pair(c_first, c_second);
376 std::vector<bezier_curve_t>
curves;
378 for (
int i = 0; i < times.rows(); ++i) {
379 std::pair<bezier_curve_t, bezier_curve_t> pairsplit = current.split(times[i]);
380 curves.push_back(pairsplit.first);
381 current = pairsplit.second;
383 curves.push_back(current);
385 for (
typename std::vector<bezier_curve_t>::const_iterator cit =
curves.begin(); cit !=
curves.end(); ++cit) {
387 res.add_curve_ptr(ptr);
399 if (t1 < T_min_ || t1 > T_max_ || t2 < T_min_ || t2 > T_max_) {
400 throw std::out_of_range(
"In Extract curve : times out of bounds");
402 if (fabs(t1 - T_min_) < MARGIN && fabs(t2 - T_max_) < MARGIN)
404 return bezier_curve_t(waypoints().begin(), waypoints().end(), T_min_, T_max_, mult_T_);
406 if (fabs(t1 - T_min_) < MARGIN)
408 return split(t2).first;
410 if (fabs(t2 - T_max_) < MARGIN)
412 return split(t1).second;
414 std::pair<bezier_curve_t, bezier_curve_t> c_split = this->
split(t1);
415 return c_split.second.split(t2).first;
423 template <
typename In>
426 num_t T = T_max_ - T_min_;
427 num_t T_square = T * T;
428 point_t P0, P1, P2, P_n_2, P_n_1, PN;
430 PN = *(PointsEnd - 1);
431 P1 = P0 + constraints.init_vel * T / (
num_t)degree_;
432 P_n_1 = PN - constraints.end_vel * T / (
num_t)degree_;
433 P2 = constraints.init_acc * T_square / (
num_t)(degree_ * (degree_ - 1)) + 2 * P1 - P0;
434 P_n_2 = constraints.end_acc * T_square / (
num_t)(degree_ * (degree_ - 1)) + 2 * P_n_1 - PN;
438 for (In it = PointsBegin + 1; it != PointsEnd - 1; ++it) {
441 res.push_back(P_n_2);
442 res.push_back(P_n_1);
447 void check_conditions()
const {
448 if (control_points_.size() == 0) {
449 throw std::runtime_error(
450 "Error in bezier curve : there is no control points set / did you use empty constructor ?");
451 }
else if (dim_ == 0) {
452 throw std::runtime_error(
453 "Error in bezier curve : Dimension of points is zero / did you use empty constructor ?");
462 std::size_t
virtual dim()
const {
return dim_; };
465 virtual time_t min()
const {
return T_min_; }
468 virtual time_t max()
const {
return T_max_; }
471 virtual std::size_t
degree()
const {
return degree_; }
484 std::vector<Bern<Numeric> > bernstein_;
486 static const double MARGIN;
490 std::vector<point_t> ts;
491 ts.push_back(point_t::Zero(
dim));
496 friend class boost::serialization::access;
498 template <
class Archive>
499 void serialize(Archive& ar,
const unsigned int version) {
503 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(
curve_abc_t);
504 ar& boost::serialization::make_nvp(
"dim", dim_);
505 ar& boost::serialization::make_nvp(
"T_min", T_min_);
506 ar& boost::serialization::make_nvp(
"T_max", T_max_);
507 ar& boost::serialization::make_nvp(
"mult_T", mult_T_);
508 ar& boost::serialization::make_nvp(
"size", size_);
509 ar& boost::serialization::make_nvp(
"degree", degree_);
510 ar& boost::serialization::make_nvp(
"bernstein", bernstein_);
511 ar& boost::serialization::make_nvp(
"control_points", control_points_);
515 template <
typename Time,
typename Numeric,
bool Safe,
typename Po
int>
516 const double bezier_curve<Time, Numeric, Safe, Point>::MARGIN(0.001);
519 #endif //_CLASS_BEZIERCURVE