377 const std::vector<CenterPoint>& traj_original,
380 const int N =
static_cast<int>(traj.size());
383 std::cerr <<
"[optimizeTrajectoryCeres] need at least 4 points\n";
388 normalizeTrajectoryAngles(traj);
390 ceres::Problem problem;
392 for (
int i = 0; i < N; ++i)
393 problem.AddParameterBlock(&traj[i].x, 4);
396 problem.SetParameterBlockConstant(&traj.front().x);
397 problem.SetParameterBlockConstant(&traj.back().x);
400 for (
int i = 1; i <= N - 2; ++i)
402 problem.AddResidualBlock(
403 new ceres::AutoDiffCostFunction<PoseSmoothResidual, 3, 4, 4, 4>(
414 problem.AddResidualBlock(
415 new ceres::AutoDiffCostFunction<StartRotationResidual, 1, 4, 4>(
423 problem.AddResidualBlock(
424 new ceres::AutoDiffCostFunction<StartRotationResidual, 1, 4, 4>(
432 for (
int i = 1; i <= N - 2; ++i)
434 problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<VelSmoothResidual, 1, 4, 4, 4>(
445 for (
int i = 2; i <= N - 2; ++i)
447 problem.AddResidualBlock(
448 new ceres::AutoDiffCostFunction<PoseJerkResidual, 3, 4, 4, 4, 4>(
461 for (
int i = 1; i <= N - 2; ++i)
463 problem.AddResidualBlock(
464 new ceres::AutoDiffCostFunction<RobotSmoothResidual, 3, 4, 4, 4>(
474 double d_avg = computeAverageSpacing(traj);
477 for (
int i = 0; i < N - 1; ++i)
479 problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<SpacingResidual, 1, 4, 4>(
489 for (
int i = 0; i < N; ++i)
493 s_local = segment_length(traj[0], traj[1]);
495 s_local = segment_length(traj[N - 2], traj[N - 1]);
497 s_local = 0.5 * (segment_length(traj[i], traj[i - 1]) +
498 segment_length(traj[i + 1], traj[i]));
499 double s_sqrt = std::sqrt(std::max(1e-6, s_local));
509 problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<ObstacleResidual, 1, 4>(
520 for (
int i = 0; i < N; ++i)
522 problem.AddResidualBlock(
new ceres::AutoDiffCostFunction<VelLimitResidual, 1, 4>(
531 if (
static_cast<int>(traj_original.size()) != N)
533 std::cerr <<
"[optimizeTrajectoryCeres] traj_original size mismatch; skipping "
538 for (
int i = 0; i < N; ++i)
542 double wth = opts.
w_track * 300.0;
543 double wv = opts.
w_track * 0.2;
544 problem.AddResidualBlock(
545 new ceres::AutoDiffCostFunction<TrackingResidual, 4, 4>(
548 traj_original[i].theta,
561 ceres::Solver::Options options;
563 options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
564 options.minimizer_progress_to_stdout =
false;
566 options.function_tolerance = 1e-6;
567 options.parameter_tolerance = 1e-8;
571 options.trust_region_strategy_type = ceres::LEVENBERG_MARQUARDT;
573 options.initial_trust_region_radius = 1e1;
574 options.max_trust_region_radius = 1e3;
575 options.min_trust_region_radius = 1e-3;
578 options.min_relative_decrease = 1e-3;
580 auto print_residuals = [&problem, N]()
582 std::vector<ceres::ResidualBlockId> to_eval;
583 problem.GetResidualBlocks(&to_eval);
584 ceres::Problem::EvaluateOptions options;
585 options.residual_blocks = to_eval;
586 double total_cost = 0.0;
587 std::vector<double> evaluated_residuals;
588 problem.Evaluate(options, &total_cost, &evaluated_residuals,
nullptr,
nullptr);
589 for (
auto i = 0; i < evaluated_residuals.size(); i++)
595 ceres::Solver::Summary summary;
597 ceres::Solve(options, &problem, &summary);
600 normalizeTrajectoryAngles(traj);
604 ARMARX_INFO <<
"[optimizeTrajectoryCeres] Done. Final cost: " << summary.final_cost
605 <<
" iterations: " << summary.num_successful_steps <<
"\n";