voidTebLocalPlannerROS::initialize(std::string name, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros) { if(!initialized_) { // create Node Handle with name of plugin (as used in move_base for loading) ros::NodeHandle nh("~/" + name); // get parameters of TebConfig via the nodehandle and override the default config cfg_.loadRosParamFromNodeHandle(nh); // TebConfig cfg_; // nh.param("trapped_threshold", trapped_threshold_, 20); nh.param("filter_back_velocity", filter_back_velocity_, true); // nh.param("setting_acc", setting_acc_, 1.5);
obstacles_.reserve(500); // ObstContainer obstacles_; // 在TebVisualization构造函数里,注册话题 global_plan, local_plan,teb_poses, teb_markers, teb_feedback visualization_ = TebVisualizationPtr(newTebVisualization(nh, cfg_)); //创建robot footprint/contour model for optimization,对5种类型分别处理 // 点类型最简单,返回新建的PointRobotFootprint共享指针 // 对于polygon类型,只对 Point2dContainer vertices_;赋值 RobotFootprintModelPtr robot_model = getRobotFootprintFromParamServer(nh); // 根据参数,选择创建哪种 planner if (cfg_.hcp.enable_homotopy_class_planning) { planner_ = PlannerInterfacePtr(newHomotopyClassPlanner(cfg_, &obstacles_, robot_model, visualization_, &via_points_)); ROS_INFO("Parallel planning in distinctive topologies enabled."); } else { planner_ = PlannerInterfacePtr(newTebOptimalPlanner(cfg_, &obstacles_, robot_model, visualization_, &via_points_)); ROS_INFO("Parallel planning in distinctive topologies disabled."); } // init other variables tf_ = tf; // 在 move_base_node.cpp中最初定义 // 这个就是 controller_costmap_ros_ = new costmap_2d::Costmap2DROS("local_costmap", tf_); costmap_ros_ = costmap_ros; // locking should be done in MoveBase costmap_ = costmap_ros_->getCostmap();
if (cfg_.trajectory.global_plan_overwrite_orientation) { robot_goal_.theta() = estimateLocalGoalOrientation(global_plan_, goal_point, goal_idx, tf_plan_to_global); // overwrite/update goal orientation of the transformed plan with the actual goal // (enable using the plan as initialization) transformed_plan.back().pose.orientation = tf::createQuaternionMsgFromYaw(robot_goal_.theta()); } else robot_goal_.theta() = tf::getYaw(goal_point.getRotation());
// plan only contains the goal, 一般在导航的最后出现size是1的情况 // 用实际的机器人位姿更新 transformed plan 的起点(allows using the plan as initial trajectory) if (transformed_plan.size()==1) { // 插入起点,但不初始化 transformed_plan.insert(transformed_plan.begin(), geometry_msgs::PoseStamped() ); } tf::poseTFToMsg(robot_pose, transformed_plan.front().pose); // 把起点更新为 机器人当前位姿
time elastic band(时间橡皮筋)从elastic band算法(1993年提出)优化而来。TEB的初始轨迹是全局路径传来的transformed_plan,中间插入N个控制橡皮筋形状的路径点(机器人位姿),在点与点之间定义时间差,转换为明确依赖于时间的轨迹,从而实现对机器人的实时控制。由于其模块化的形式,该方法可以扩展目标函数和约束。
TEB中实现了两种规划器,一个就是普通的TebOptimalPlanner,另一个是HomotopyClassPlanner,HomotopyClassPlanner是一种同时优化多个轨迹的方法,由于目标函数的非凸性(非凸函数)会生成一系列最优的候选轨迹,最终在备选局部解的集合中寻求总体最佳候选轨迹,对应论文:《Integrated online trajectory planning and optimization in distinctive topologies》
使用Depth First Search(深度优先方法)搜索所有可行的路径。将这些路径作为参考,实例化多个TebOptimalPlanner类的实例。采用多线程并行优化,得到多条优化后的路径。将这些路径进行可行性分析,选出代价值最小的最优路径。不得不说HomotopyClassPlanner类里的方法是一个鲁棒性和可靠性更高的方法。