ros如何及时清除障碍物层或者超声波层的的消息 clear_costmap_recovery 代码详解

首先解释一下这个包是用来干嘛的?

clear_costmap_recovery::ClearCostmapRecovery是一种简单的修复机制,它将距离机器人一定距离范围区域外的代价地图恢复为静态地图。 其继承了nav_core包中nav_core::RecoveryBehavior ,以插件方式在move_base node中使用。

其中参数的作用

~<name>/reset_distance (double, default: 3.0)指定距离机器人半径几米的区域之外的障碍在恢复代价地图为静态地图时候将被清除。

~<name>/layer_names (std::vector, default:"obstacles" )哪一层的信息将会被清除


以下是源码解读

#include <clear_costmap_recovery/clear_costmap_recovery.h>
#include <pluginlib/class_list_macros.h>
#include <vector>

//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<std::string> 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<boost::shared_ptr<costmap_2d::Layer> >* plugins = costmap->getLayeredCostmap()->getPlugins();

  tf::Stamped<tf::Pose> 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<boost::shared_ptr<costmap_2d::Layer> >::iterator pluginp = plugins->begin(); pluginp != plugins->end(); ++pluginp) {
    boost::shared_ptr<costmap_2d::Layer> 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_2d::CostmapLayer> costmap;
      costmap = boost::static_pointer_cast<costmap_2d::CostmapLayer>(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<nav_core::RecoveryBehavior> 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<nav_core::RecoveryBehavior> 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<nav_core::RecoveryBehavior> 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<boost::recursive_mutex> 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;

如何让障碍物信息及时清除呢 原来这一块写了这个博客但是 发现错了 所以重新写了一篇新博客 请看下一篇 如何及时清除

### 回答1: 超声波避障是一种常见的机器人避障控制方法,下面是一个用Python编写的超声波避障代码示例: ```python import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) # 定义超声波模块的引脚 TRIG_PIN = 23 ECHO_PIN = 24 GPIO.setup(TRIG_PIN, GPIO.OUT) GPIO.setup(ECHO_PIN, GPIO.IN) def get_distance(): # 发送超声波信号 GPIO.output(TRIG_PIN, GPIO.HIGH) time.sleep(0.0001) GPIO.output(TRIG_PIN, GPIO.LOW) # 接收超声波回波 while GPIO.input(ECHO_PIN) == GPIO.LOW: start_time = time.time() while GPIO.input(ECHO_PIN) == GPIO.HIGH: end_time = time.time() # 计算距离 duration = end_time - start_time distance = duration * 34300 / 2 # 声速为343m/s distance = round(distance, 2) return distance def avoid_obstacle(): distance = get_distance() print("当前距离:", distance, "cm") if distance < 10: # 超过10cm才开始避障 print("避障中...") # 控制机器人避障动作 # 例如向左转或向右转 avoid_obstacle() GPIO.cleanup() ``` 该代码中使用RPi.GPIO库来控制树莓派的GPIO引脚。首先需要设置超声波模块的引脚为输出和输入模式,并定义了触发信号的引脚和回波信号的引脚。`get_distance()`函数用于测量超声波的回波时长,并通过声速计算出距离。`avoid_obstacle()`函数用于根据测得的距离进行避障动作。在主程序中,调用`avoid_obstacle()`函数来进行避障操作,并通过cleanup()函数清理GPIO引脚的设置。 ### 回答2: 下面是一个用Python编写的超声波避障代码示例: ```python import RPi.GPIO as GPIO import time # 设置GPIO引脚号 TRIG_PIN = 17 ECHO_PIN = 27 def setup(): # 设置GPIO模式 GPIO.setmode(GPIO.BCM) GPIO.setup(TRIG_PIN, GPIO.OUT) GPIO.setup(ECHO_PIN, GPIO.IN) def get_distance(): # 发送超声波 GPIO.output(TRIG_PIN, GPIO.HIGH) time.sleep(0.000015) GPIO.output(TRIG_PIN, GPIO.LOW) # 接收信号并计算距离 while GPIO.input(ECHO_PIN) == GPIO.LOW: pass pulse_start = time.time() while GPIO.input(ECHO_PIN) == GPIO.HIGH: pass pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = round(distance, 2) return distance def loop(): while True: distance = get_distance() print("距离:%0.2fcm" % distance) if distance < 20: print("前方有障碍物,停止前进!") # 这里可以添加停止前进的代码 time.sleep(1) def destroy(): # 清理GPIO引脚 GPIO.cleanup() if __name__ == '__main__': try: setup() loop() except KeyboardInterrupt: destroy() ``` 这个代码使用了树莓派的RPi.GPIO库来控制GPIO引脚。首先,在`setup()`函数中设置了超声波的发送引脚(TRIG_PIN)为输出模式,接收引脚(ECHO_PIN)为输入模式。然后,在`get_distance()`函数中发送超声波并接收回波,并根据回波的时间计算距离。最后,在`loop()`函数中不断获取距离并判断是否有障碍物,如果有障碍物,则停止前进。 在`main`函数中,我们调用`setup()`函数来初始化GPIO引脚,然后进入`loop()`函数进行循环检测距离。如果检测到键盘中断(Ctrl+C),则调用`destroy()`函数来清理GPIO引脚。 ### 回答3: 超声波避障代码是用Python编写的,主要通过超声波传感器探测前方障碍物的距离,然后根据距离判断是否需要避障。 首先,我们需要导入相应的库,例如RPi.GPIO用于控制树莓派的GPIO针脚,以及time用于定时操作。 然后,我们需要设置GPIO针脚的模式(输入或输出)。超声波传感器分为触发引脚和接收引脚,我们需要将触发引脚设置为输出,接收引脚设置为输入。 接下来,我们需要定义函数来测量距离。首先,将触发引脚设置为高电平,持续10微秒,然后将其设置为低电平。接收引脚会接收到超声波的回响,我们需要计算回响时间并将其转换为距离。 最后,我们可以使用一个无限循环来不断测量距离,如果距离小于设定的阈值,则表示有障碍物需要避障。我们可以通过控制电机或舵机的行动来实现避障操作,例如停下、向后退、向左转或向右转。 需要注意的是,代码中可能还需要添加一些额外的功能,如灯光提示或声音提示,以增加避障的效果和安全性。 总结起来,超声波避障代码使用Python编写,通过超声波传感器探测距离,根据距离判断是否需要避障,并通过控制电机或舵机来实现相应的动作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值