32using std::placeholders::_1;
33using std::placeholders::_2;
34using std::placeholders::_3;
40 const uint32_t spline_order)
41 : x_knots_(x_knots), spline_order_(spline_order) {
47 const Eigen::MatrixXd& constraint_matrix,
48 const Eigen::MatrixXd& constraint_boundary) {
49 return inequality_constraint_.
AddConstraint(constraint_matrix,
54 const Eigen::MatrixXd& constraint_matrix,
55 const Eigen::MatrixXd& constraint_boundary) {
61 const std::vector<double>& lower_bound,
62 const std::vector<double>& upper_bound) {
63 std::vector<double> filtered_lower_bound;
64 std::vector<double> filtered_upper_bound;
65 std::vector<double> filtered_lower_bound_x;
66 std::vector<double> filtered_upper_bound_x;
68 if (x_knots_.size() < 2) {
72 if (!FilterConstraints(x_coord, lower_bound, upper_bound,
73 &filtered_lower_bound_x, &filtered_lower_bound,
74 &filtered_upper_bound_x, &filtered_upper_bound)) {
78 const uint32_t num_params = spline_order_ + 1;
80 filtered_upper_bound.size() + filtered_lower_bound.size(),
81 (x_knots_.size() - 1) * num_params);
82 Eigen::MatrixXd inequality_boundary = Eigen::MatrixXd::Zero(
83 filtered_upper_bound.size() + filtered_lower_bound.size(), 1);
85 for (uint32_t i = 0; i < filtered_lower_bound.size(); ++i) {
86 uint32_t index = FindIndex(filtered_lower_bound_x[i]);
88 const double corrected_x = filtered_lower_bound_x[i] - x_knots_[index];
90 for (uint32_t j = 0; j < num_params; ++j) {
94 inequality_boundary(i, 0) = filtered_lower_bound[i];
97 for (uint32_t i = 0; i < filtered_upper_bound.size(); ++i) {
98 uint32_t index = FindIndex(filtered_upper_bound_x[i]);
99 const double corrected_x = filtered_upper_bound_x[i] - x_knots_[index];
101 for (uint32_t j = 0; j < num_params; ++j) {
103 j + index * num_params) = coef;
106 inequality_boundary(i + filtered_lower_bound.size(), 0) =
107 -filtered_upper_bound[i];
111 inequality_boundary);
115 const std::vector<double>& x_coord,
const std::vector<double>& lower_bound,
116 const std::vector<double>& upper_bound) {
117 std::vector<double> filtered_lower_bound;
118 std::vector<double> filtered_upper_bound;
119 std::vector<double> filtered_lower_bound_x;
120 std::vector<double> filtered_upper_bound_x;
122 if (x_knots_.size() < 2) {
126 if (!FilterConstraints(x_coord, lower_bound, upper_bound,
127 &filtered_lower_bound_x, &filtered_lower_bound,
128 &filtered_upper_bound_x, &filtered_upper_bound)) {
133 const uint32_t num_params = spline_order_ + 1;
135 filtered_upper_bound.size() + filtered_lower_bound.size(),
136 (x_knots_.size() - 1) * num_params);
137 Eigen::MatrixXd inequality_boundary = Eigen::MatrixXd::Zero(
138 filtered_upper_bound.size() + filtered_lower_bound.size(), 1);
140 for (uint32_t i = 0; i < filtered_lower_bound.size(); ++i) {
141 uint32_t index = FindIndex(filtered_lower_bound_x[i]);
142 const double corrected_x = filtered_lower_bound_x[i] - x_knots_[index];
144 for (uint32_t j = 1; j < num_params; ++j) {
148 inequality_boundary(i, 0) = filtered_lower_bound[i];
151 for (uint32_t i = 0; i < filtered_upper_bound.size(); ++i) {
152 uint32_t index = FindIndex(filtered_upper_bound_x[i]);
153 const double corrected_x = filtered_upper_bound_x[i] - x_knots_[index];
155 for (uint32_t j = 1; j < num_params; ++j) {
157 j + index * num_params) = coef * j;
160 inequality_boundary(i + filtered_lower_bound.size(), 0) =
161 -filtered_upper_bound[i];
164 inequality_boundary);
168 const std::vector<double>& x_coord,
const std::vector<double>& lower_bound,
169 const std::vector<double>& upper_bound) {
170 std::vector<double> filtered_lower_bound;
171 std::vector<double> filtered_upper_bound;
172 std::vector<double> filtered_lower_bound_x;
173 std::vector<double> filtered_upper_bound_x;
175 if (x_knots_.size() < 2) {
179 if (!FilterConstraints(x_coord, lower_bound, upper_bound,
180 &filtered_lower_bound_x, &filtered_lower_bound,
181 &filtered_upper_bound_x, &filtered_upper_bound)) {
186 const uint32_t num_params = spline_order_ + 1;
188 filtered_upper_bound.size() + filtered_lower_bound.size(),
189 (x_knots_.size() - 1) * num_params);
190 Eigen::MatrixXd inequality_boundary = Eigen::MatrixXd::Zero(
191 filtered_upper_bound.size() + filtered_lower_bound.size(), 1);
193 for (uint32_t i = 0; i < filtered_lower_bound.size(); ++i) {
194 uint32_t index = FindIndex(filtered_lower_bound_x[i]);
195 const double corrected_x = filtered_lower_bound_x[i] - x_knots_[index];
197 for (uint32_t j = 2; j < num_params; ++j) {
201 inequality_boundary(i, 0) = filtered_lower_bound[i];
204 for (uint32_t i = 0; i < filtered_upper_bound.size(); ++i) {
205 uint32_t index = FindIndex(filtered_upper_bound_x[i]);
206 const double corrected_x = filtered_upper_bound_x[i] - x_knots_[index];
208 for (uint32_t j = 2; j < num_params; ++j) {
210 j + index * num_params) = coef * j * (j - 1);
213 inequality_boundary(i + filtered_lower_bound.size(), 0) =
214 -filtered_upper_bound[i];
217 inequality_boundary);
221 const std::vector<double>& x_coord,
const std::vector<double>& lower_bound,
222 const std::vector<double>& upper_bound) {
223 std::vector<double> filtered_lower_bound;
224 std::vector<double> filtered_upper_bound;
225 std::vector<double> filtered_lower_bound_x;
226 std::vector<double> filtered_upper_bound_x;
228 if (!FilterConstraints(x_coord, lower_bound, upper_bound,
229 &filtered_lower_bound_x, &filtered_lower_bound,
230 &filtered_upper_bound_x, &filtered_upper_bound)) {
231 AERROR <<
"Fail to filter constraints.";
235 if (x_knots_.size() < 2) {
236 AERROR <<
"x_konts size cannot be < 2.";
241 const uint32_t num_params = spline_order_ + 1;
243 filtered_upper_bound.size() + filtered_lower_bound.size(),
244 (x_knots_.size() - 1) * num_params);
245 Eigen::MatrixXd inequality_boundary = Eigen::MatrixXd::Zero(
246 filtered_upper_bound.size() + filtered_lower_bound.size(), 1);
248 for (uint32_t i = 0; i < filtered_lower_bound.size(); ++i) {
249 uint32_t index = FindIndex(filtered_lower_bound_x[i]);
250 const double corrected_x = filtered_lower_bound_x[i] - x_knots_[index];
252 for (uint32_t j = 3; j < num_params; ++j) {
254 coef * j * (j - 1) * (j - 2);
257 inequality_boundary(i, 0) = filtered_lower_bound[i];
260 for (uint32_t i = 0; i < filtered_upper_bound.size(); ++i) {
261 uint32_t index = FindIndex(filtered_upper_bound_x[i]);
262 const double corrected_x = filtered_upper_bound_x[i] - x_knots_[index];
264 for (uint32_t j = 3; j < num_params; ++j) {
266 j + index * num_params) =
267 coef * j * (j - 1) * (j - 2);
270 inequality_boundary(i + filtered_lower_bound.size(), 0) =
271 -filtered_upper_bound[i];
274 inequality_boundary);
278 uint32_t index = FindIndex(x);
279 std::vector<double> power_x;
280 const uint32_t num_params = spline_order_ + 1;
281 GeneratePowerX(x - x_knots_[index], num_params, &power_x);
283 Eigen::MatrixXd::Zero(1, (x_knots_.size() - 1) * num_params);
284 uint32_t index_offset = index * num_params;
285 for (uint32_t i = 0; i < num_params; ++i) {
288 Eigen::MatrixXd equality_boundary(1, 1);
289 equality_boundary(0, 0) = fx;
293bool Spline1dConstraint::AddConstraintInRange(AddConstraintInRangeFunc func,
294 const double x,
const double val,
295 const double range) {
299 std::vector<double> x_vec;
302 std::vector<double> lower_bound;
303 std::vector<double> upper_bound;
304 lower_bound.push_back(val - range);
305 upper_bound.push_back(val + range);
306 return func(x_vec, lower_bound, upper_bound);
311 const double range) {
312 return AddConstraintInRange(
319 uint32_t index = FindIndex(x);
320 std::vector<double> power_x;
321 const uint32_t num_params = spline_order_ + 1;
322 GeneratePowerX(x - x_knots_[index], num_params, &power_x);
324 Eigen::MatrixXd::Zero(1, (x_knots_.size() - 1) * num_params);
325 uint32_t index_offset = index * num_params;
326 for (uint32_t i = 1; i < num_params; ++i) {
329 Eigen::MatrixXd equality_boundary(1, 1);
330 equality_boundary(0, 0) = dfx;
335 const double x,
const double dfx,
const double range) {
336 return AddConstraintInRange(
343 uint32_t index = FindIndex(x);
344 std::vector<double> power_x;
345 const uint32_t num_params = spline_order_ + 1;
346 GeneratePowerX(x - x_knots_[index], num_params, &power_x);
348 Eigen::MatrixXd::Zero(1, (x_knots_.size() - 1) * num_params);
349 uint32_t index_offset = index * num_params;
350 for (uint32_t i = 2; i < num_params; ++i) {
353 Eigen::MatrixXd equality_boundary(1, 1);
354 equality_boundary(0, 0) = ddfx;
359 const double x,
const double ddfx,
const double range) {
360 return AddConstraintInRange(
367 const double dddfx) {
368 uint32_t index = FindIndex(x);
369 std::vector<double> power_x;
370 const uint32_t num_params = spline_order_ + 1;
371 GeneratePowerX(x - x_knots_[index], num_params, &power_x);
373 Eigen::MatrixXd::Zero(1, (x_knots_.size() - 1) * num_params);
374 uint32_t index_offset = index * num_params;
375 for (uint32_t i = 3; i < num_params; ++i) {
377 power_x[i - 3] * i * (i - 1) * (i - 2);
379 Eigen::MatrixXd equality_boundary(1, 1);
380 equality_boundary(0, 0) = dddfx;
385 const double x,
const double dddfx,
const double range) {
386 return AddConstraintInRange(
393 if (x_knots_.size() < 3) {
396 const uint32_t num_params = spline_order_ + 1;
398 x_knots_.size() - 2, (x_knots_.size() - 1) * num_params);
399 Eigen::MatrixXd equality_boundary =
400 Eigen::MatrixXd::Zero(x_knots_.size() - 2, 1);
402 for (uint32_t i = 0; i < x_knots_.size() - 2; ++i) {
403 double left_coef = 1.0;
404 double right_coef = -1.0;
405 const double x_left = x_knots_[i + 1] - x_knots_[i];
406 const double x_right = 0.0;
407 for (uint32_t j = 0; j < num_params; ++j) {
411 right_coef *= x_right;
419 if (x_knots_.size() < 3) {
423 const uint32_t n_constraint =
424 (
static_cast<uint32_t
>(x_knots_.size()) - 2) * 2;
425 const uint32_t num_params = spline_order_ + 1;
427 Eigen::MatrixXd::Zero(n_constraint, (x_knots_.size() - 1) * num_params);
428 Eigen::MatrixXd equality_boundary = Eigen::MatrixXd::Zero(n_constraint, 1);
430 for (uint32_t i = 0; i < n_constraint; i += 2) {
431 double left_coef = 1.0;
432 double right_coef = -1.0;
433 double left_dcoef = 1.0;
434 double right_dcoef = -1.0;
435 const double x_left = x_knots_[i / 2 + 1] - x_knots_[i / 2];
436 const double x_right = 0.0;
437 for (uint32_t j = 0; j < num_params; ++j) {
444 left_dcoef = left_coef;
445 right_dcoef = right_coef;
448 right_coef *= x_right;
456 if (x_knots_.size() < 3) {
460 const uint32_t n_constraint =
461 (
static_cast<uint32_t
>(x_knots_.size()) - 2) * 3;
462 const uint32_t num_params = spline_order_ + 1;
464 Eigen::MatrixXd::Zero(n_constraint, (x_knots_.size() - 1) * num_params);
465 Eigen::MatrixXd equality_boundary = Eigen::MatrixXd::Zero(n_constraint, 1);
467 for (uint32_t i = 0; i < n_constraint; i += 3) {
468 double left_coef = 1.0;
469 double right_coef = -1.0;
470 double left_dcoef = 1.0;
471 double right_dcoef = -1.0;
472 double left_ddcoef = 1.0;
473 double right_ddcoef = -1.0;
475 const double x_left = x_knots_[i / 3 + 1] - x_knots_[i / 3];
476 const double x_right = 0.0;
477 for (uint32_t j = 0; j < num_params; ++j) {
483 left_ddcoef * j * (j - 1);
485 right_ddcoef * j * (j - 1);
486 left_ddcoef = left_dcoef;
487 right_ddcoef = right_dcoef;
494 left_dcoef = left_coef;
495 right_dcoef = right_coef;
498 right_coef *= x_right;
506 if (x_knots_.size() < 3) {
510 const uint32_t n_constraint =
511 (
static_cast<uint32_t
>(x_knots_.size()) - 2) * 4;
512 const uint32_t num_params = spline_order_ + 1;
514 Eigen::MatrixXd::Zero(n_constraint, (x_knots_.size() - 1) * num_params);
515 Eigen::MatrixXd equality_boundary = Eigen::MatrixXd::Zero(n_constraint, 1);
517 for (uint32_t i = 0; i < n_constraint; i += 4) {
518 double left_coef = 1.0;
519 double right_coef = -1.0;
520 double left_dcoef = 1.0;
521 double right_dcoef = -1.0;
522 double left_ddcoef = 1.0;
523 double right_ddcoef = -1.0;
524 double left_dddcoef = 1.0;
525 double right_dddcoef = -1.0;
527 const double x_left = x_knots_[i / 4 + 1] - x_knots_[i / 4];
528 const double x_right = 0.0;
529 for (uint32_t j = 0; j < num_params; ++j) {
535 left_dddcoef * j * (j - 1) * (j - 2);
537 right_dddcoef * j * (j - 1) * (j - 2);
538 left_dddcoef = left_ddcoef;
539 right_dddcoef = right_ddcoef;
544 left_ddcoef * j * (j - 1);
546 right_ddcoef * j * (j - 1);
547 left_ddcoef = left_dcoef;
548 right_ddcoef = right_dcoef;
555 left_dcoef = left_coef;
556 right_dcoef = right_coef;
560 right_coef *= x_right;
568 const std::vector<double>& x_coord) {
569 if (x_coord.size() < 2) {
574 const uint32_t num_params = spline_order_ + 1;
576 x_coord.size() - 1, (x_knots_.size() - 1) * num_params);
577 Eigen::MatrixXd inequality_boundary =
578 Eigen::MatrixXd::Zero(x_coord.size() - 1, 1);
580 uint32_t prev_spline_index = FindIndex(x_coord[0]);
581 double prev_rel_x = x_coord[0] - x_knots_[prev_spline_index];
582 std::vector<double> prev_coef;
583 GeneratePowerX(prev_rel_x, num_params, &prev_coef);
584 for (uint32_t i = 1; i < x_coord.size(); ++i) {
585 uint32_t cur_spline_index = FindIndex(x_coord[i]);
586 double cur_rel_x = x_coord[i] - x_knots_[cur_spline_index];
587 std::vector<double> cur_coef;
589 GeneratePowerX(cur_rel_x, num_params, &cur_coef);
591 if (cur_spline_index == prev_spline_index) {
592 for (uint32_t j = 0; j < cur_coef.size(); ++j) {
594 cur_coef[j] - prev_coef[j];
598 for (uint32_t j = 0; j < cur_coef.size(); ++j) {
605 prev_coef = cur_coef;
606 prev_spline_index = cur_spline_index;
610 inequality_boundary);
618 return inequality_constraint_;
622 return equality_constraint_;
625uint32_t Spline1dConstraint::FindIndex(
const double x)
const {
626 auto upper_bound = std::upper_bound(x_knots_.begin() + 1, x_knots_.end(), x);
627 return std::min(
static_cast<uint32_t
>(x_knots_.size() - 1),
628 static_cast<uint32_t
>(upper_bound - x_knots_.begin())) -
632bool Spline1dConstraint::FilterConstraints(
633 const std::vector<double>& x_coord,
const std::vector<double>& lower_bound,
634 const std::vector<double>& upper_bound,
635 std::vector<double>*
const filtered_lower_bound_x,
636 std::vector<double>*
const filtered_lower_bound,
637 std::vector<double>*
const filtered_upper_bound_x,
638 std::vector<double>*
const filtered_upper_bound) {
639 filtered_lower_bound->clear();
640 filtered_upper_bound->clear();
641 filtered_lower_bound_x->clear();
642 filtered_upper_bound_x->clear();
644 const double inf = std::numeric_limits<double>::infinity();
646 filtered_lower_bound->reserve(lower_bound.size());
647 filtered_lower_bound_x->reserve(lower_bound.size());
649 filtered_upper_bound->reserve(upper_bound.size());
650 filtered_upper_bound_x->reserve(upper_bound.size());
652 for (uint32_t i = 0; i < lower_bound.size(); ++i) {
653 if (std::isnan(lower_bound[i]) || lower_bound[i] == inf) {
656 if (lower_bound[i] < inf && lower_bound[i] > -inf) {
657 filtered_lower_bound->emplace_back(lower_bound[i]);
658 filtered_lower_bound_x->emplace_back(x_coord[i]);
662 for (uint32_t i = 0; i < upper_bound.size(); ++i) {
663 if (std::isnan(upper_bound[i]) || upper_bound[i] == -inf) {
666 if (upper_bound[i] < inf && upper_bound[i] > -inf) {
667 filtered_upper_bound->emplace_back(upper_bound[i]);
668 filtered_upper_bound_x->emplace_back(x_coord[i]);
674void Spline1dConstraint::GeneratePowerX(
675 const double x,
const uint32_t order,
676 std::vector<double>*
const power_x)
const {
678 for (uint32_t i = 0; i < order; ++i) {
679 power_x->push_back(cur_x);
bool AddConstraint(const Eigen::MatrixXd &constraint_matrix, const Eigen::MatrixXd &constraint_boundary)
void SetIsEquality(const double is_equality)
bool AddPointSecondDerivativeConstraint(const double x, const double ddfx)
bool AddDerivativeBoundary(const std::vector< double > &x_coord, const std::vector< double > &lower_bound, const std::vector< double > &upper_bound)
bool AddPointThirdDerivativeConstraintInRange(const double x, const double dddfx, const double range)
bool AddThirdDerivativeSmoothConstraint()
const AffineConstraint & equality_constraint() const
bool AddMonotoneInequalityConstraintAtKnots()
bool AddSecondDerivativeSmoothConstraint()
bool AddBoundary(const std::vector< double > &x_coord, const std::vector< double > &lower_bound, const std::vector< double > &upper_bound)
: inequality boundary constraints if no boundary, do specify either by std::infinity or let vector....
bool AddEqualityConstraint(const Eigen::MatrixXd &constraint_matrix, const Eigen::MatrixXd &constraint_boundary)
bool AddThirdDerivativeBoundary(const std::vector< double > &x_coord, const std::vector< double > &lower_bound, const std::vector< double > &upper_bound)
bool AddPointDerivativeConstraint(const double x, const double dfx)
const AffineConstraint & inequality_constraint() const
: output interface inequality constraint
Spline1dConstraint(const Spline1d &pss)
bool AddInequalityConstraint(const Eigen::MatrixXd &constraint_matrix, const Eigen::MatrixXd &constraint_boundary)
bool AddMonotoneInequalityConstraint(const std::vector< double > &x_coord)
: Add monotone constraint inequality, guarantee the monotone city at evaluated point.
bool AddDerivativeSmoothConstraint()
bool AddSecondDerivativeBoundary(const std::vector< double > &x_coord, const std::vector< double > &lower_bound, const std::vector< double > &upper_bound)
bool AddSmoothConstraint()
bool AddPointSecondDerivativeConstraintInRange(const double x, const double ddfx, const double range)
bool AddPointDerivativeConstraintInRange(const double x, const double dfx, const double range)
bool AddPointThirdDerivativeConstraint(const double x, const double dddfx)
bool AddPointConstraintInRange(const double x, const double fx, const double range)
bool AddPointConstraint(const double x, const double fx)
: equality constraint to guarantee joint smoothness boundary equality constriant constraint on fx,...
Planning module main class.
: wrapp up solver constraint interface with direct methods and preset methods