首先解释一下这个包是用来干嘛的?
clear_costmap_recovery::ClearCostmapRecovery是一种简单的修复机制,它将距离机器人一定距离范围区域外的代价地图恢复为静态地图。 其继承了nav_core包中nav_core::RecoveryBehavior ,以插件方式在move_base node中使用。
其中参数的作用
~
~
以下是源码解读
#include
#include
#include
//register this planner as a RecoveryBehavior plugin
PLUGINLIB_DECLARE_CLASS(clear_costmap_recovery, ClearCostmapRecovery, clear_costmap_recovery::ClearCostmapRecovery, nav_core::RecoveryBehavior)
using costmap_2d::NO_INFORMATION;
namespace clear_costmap_recovery {
ClearCostmapRecovery::ClearCostmapRecovery(): global_costmap_(NULL), local_costmap_(NULL),
tf_(NULL), initialized_(false) {}
void ClearCostmapRecovery::initialize(std::string name, tf::TransformListener* tf,
costmap_2d::Costmap2DROS* global_costmap, costmap_2d::Costmap2DROS* local_costmap){
if(!initialized_){
name_ = name;
tf_ = tf;
global_costmap_ = global_costmap;
local_costmap_ = local_costmap;
//get some parameters from the parameter server
ros::NodeHandle private_nh("~/" + name_);
private_nh.param("reset_distance", reset_distance_, 3.0);//设置默认的距离
std::vector clearable_layers_default, clearable_layers;
clearable_layers_default.push_back( std::string("obstacles") );//设置默认要被清除的层
private_nh.param("layer_names", clearable_layers, clearable_layers_default);//从参数空间引入要被清除的层
for(unsigned i=0; i < clearable_layers.size(); i++) {
ROS_INFO("Recovery behavior will clear layer %s", clearable_layers[i].c_str());
clearable_layers_.insert(clearable_layers[i]);//因为参数是个vector 所以逐一插入
}
initialized_ = true;
}
else{
ROS_ERROR("You should not call initialize twice on this object, doing nothing");
}
}
void ClearCostmapRecovery::runBehavior(){
if(!initialized_){
ROS_ERROR("This object must be initialized before runBehavior is called");
return;
}
if(global_costmap_ == NULL || local_costmap_ == NULL){
ROS_ERROR("The costmaps passed to the ClearCostmapRecovery object cannot be NULL. Doing nothing.");
return;
}
ROS_WARN("Clearing costmap to unstuck robot (%fm).", reset_distance_);
clear(global_costmap_);//清除全局地图的层
clear(local_costmap_);//清除局部地图的层
}
void ClearCostmapRecovery::clear(costmap_2d::Costmap2DROS* costmap){
std::vector >* plugins = costmap->getLayeredCostmap()->getPlugins();
tf::Stamped pose;
if(!costmap->getRobotPose(pose)){
ROS_ERROR("Cannot clear map because pose cannot be retrieved");
return;
}
double x = pose.getOrigin().x();
double y = pose.getOrigin().y();
for (std::vector >::iterator pluginp = plugins->begin(); pluginp != plugins->end(); ++pluginp) {
boost::shared_ptr plugin = *pluginp;
std::string name = plugin->getName();
int slash = name.rfind('/');
if( slash != std::string::npos ){
name = name.substr(slash+1);
}
if(clearable_layers_.count(name)!=0){
//将plugin的名字(层的名字与我们的要清除的层的名字进行对比) 如果是则清除
boost::shared_ptr costmap;
costmap = boost::static_pointer_cast(plugin);
clearMap(costmap, x, y);
}
}
}
看看这个是在哪里被调用的 是在move_base.cpp 里面
//we'll load our default recovery behaviors here
void MoveBase::loadDefaultRecoveryBehaviors(){
recovery_behaviors_.clear();
try{
//we need to set some parameters based on what's been passed in to us to maintain backwards compatibility
ros::NodeHandle n("~");
//这里设置了机器人要清除的距离参数
n.setParam("conservative_reset/reset_distance", conservative_reset_dist_);
n.setParam("aggressive_reset/reset_distance", circumscribed_radius_ * 4);
//这个地方就是首先movebase 会把各个recovery机制引进进来 源码这个地方并没有设置要清除的层的参数 所
//以默认还是obstalces层
boost::shared_ptr cons_clear(recovery_loader_.createInstance("clear_costmap_recovery/ClearCostmapRecovery"));
cons_clear->initialize("conservative_reset", &tf_, planner_costmap_ros_, controller_costmap_ros_);
recovery_behaviors_.push_back(cons_clear);
//next, we'll load a recovery behavior to rotate in place
boost::shared_ptr rotate(recovery_loader_.createInstance("rotate_recovery/RotateRecovery"));
if(clearing_rotation_allowed_){
rotate->initialize("rotate_recovery", &tf_, planner_costmap_ros_, controller_costmap_ros_);
recovery_behaviors_.push_back(rotate);
}
//next, we'll load a recovery behavior that will do an aggressive reset of the costmap
boost::shared_ptr ags_clear(recovery_loader_.createInstance("clear_costmap_recovery/ClearCostmapRecovery"));
ags_clear->initialize("aggressive_reset", &tf_, planner_costmap_ros_, controller_costmap_ros_);
recovery_behaviors_.push_back(ags_clear);
//we'll rotate in-place one more time
if(clearing_rotation_allowed_)
recovery_behaviors_.push_back(rotate);
}
catch(pluginlib::PluginlibException& ex){
ROS_FATAL("Failed to load a plugin. This should not happen on default recovery behaviors. Error: %s", ex.what());
}
return;
}
在哪里是使用 是在movebase 主程序里面 机器人状态的CLEARING 状态下进行的地图清除
//we'll try to clear out space with any user-provided recovery behaviors
case CLEARING:
ROS_DEBUG_NAMED("move_base","In clearing/recovery state");
//we'll invoke whatever recovery behavior we're currently on if they're enabled
if(recovery_behavior_enabled_ && recovery_index_ < recovery_behaviors_.size()){
ROS_DEBUG_NAMED("move_base_recovery","Executing behavior %u of %zu", recovery_index_, recovery_behaviors_.size());
recovery_behaviors_[recovery_index_]->runBehavior();
//we at least want to give the robot some time to stop oscillating after executing the behavior
last_oscillation_reset_ = ros::Time::now();
//we'll check if the recovery behavior actually worked
ROS_DEBUG_NAMED("move_base_recovery","Going back to planning state");
last_valid_plan_ = ros::Time::now();
planning_retries_ = 0;
state_ = PLANNING;
//update the index of the next recovery behavior that we'll try
recovery_index_++;
}
else{
ROS_DEBUG_NAMED("move_base_recovery","All recovery behaviors have failed, locking the planner and disabling it.");
//disable the planner thread
boost::unique_lock lock(planner_mutex_);
runPlanner_ = false;
lock.unlock();
ROS_DEBUG_NAMED("move_base_recovery","Something should abort after this.");
if(recovery_trigger_ == CONTROLLING_R){
ROS_ERROR("Aborting because a valid control could not be found. Even after executing all recovery behaviors");
as_->setAborted(move_base_msgs::MoveBaseResult(), "Failed to find a valid control. Even after executing recovery behaviors.");
}
else if(recovery_trigger_ == PLANNING_R){
ROS_ERROR("Aborting because a valid plan could not be found. Even after executing all recovery behaviors");
as_->setAborted(move_base_msgs::MoveBaseResult(), "Failed to find a valid plan. Even after executing recovery behaviors.");
}
else if(recovery_trigger_ == OSCILLATION_R){
ROS_ERROR("Aborting because the robot appears to be oscillating over and over. Even after executing all recovery behaviors");
as_->setAborted(move_base_msgs::MoveBaseResult(), "Robot is oscillating. Even after executing recovery behaviors.");
}
resetState();
return true;
}
break;
如何让障碍物信息及时清除呢 原来这一块写了这个博客但是 发现错了 所以重新写了一篇新博客 请看下一篇 如何及时清除