Fast Planner规划算法(四)—— Fast Planner程序框架


   本系列文章用于学习记录Fast-Planner规划算法的相关内容,主要学习资料是深蓝学院的移动机器人运动规划课程

   五、Fast Planner程序框架

   Fast Planner算法相关的程序存放在fast_planner文件夹内

在这里插入图片描述

   fast_planner文件夹下包含八个文件夹,各文件夹的作用如下:

   (1)、bag:脚本文件

   (2)、bspline:非均匀B样条,用于后端时间重分配部分

   (3)、bspline_opt :均匀B样条,用于后端轨迹优化部分

   (4)、path_searching:包含A*算法、Hybrid A * 算法、基于拓扑的PRM算法,三个规划算法,用于前端的路径规划

   (5)、plan_env:用于地图生成,包括栅格地图生成、ESDF生成等

   (6)、plan_manage:主文件夹,主节点所在文件夹,

   (7)、poly_traj:定义了一个多项式的轨迹类

   (8)、traj_utils:可视化相关内容

在这里插入图片描述

   要理解Fast Planner的程序框架,就应该从主节点所在的plan_manage文件夹开始:

   (1)fast_planner_node.cpp

   fast_planner_node.cpp文件是我们通过launch文件启动Fast Planner程序的接口,也是ROS中Fast Planner的主节点,该文件在完成节点初始化后,会根据参数planner的值选择进行kino_replan或者topo_replan的初始化。

在这里插入图片描述

   (2)kino_replan_fsm.cpp

   若参数planner的值为1,则执行kino_replan的初始化,kino_replan的初始化的具体程序在kino_replan_fsm.cpp文件中,这个文件也是ROS跟 Fast Planner程序的接口性程序,包括参数加载、回调、订阅等。

   kino_replan_fsm.cpp文件中的execFSMCallback函数是状态基,用于处理在机器人运行过程中遇到各种情况下,是选择急停、还是重新规划、还是继续执行等。

void KinoReplanFSM::execFSMCallback(const ros::TimerEvent& e)

   kino_replan_fsm.cpp文件中的checkCollisionCallback是用于检查碰撞的函数

void KinoReplanFSM::checkCollisionCallback(const ros::TimerEvent& e)

   kino_replan_fsm.cpp文件中的callKinodynamicReplan函数中,会调用kinodynamicReplan函数,本系列前三篇文章介绍的内容全包含在和这个函数中,即局部的包含前端和后端的规划方法。该函数在planner_manager.cpp文件中。

bool KinoReplanFSM::callKinodynamicReplan()
 bool plan_success =
      planner_manager_->kinodynamicReplan(start_pt_, start_vel_, start_acc_, end_pt_, end_vel_);

   ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

   (3)planner_manager.cpp

   kino_replan_fsm.cpp文件通过调用kinodynamicReplan函数来调用该文件。

bool FastPlannerManager::kinodynamicReplan(Eigen::Vector3d start_pt, Eigen::Vector3d start_vel,
                                           Eigen::Vector3d start_acc, Eigen::Vector3d end_pt,
                                           Eigen::Vector3d end_vel)

   kinodynamicReplan函数中完成一些初始化操作后,首先后使用Hybrid A * 算法进行前端的路径搜索,该部分内容通过调用kinodynamic_astar.cpp中的search函数完成。

 int status = kino_path_finder_->search(start_pt, start_vel, start_acc, end_pt, end_vel, true);
int KinodynamicAstar::search(Eigen::Vector3d start_pt, Eigen::Vector3d start_v, Eigen::Vector3d start_a,
                             Eigen::Vector3d end_pt, Eigen::Vector3d end_v, bool init, bool dynamic, double time_start)

   接下来会将前端得到的路径转换成B样条曲线的形式,作为后端优化的初值,该部分内容在parameterizeToBspline,这个函数的具体程序在non_uniform_bspline.cpp文件中

NonUniformBspline::parameterizeToBspline(ts, point_set, start_end_derivatives, ctrl_pts);
void NonUniformBspline::parameterizeToBspline(const double& ts, const vector<Eigen::Vector3d>& point_set,
                                              const vector<Eigen::Vector3d>& start_end_derivative,
                                              Eigen::MatrixXd&               ctrl_pts)

   接下来就是后端的使用均匀B样条及优化算法进行轨迹优化了,该部分内容是通过调用BsplineOptimizeTraj函数来完成的,该函数的具体程序在bspline_optimizer.cpp文件中

ctrl_pts = bspline_optimizers_[0]->BsplineOptimizeTraj(ctrl_pts, ts, cost_function, 1, 1);
Eigen::MatrixXd BsplineOptimizer::BsplineOptimizeTraj(const Eigen::MatrixXd& points, const double& ts,
                                                      const int& cost_function, int max_num_id,
                                                      int max_time_id)

   最后,就是时间的重分配了,通过调用非均匀的B样条来进行时间的重分配,该部分内容在类NonUniformBspline中完成,该类的具体程序在non_uniform_bspline.cpp文件中

  NonUniformBspline pos = NonUniformBspline(ctrl_pts, 3, ts);

  double to = pos.getTimeSum();
  pos.setPhysicalLimits(pp_.max_vel_, pp_.max_acc_);
  bool feasible = pos.checkFeasibility(false);

  int iter_num = 0;
  while (!feasible && ros::ok()) {

    feasible = pos.reallocateTime();

    if (++iter_num >= 3) break;
  }
NonUniformBspline::NonUniformBspline(const Eigen::MatrixXd& points, const int& order,
                                     const double& interval) {
  setUniformBspline(points, order, interval);
}

   上面就是 Fast Planner程序的大概流程,跟前三篇文章 介绍的流程是相同的。

   ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

   我们现在来看一下上面流程中,比较重要的使用均匀B样条曲线及优化算法进行后端优化的位于bspline_optimizer.cpp文件中的BsplineOptimizeTraj函数

Eigen::MatrixXd BsplineOptimizer::BsplineOptimizeTraj(const Eigen::MatrixXd& points, const double& ts,
                                                      const int& cost_function, int max_num_id,
                                                      int max_time_id)

   首先是对优化问题进行一些设置,points是控制点的初值,ts是B样条的时间,setCostFunction(cost_function)是选择在优化过程中加入那些类型的代价,如平滑、无碰撞、距离,等代价函数。

  setControlPoints(points);
  setBsplineInterval(ts);
  setCostFunction(cost_function);
  setTerminateCond(max_num_id, max_time_id);

   然后,执行optimize()函数来进行优化

 optimize();

   在optimize()函数中需要特别注意的是需要最小化的目标函数的设置,即costFunction函数的计算

 opt.set_min_objective(BsplineOptimizer::costFunction, this);

   costFunction函数计算目标函数的具体程序如下:

double BsplineOptimizer::costFunction(const std::vector<double>& x, std::vector<double>& grad,
                                      void* func_data) {
  BsplineOptimizer* opt = reinterpret_cast<BsplineOptimizer*>(func_data);
  double            cost;
  opt->combineCost(x, grad, cost);
  opt->iter_num_++;

  /* save the min cost result */
  if (cost < opt->min_cost_) {
    opt->min_cost_      = cost;
    opt->best_variable_ = x;
  }
  return cost;
}

   具体cost的计算是在其调用的combineCost函数中

void BsplineOptimizer::combineCost(const std::vector<double>& x, std::vector<double>& grad,
                                   double& f_combine) 

   在计算cost时,我们传入的是控制点,得到的是目标函数值及其梯度值



   参考资料:

   1、深蓝学院-移动机器人运动规划


  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕羽★

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值