49 std::vector<Eigen::Vector2d> points)
50 : init_points_(
std::move(points)) {
51 num_of_points_ =
static_cast<int>(init_points_.size());
52 CHECK_GT(num_of_points_, 1);
54 point_distances_.reserve(num_of_points_ - 1);
55 for (
int i = 0; i + 1 < num_of_points_; ++i) {
56 point_distances_.push_back((init_points_[i + 1] - init_points_[i]).norm());
59 std::vector<double> normalized_theta;
60 for (
int i = 0; i + 1 < num_of_points_; ++i) {
61 Eigen::Vector2d v = init_points_[i + 1] - init_points_[i];
62 double theta = std::atan2(v.y(), v.x());
63 normalized_theta.push_back(theta);
65 normalized_theta.push_back(normalized_theta.back());
67 relative_theta_.push_back(normalized_theta.front());
68 for (
int i = 1; i < num_of_points_; ++i) {
71 relative_theta_.push_back(relative_theta_.back() + theta_diff);
74 piecewise_paths_.resize(num_of_points_ - 1);
115 int m,
double* g_l,
double* g_u) {
116 CHECK_EQ(n, num_of_variables_);
117 CHECK_EQ(m, num_of_constraints_);
121 for (
int i = 0; i < num_of_points_; ++i) {
124 double theta_lower = 0.0;
125 double theta_upper = 0.0;
126 double kappa_lower = 0.0;
127 double kappa_upper = 0.0;
128 double dkappa_lower = 0.0;
129 double dkappa_upper = 0.0;
130 double x_lower = 0.0;
131 double x_upper = 0.0;
132 double y_lower = 0.0;
133 double y_upper = 0.0;
134 if (i == 0 && has_fixed_start_point_) {
135 theta_lower = start_theta_;
136 theta_upper = start_theta_;
137 kappa_lower = start_kappa_;
138 kappa_upper = start_kappa_;
139 dkappa_lower = start_dkappa_;
140 dkappa_upper = start_dkappa_;
146 }
else if (i + 1 == num_of_points_ && has_fixed_end_point_) {
147 theta_lower = end_theta_;
148 theta_upper = end_theta_;
149 kappa_lower = end_kappa_;
150 kappa_upper = end_kappa_;
151 dkappa_lower = end_dkappa_;
152 dkappa_upper = end_dkappa_;
157 }
else if (i + 1 == num_of_points_ && has_fixed_end_point_position_) {
158 theta_lower = relative_theta_[i] - M_PI * 0.2;
159 theta_upper = relative_theta_[i] + M_PI * 0.2;
162 dkappa_lower = -0.02;
169 theta_lower = relative_theta_[i] - M_PI * 0.2;
170 theta_upper = relative_theta_[i] + M_PI * 0.2;
173 dkappa_lower = -0.02;
175 x_lower = init_points_[i].x() - default_max_point_deviation_;
176 x_upper = init_points_[i].x() + default_max_point_deviation_;
177 y_lower = init_points_[i].y() - default_max_point_deviation_;
178 y_upper = init_points_[i].y() + default_max_point_deviation_;
182 x_l[index] = theta_lower;
183 x_u[index] = theta_upper;
186 x_l[index + 1] = kappa_lower;
187 x_u[index + 1] = kappa_upper;
190 x_l[index + 2] = dkappa_lower;
191 x_u[index + 2] = dkappa_upper;
194 x_l[index + 3] = x_lower;
195 x_u[index + 3] = x_upper;
198 x_l[index + 4] = y_lower;
199 x_u[index + 4] = y_upper;
203 int variable_offset = num_of_points_ * 5;
204 for (
int i = 0; i + 1 < num_of_points_; ++i) {
205 x_l[variable_offset + i] =
206 point_distances_[i] - 2.0 * default_max_point_deviation_;
207 x_u[variable_offset + i] = point_distances_[i] * M_PI * 0.5;
212 for (
int i = 0; i + 1 < num_of_points_; ++i) {
218 g_l[i * 2 + 1] = 0.0;
219 g_u[i * 2 + 1] = 0.0;
222 int constraint_offset = 2 * (num_of_points_ - 1);
223 for (
int i = 0; i < num_of_points_; ++i) {
224 g_l[constraint_offset + i] = 0.0;
225 g_u[constraint_offset + i] =
226 default_max_point_deviation_ * default_max_point_deviation_;
232 bool init_z,
double* z_L,
236 CHECK_EQ(n, num_of_variables_);
241 for (
int i = 0; i < num_of_points_; ++i) {
243 x[index] = relative_theta_[i];
246 x[index + 3] = init_points_[i].x();
247 x[index + 4] = init_points_[i].y();
250 int variable_offset = num_of_points_ * 5;
251 for (
int i = 0; i + 1 < num_of_points_; ++i) {
252 double delta_theta = relative_theta_[i + 1] - relative_theta_[i];
253 x[variable_offset + i] = point_distances_[i] / std::cos(0.5 * delta_theta);
256 for (
int i = 0; i + 1 < num_of_points_; ++i) {
257 double delta_theta = relative_theta_[i + 1] - relative_theta_[i];
258 x[(i + 1) * 5 + 1] = delta_theta / x[variable_offset + i];
262 if (has_fixed_start_point_) {
265 x[2] = start_dkappa_;
272 CHECK_EQ(n, num_of_variables_);
274 update_piecewise_spiral_paths(x, n);
278 for (
int i = 0; i + 1 < num_of_points_; ++i) {
279 const auto& spiral_curve = piecewise_paths_[i];
280 double delta_s = spiral_curve.ParamLength();
282 obj_value += delta_s * weight_curve_length_;
284 for (
int j = 0; j < num_of_internal_points_; ++j) {
286 static_cast<double>(j) /
static_cast<double>(num_of_internal_points_);
287 double s = ratio * delta_s;
289 double kappa = spiral_curve.Evaluate(1, s);
290 obj_value += kappa * kappa * weight_kappa_;
292 double dkappa = spiral_curve.Evaluate(2, s);
293 obj_value += dkappa * dkappa * weight_dkappa_;
301 CHECK_EQ(n, num_of_variables_);
302 std::fill(grad_f, grad_f + n, 0.0);
305 update_piecewise_spiral_paths(x, n);
308 int variable_offset = num_of_points_ * 5;
309 for (
int i = 0; i + 1 < num_of_points_; ++i) {
311 int index1 = (i + 1) * 5;
313 auto& spiral_curve = piecewise_paths_[i];
314 double delta_s = spiral_curve.ParamLength();
316 grad_f[variable_offset + i] += weight_curve_length_ * 1.0;
318 for (
int j = 0; j < num_of_internal_points_; ++j) {
320 static_cast<double>(j) /
static_cast<double>(num_of_internal_points_);
321 double s = ratio * delta_s;
323 double kappa = spiral_curve.Evaluate(1, s);
324 grad_f[index0] += weight_kappa_ * 2.0 * kappa *
325 spiral_curve.DeriveKappaDerivative(
326 THETA0, j, num_of_internal_points_);
327 grad_f[index0 + 1] += weight_kappa_ * 2.0 * kappa *
328 spiral_curve.DeriveKappaDerivative(
329 KAPPA0, j, num_of_internal_points_);
330 grad_f[index0 + 2] += weight_kappa_ * 2.0 * kappa *
331 spiral_curve.DeriveKappaDerivative(
332 DKAPPA0, j, num_of_internal_points_);
334 grad_f[index1] += weight_kappa_ * 2.0 * kappa *
335 spiral_curve.DeriveKappaDerivative(
336 THETA1, j, num_of_internal_points_);
337 grad_f[index1 + 1] += weight_kappa_ * 2.0 * kappa *
338 spiral_curve.DeriveKappaDerivative(
339 KAPPA1, j, num_of_internal_points_);
340 grad_f[index1 + 2] += weight_kappa_ * 2.0 * kappa *
341 spiral_curve.DeriveKappaDerivative(
342 DKAPPA1, j, num_of_internal_points_);
344 grad_f[variable_offset + i] += weight_kappa_ * 2.0 * kappa *
345 spiral_curve.DeriveKappaDerivative(
346 DELTA_S, j, num_of_internal_points_);
348 double dkappa = spiral_curve.Evaluate(2, s);
349 grad_f[index0] += weight_dkappa_ * 2.0 * dkappa *
350 spiral_curve.DeriveDKappaDerivative(
351 THETA0, j, num_of_internal_points_);
352 grad_f[index0 + 1] += weight_dkappa_ * 2.0 * dkappa *
353 spiral_curve.DeriveDKappaDerivative(
354 KAPPA0, j, num_of_internal_points_);
355 grad_f[index0 + 2] += weight_dkappa_ * 2.0 * dkappa *
356 spiral_curve.DeriveDKappaDerivative(
357 DKAPPA0, j, num_of_internal_points_);
359 grad_f[index1] += weight_dkappa_ * 2.0 * dkappa *
360 spiral_curve.DeriveDKappaDerivative(
361 THETA1, j, num_of_internal_points_);
362 grad_f[index1 + 1] += weight_dkappa_ * 2.0 * dkappa *
363 spiral_curve.DeriveDKappaDerivative(
364 KAPPA1, j, num_of_internal_points_);
365 grad_f[index1 + 2] += weight_dkappa_ * 2.0 * dkappa *
366 spiral_curve.DeriveDKappaDerivative(
367 DKAPPA1, j, num_of_internal_points_);
369 grad_f[variable_offset + i] += weight_dkappa_ * 2.0 * dkappa *
370 spiral_curve.DeriveDKappaDerivative(
371 DELTA_S, j, num_of_internal_points_);
379 CHECK_EQ(n, num_of_variables_);
380 CHECK_EQ(m, num_of_constraints_);
383 update_piecewise_spiral_paths(x, n);
387 for (
int i = 0; i + 1 < num_of_points_; ++i) {
389 int index1 = (i + 1) * 5;
391 const auto& spiral_curve = piecewise_paths_[i];
392 double delta_s = spiral_curve.ParamLength();
394 double x_diff = x[index1 + 3] - x[index0 + 3] -
395 spiral_curve.ComputeCartesianDeviationX(delta_s);
396 g[i * 2] = x_diff * x_diff;
398 double y_diff = x[index1 + 4] - x[index0 + 4] -
399 spiral_curve.ComputeCartesianDeviationY(delta_s);
400 g[i * 2 + 1] = y_diff * y_diff;
404 int constraint_offset = 2 * (num_of_points_ - 1);
405 for (
int i = 0; i < num_of_points_; ++i) {
406 int variable_index = i * 5;
407 double x_cor = x[variable_index + 3];
408 double y_cor = x[variable_index + 4];
410 double x_diff = x_cor - init_points_[i].x();
411 double y_diff = y_cor - init_points_[i].y();
413 g[constraint_offset + i] = x_diff * x_diff + y_diff * y_diff;
419 int m,
int nele_jac,
int* iRow,
420 int* jCol,
double* values) {
421 CHECK_EQ(n, num_of_variables_);
422 CHECK_EQ(m, num_of_constraints_);
424 if (values ==
nullptr) {
427 int variable_offset = num_of_points_ * 5;
428 for (
int i = 0; i + 1 < num_of_points_; ++i) {
429 int variable_index = i * 5;
432 iRow[nz_index] = i * 2;
433 jCol[nz_index] = variable_index + 0;
437 iRow[nz_index] = i * 2;
438 jCol[nz_index] = variable_index + 1;
442 iRow[nz_index] = i * 2;
443 jCol[nz_index] = variable_index + 2;
447 iRow[nz_index] = i * 2;
448 jCol[nz_index] = variable_index + 3;
452 iRow[nz_index] = i * 2;
453 jCol[nz_index] = variable_index + 5;
457 iRow[nz_index] = i * 2;
458 jCol[nz_index] = variable_index + 6;
462 iRow[nz_index] = i * 2;
463 jCol[nz_index] = variable_index + 7;
467 iRow[nz_index] = i * 2;
468 jCol[nz_index] = variable_index + 8;
472 iRow[nz_index] = i * 2;
473 jCol[nz_index] = variable_offset + i;
477 iRow[nz_index] = i * 2 + 1;
478 jCol[nz_index] = variable_index + 0;
482 iRow[nz_index] = i * 2 + 1;
483 jCol[nz_index] = variable_index + 1;
487 iRow[nz_index] = i * 2 + 1;
488 jCol[nz_index] = variable_index + 2;
492 iRow[nz_index] = i * 2 + 1;
493 jCol[nz_index] = variable_index + 4;
497 iRow[nz_index] = i * 2 + 1;
498 jCol[nz_index] = variable_index + 5;
502 iRow[nz_index] = i * 2 + 1;
503 jCol[nz_index] = variable_index + 6;
507 iRow[nz_index] = i * 2 + 1;
508 jCol[nz_index] = variable_index + 7;
512 iRow[nz_index] = i * 2 + 1;
513 jCol[nz_index] = variable_index + 9;
517 iRow[nz_index] = i * 2 + 1;
518 jCol[nz_index] = variable_offset + i;
522 int constraint_offset = 2 * (num_of_points_ - 1);
523 for (
int i = 0; i < num_of_points_; ++i) {
524 iRow[nz_index] = constraint_offset + i;
525 jCol[nz_index] = i * 5 + 3;
528 iRow[nz_index] = constraint_offset + i;
529 jCol[nz_index] = i * 5 + 4;
533 CHECK_EQ(nz_index, nele_jac);
536 update_piecewise_spiral_paths(x, n);
539 std::fill(values, values + nele_jac, 0.0);
543 for (
int i = 0; i + 1 < num_of_points_; ++i) {
545 int index1 = (i + 1) * 5;
547 auto& spiral_curve = piecewise_paths_[i];
548 double delta_s = spiral_curve.ParamLength();
550 double x_diff = x[index1 + 3] - x[index0 + 3] -
551 spiral_curve.ComputeCartesianDeviationX(delta_s);
552 double y_diff = x[index1 + 4] - x[index0 + 4] -
553 spiral_curve.ComputeCartesianDeviationY(delta_s);
555 auto pos_theta0 = spiral_curve.DeriveCartesianDeviation(THETA0);
556 auto pos_kappa0 = spiral_curve.DeriveCartesianDeviation(KAPPA0);
557 auto pos_dkappa0 = spiral_curve.DeriveCartesianDeviation(DKAPPA0);
559 auto pos_theta1 = spiral_curve.DeriveCartesianDeviation(THETA1);
560 auto pos_kappa1 = spiral_curve.DeriveCartesianDeviation(KAPPA1);
561 auto pos_dkappa1 = spiral_curve.DeriveCartesianDeviation(DKAPPA1);
563 auto pos_delta_s = spiral_curve.DeriveCartesianDeviation(DELTA_S);
567 values[nz_index] += 2.0 * x_diff * (-pos_theta0.first);
571 values[nz_index] += 2.0 * x_diff * (-pos_kappa0.first);
575 values[nz_index] += 2.0 * x_diff * (-pos_dkappa0.first);
579 values[nz_index] += 2.0 * x_diff * (-1.0);
583 values[nz_index] += 2.0 * x_diff * (-pos_theta1.first);
587 values[nz_index] += 2.0 * x_diff * (-pos_kappa1.first);
591 values[nz_index] += 2.0 * x_diff * (-pos_dkappa1.first);
595 values[nz_index] += 2.0 * x_diff;
599 values[nz_index] += 2.0 * x_diff * (-pos_delta_s.first);
604 values[nz_index] += 2.0 * y_diff * (-pos_theta0.second);
608 values[nz_index] += 2.0 * y_diff * (-pos_kappa0.second);
612 values[nz_index] += 2.0 * y_diff * (-pos_dkappa0.second);
616 values[nz_index] += 2.0 * y_diff * (-1.0);
620 values[nz_index] += 2.0 * y_diff * (-pos_theta1.second);
624 values[nz_index] += 2.0 * y_diff * (-pos_kappa1.second);
628 values[nz_index] += 2.0 * y_diff * (-pos_dkappa1.second);
632 values[nz_index] += 2.0 * y_diff;
636 values[nz_index] += 2.0 * y_diff * (-pos_delta_s.second);
640 for (
int i = 0; i < num_of_points_; ++i) {
641 values[nz_index] = 2.0 * (x[i * 5 + 3] - init_points_[i].x());
644 values[nz_index] = 2.0 * (x[i * 5 + 4] - init_points_[i].y());
648 CHECK_EQ(nz_index, nele_jac);
663 Ipopt::SolverReturn status,
int n,
const double* x,
const double* z_L,
664 const double* z_U,
int m,
const double* g,
const double* lambda,
665 double obj_value,
const Ipopt::IpoptData* ip_data,
666 Ipopt::IpoptCalculatedQuantities* ip_cq) {
667 opt_theta_.reserve(num_of_points_);
668 opt_kappa_.reserve(num_of_points_);
669 opt_dkappa_.reserve(num_of_points_);
670 opt_x_.reserve(num_of_points_);
671 opt_y_.reserve(num_of_points_);
672 for (
int i = 0; i < num_of_points_; ++i) {
674 opt_theta_.push_back(x[index]);
675 opt_kappa_.push_back(x[index + 1]);
676 opt_dkappa_.push_back(x[index + 2]);
677 opt_x_.push_back(x[index + 3]);
678 opt_y_.push_back(x[index + 4]);
681 opt_s_.reserve(num_of_points_ - 1);
682 int variable_offset = num_of_points_ * 5;
683 for (
int i = 0; i + 1 < num_of_points_; ++i) {
684 opt_s_.push_back(x[variable_offset + i]);