本文链接地址: 局部规划器-TebLocalPlannerROS
Content:
由于Teb算法能很好的支持阿克曼小车,这儿使用TebLocalPlannerROS进行局部规划
在Move Base初始化中通过参数指定base_local_planner为teb_local_planner/TebLocalPlannerROS
private_nh.param("base_local_planner", local_planner, std::string("base_local_planner/TrajectoryPlannerROS")); //create a local planner try { tc_ = blp_loader_.createInstance(local_planner); ROS_INFO("Created local_planner %s", local_planner.c_str()); tc_->initialize(blp_loader_.getName(local_planner), &tf_, controller_costmap_ros_); } catch (const pluginlib::PluginlibException& ex) { ROS_FATAL("Failed to create the %s planner, are you sure it is properly registered and that the containing library is built? Exception: %s", local_planner.c_str(), ex.what()); exit(1); } |
Move Base中通过调用tc_->computeVelocityCommands(cmd_vel)完成速度命令计算。
局部规划器初始化
void TebLocalPlannerROS::initialize(std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) { // check if the plugin is already initialized 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); // reserve some memory for obstacles obstacles_.reserve(500); // create visualization instance visualization_ = TebVisualizationPtr(new TebVisualization(nh, cfg_)); //获取小车的参数,这些参数将用于模型优化,路径计算,比如阿克曼小车的最小转弯半径 // create robot footprint/contour model for optimization RobotFootprintModelPtr robot_model = getRobotFootprintFromParamServer(nh); //这儿我们解读TebOptimalPlanner分支 // create the planner instance if (cfg_.hcp.enable_homotopy_class_planning) { planner_ = PlannerInterfacePtr(new HomotopyClassPlanner(cfg_, &obstacles_, robot_model, visualization_, &via_points_)); ROS_INFO("Parallel planning in distinctive topologies enabled."); } else { planner_ = PlannerInterfacePtr(new TebOptimalPlanner(cfg_, &obstacles_, robot_model, visualization_, &via_points_)); ROS_INFO("Parallel planning in distinctive topologies disabled."); } // init other variables tf_ = tf; costmap_ros_ = costmap_ros; costmap_ = costmap_ros_->getCostmap(); // locking should be done in MoveBase. costmap_model_ = boost::make_shared(*costmap_); global_frame_ = costmap_ros_->getGlobalFrameID(); cfg_.map_frame = global_frame_; // TODO robot_base_frame_ = costmap_ros_->getBaseFrameID(); //Initialize a costmap to polygon converter if (!cfg_.obstacles.costmap_converter_plugin.empty()) { try { costmap_converter_ = costmap_converter_loader_.createInstance(cfg_.obstacles.costmap_converter_plugin); std::string converter_name = costmap_converter_loader_.getName(cfg_.obstacles.costmap_converter_plugin); // replace '::' by '/' to convert the c++ namespace to a NodeHandle namespace boost::replace_all(converter_name, "::", "/"); costmap_converter_->setOdomTopic(cfg_.odom_topic); costmap_converter_->initialize(ros::NodeHandle(nh, "costmap_converter/" + converter_name)); costmap_converter_->setCostmap2D(costmap_); costmap_converter_->startWorker(ros::Rate(cfg_.obstacles.costmap_converter_rate), costmap_, cfg_.obstacles.costmap_converter_spin_thread); ROS_INFO_STREAM("Costmap conversion plugin " << cfg_.obstacles.costmap_converter_plugin << " loaded."); } catch(pluginlib::PluginlibException& ex) { ROS_WARN("The specified costmap converter plugin cannot be loaded. All occupied costmap cells are treaten as point obstacles. |