当前位置:   article > 正文

mpc_local_planner详解

mpc_local_planner使用

控制器配置

  1. Controller::configure()
  2. {
  3. //创建机器模型
  4. _dynamics = std::make_shared<UnicycleModel>();
  5. //离散网络,比如多重打靶法。参考点,输入,状态,等变量也会存放在grid里面,会实时更新。而且grid也继承了顶点传入到超图问题构建中
  6. _grid = configureGrid(nh);
  7. //求解器
  8. _solver = configureSolver(nh);
  9. //最优化问题构建, _dynamics,_grid,_solver这三个指针也会传入到最优化问题类里
  10. _structured_ocp = configureOcp(nh, obstacles, robot_model, via_points);
  11. }

求解器配置

  1. configureSolver()
  2. {
  3. //SolverIpopt这个类里面会新建2个结构:
  4. //_ipopt_nlp = new IpoptWrapper(this);
  5. //_ipopt_app = IpoptApplicationFactory();
  6. //IpoptWrapper类是Ipopt的结构壳子,在nlp_solver_ipopt_wrapper.cpp中,里面主要是求解器的接口
  7. //这个类只是壳子,具体的问题实现在optimaization里面的问题类里,在configureOcp()里面,就创建了一个HyperGraphOptimizationProblemEdgeBased超图最优问题
  8. //get_nlp_info() 变量和约束信息
  9. //eval_f() 目标函数
  10. //eval_jac_g() 雅可比矩阵
  11. //eval_h() 海森矩阵
  12. //IpoptApplicationFactory是ipopt的标准用法,创建一个IPOPT应用程序:
  13. //ApplicationReturnStatus status;
  14. //status = _ipopt_app->Initialize();
  15. // 设置优化参数
  16. //_ipopt_app->Options()->SetNumericValue("tol", 1e-9); //最小迭阈值
  17. //_ipopt_app->Options()->SetStringValue("mu_strategy", "adaptive");
  18. //_ipopt_app->OptimizeTNLP(_ipopt_nlp);
  19. //_ipopt_nlp->eval_f(); //获取
  20. corbo::SolverIpopt::Ptr solver = std::make_shared<corbo::SolverIpopt>();
  21. solver->initialize();
  22. solver->setIterations(iterations); //迭代次数
  23. solver->setMaxCpuTime(max_cpu_time);//最大计算时间
  24. solver->setIpoptOptionNumeric(); //对应SetNumericValue() 最小迭代阈值
  25. solver->setIpoptOptionString(); //对应SetStringValue
  26. }

最优化问题构造

  1. Controller::configureOcp()
  2. {
  3. //构建一个超图最优化问题框架,
  4. corbo::BaseHyperGraphOptimizationProblem::Ptr hg = std::make_shared<corbo::HyperGraphOptimizationProblemEdgeBased>();
  5. //构建一个最优控制问题框架,相当于在上面的框架上再套一层
  6. corbo::StructuredOptimalControlProblem::Ptr ocp = std::make_shared<corbo::StructuredOptimalControlProblem>(_grid, _dynamics, hg, _solver);
  7. //控制输入边界
  8. ocp->setControlBounds(Eigen::Vector2d(-max_vel_x_backwards, -max_vel_theta), Eigen::Vector2d(max_vel_x, max_vel_theta));
  9. //二次型目标函数cost
  10. ocp->setStageCost(std::make_shared<QuadraticFormCostSE2>(Q, R, integral_form, lsq_solver));
  11. //终端cost
  12. ocp->setFinalStageCost(std::make_shared<QuadraticFinalStateCostSE2>(Qf, lsq_solver));
  13. _inequality_constraint = std::make_shared<StageInequalitySE2>();
  14. //障碍物不等式约束
  15. _inequality_constraint->setObstacleVector(obstacles);
  16. //footprint不等式约束
  17. _inequality_constraint->setRobotFootprintModel(robot_model);
  18. //设置障碍物最小距离
  19. _inequality_constraint->setMinimumDistance(min_obstacle_dist);
  20. //是否开启动态障碍物
  21. _inequality_constraint->setEnableDynamicObstacles(enable_dynamic_obstacles);
  22. //障碍物过滤
  23. _inequality_constraint->setObstacleFilterParameters(force_inclusion_dist, cutoff_dist);
  24. //加速度约束
  25. Eigen::Vector2d ud_lb(-dec_lim_x, -acc_lim_theta);
  26. Eigen::Vector2d ud_ub(acc_lim_x, acc_lim_theta);
  27. _inequality_constraint->setControlDeviationBounds(ud_lb, ud_ub);
  28. //不等式约束传入最优控制器里
  29. ocp->setStageInequalityConstraint(_inequality_constraint);
  30. }

迭代过程

  1. //由computeVelocityCommands过来
  2. bool Controller::step(const std::vector<geometry_msgs::PoseStamped>& initial_plan, const geometry_msgs::Twist& vel, double dt, ros::Time t,
  3. corbo::TimeSeries::Ptr u_seq, corbo::TimeSeries::Ptr x_seq)
  4. {
  5. _dynamics->getSteadyStateFromPoseSE2(goal, xf); //目标点转为eigen格式
  6. //起始点根据状态反馈,来选择是用传入的start点,还是用反馈的状态点,还是用odom点。
  7. _dynamics->getSteadyStateFromPoseSE2(start, x);
  8. if(如果目标与上一个目标之间的距离或角度变化大于阈值,将清除路径规划数据 _grid。这是为了确保机器人能够适应新的目标或路径)
  9. {
  10. _grid->clear();
  11. }
  12. if (_grid->isEmpty()) //网格路径是否是空
  13. {
  14. bool backward = _guess_backwards_motion && (goal.position() - start.position()).dot(start.orientationUnitVec()) < 0; //是否需要倒车
  15. //添加时间序列信息以及姿态信息,从而转换为初始轨迹,并采用线性差值对相邻两个轨迹点之间的轨迹进行差值,生成的轨迹存放在controller类的变量_x_seq_init中
  16. generateInitialStateTrajectory(x, xf, initial_plan, backward); //生成参考轨迹
  17. }
  18. corbo::StaticReference xref(xf); //这里参考点只取了目标点一个点,状态cost是每个预测点和目标点的偏差?
  19. //当前点,目标点,参考U,时间,离散时间,输入队列,状态队列
  20. _ocp_successful = PredictiveController::step(x, xref, uref, corbo::Duration(dt), time, u_seq, x_seq, nullptr, nullptr, &_x_seq_init); //求解问题
  21. 这里会进入predictive_controller.cpp里面的step
  22. _ocp->compute(x, xref, uref, sref, t, i == 0, signal_target, xinit, uinit, ns); //求解器进行计算
  23. //后续进入strucured_optimal_control_problem.cpp

最优化问题求解接口

structured_optimal_control_problem.cpp

  1. bool StructuredOptimalControlProblem::compute(const StateVector& x, ReferenceTrajectoryInterface& xref, ReferenceTrajectoryInterface& uref,
  2. ReferenceTrajectoryInterface* sref, const Time& t, bool new_run, SignalTargetInterface* signal_target,
  3. ReferenceTrajectoryInterface* xinit, ReferenceTrajectoryInterface* uinit, const std::string& ns)
  4. {
  5. GridUpdateResult grid_udpate_result =
  6. _grid->update(x, xref, uref, _functions, *_edges, _dynamics, new_run, t, sref, &_u_prev, _u_prev_dt, xinit, uinit); //状态更新至grid
  7. if (grid_udpate_result.vertices_updated)
  8. {
  9. _optim_prob->precomputeVertexQuantities();
  10. }
  11. if (grid_udpate_result.updated())
  12. {
  13. _optim_prob->precomputeEdgeQuantities();
  14. }
  15. _solver->solve(*_optim_prob, grid_udpate_result.updated(), new_run, &_objective_value);
  16. }

ipopt接口

nlp_solver_ipopt.cpp

  1. SolverStatus SolverIpopt::solve(OptimizationProblemInterface& problem, bool new_structure, bool new_run, double* obj_value)
  2. {
  3. _ipopt_nlp->setOptimizationProblem(problem); //将问题指针传入nlp,nlp里面的计算过程全在problem里面
  4. //如果是第一次,先计算雅可比矩阵,海森矩阵
  5. if (new_structure)
  6. {
  7. _nnz_jac_constraints = problem.computeCombinedSparseJacobiansNNZ(false, true, true);
  8. problem.computeSparseHessiansNNZ(_nnz_hes_obj, _nnz_hes_eq, _nnz_hes_ineq, true);
  9. _nnz_h_lagrangian = _nnz_hes_obj + _nnz_hes_eq + _nnz_hes_ineq;
  10. _lambda_cache.resize(problem.getEqualityDimension() + problem.getInequalityDimension());
  11. _lambda_cache.setZero();
  12. _zl_cache.resize(problem.getParameterDimension());
  13. _zl_cache.setZero();
  14. _zu_cache.resize(problem.getParameterDimension());
  15. _zu_cache.setZero();
  16. // set max number of iterations
  17. _ipopt_app->Options()->SetIntegerValue("max_iter", _iterations); // max_cpu_time // TODO(roesmann) parameter for number of iterations
  18. }
  19. if (_max_cpu_time > 0)
  20. _ipopt_app->Options()->SetNumericValue("max_cpu_time", _max_cpu_time);
  21. else if (_max_cpu_time == 0)
  22. _ipopt_app->Options()->SetNumericValue("max_cpu_time", 10e6);
  23. Ipopt::ApplicationReturnStatus ipopt_status;
  24. if (new_structure)
  25. ipopt_status = _ipopt_app->OptimizeTNLP(_ipopt_nlp); //执行优化
  26. else
  27. ipopt_status = _ipopt_app->ReOptimizeTNLP(_ipopt_nlp);
  28. if (obj_value) *obj_value = _last_obj_value;
  29. return convertIpoptToNlpSolverStatus(ipopt_status);
  30. }

ipoptWrapper接口

  1. //计算目标函数
  2. eval_f()
  3. {
  4. if (new_x)
  5. {
  6. Eigen::Map<const Eigen::VectorXd> x_map(x, n);
  7. _problem->setParameterVector(x_map);
  8. if (_solver->_cache_first_order_derivatives) precompute1stOrderDerivatives();
  9. }
  10. obj_value = _problem->computeValueObjective();
  11. }
  12. //计算约束g(x)
  13. eval_g()
  14. {
  15. if (new_x)
  16. {
  17. Eigen::Map<const Eigen::VectorXd> x_map(x, n);
  18. _problem->setParameterVector(x_map);
  19. if (_solver->_cache_first_order_derivatives) precompute1stOrderDerivatives();
  20. }
  21. Eigen::Map<Eigen::VectorXd> g_map(g, m);
  22. _problem->computeValuesEquality(g_map.head(_problem->getEqualityDimension()));
  23. _problem->computeValuesInequality(g_map.tail(_problem->getInequalityDimension()));
  24. }
  25. //计算雅可比
  26. eval_jac_g()
  27. {
  28. if (new_x)
  29. {
  30. Eigen::Map<const Eigen::VectorXd> x_map(x, n);
  31. _problem->setParameterVector(x_map);
  32. if (_solver->_cache_first_order_derivatives) precompute1stOrderDerivatives();
  33. }
  34. Eigen::Map<Eigen::VectorXd> values_map(values, nele_jac);
  35. if (_solver->_cache_first_order_derivatives)
  36. values_map = _solver->_jac_constr_cache;
  37. else
  38. _problem->computeCombinedSparseJacobiansValues(values_map, false, true, true);
  39. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/213640
推荐阅读
相关标签
  

闽ICP备14008679号