zoukankan      html  css  js  c++  java
  • ROS naviagtion analysis: costmap_2d--StaticLayer

    博客转载自:https://blog.csdn.net/u013158492/article/details/50493246

    从UML中能够看到,StaticLayer主要是在实现Layer层要求实现的接口。

    virtual void onInitialize();
      virtual void activate();
      virtual void deactivate();
      virtual void reset();
      virtual void updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y,double* max_x, double* max_y);
      virtual void updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j);
      virtual void matchSize();
    

    函数virtual void activate()

    void StaticLayer::activate()
    {
      onInitialize();
    }
    

    而函数onInitialize() 中,首先初始化了一堆参数,然后调用

    map_sub_ = g_nh.subscribe(map_topic, 1, &StaticLayer::incomingMap, this);//一旦收到topic 是“map”的消息,就调用`incomingMap`
    

      

     while (!map_received_ && g_nh.ok())
     {
       ros::spinOnce();
       r.sleep();
     }//如果map_received_一直是false,则阻塞在这里。而更新map_received_的地方在回调函数incomingMap
    

    接下来判断是否接受static map的更新,如果是则开启对topic为map_topic + "_updates" 的更新。最后开启参数动态配置服务。 

    函数matchSize 中的操作依然是根据master map的尺寸,更新本层的尺寸:

    void StaticLayer::matchSize()
    {
      // If we are using rolling costmap, the static map size is
      //   unrelated to the size of the layered costmap
      if (!layered_costmap_->isRolling())
      {
        Costmap2D* master = layered_costmap_->getCostmap();
        resizeMap(master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
                  master->getOriginX(), master->getOriginY());
      }
    }
    

    函数interpretValue 则是将参数根据阈值,设定为NO_INFORMATION  FREE_SPACE LETHAL_OBSTACLE FREE_SPACE 或者其他值。

    unsigned char StaticLayer::interpretValue(unsigned char value)
    {
      // check if the static value is above the unknown or lethal thresholds
      if (track_unknown_space_ && value == unknown_cost_value_)
        return NO_INFORMATION;
      else if (!track_unknown_space_ && value == unknown_cost_value_)
        return FREE_SPACE;
      else if (value >= lethal_threshold_)
        return LETHAL_OBSTACLE;
      else if (trinary_costmap_)
        return FREE_SPACE;
    
      double scale = (double) value / lethal_threshold_;
      return scale * LETHAL_OBSTACLE;
    }
    

    以下分析回调函数incomingMap

    void StaticLayer::incomingMap(const nav_msgs::OccupancyGridConstPtr& new_map)
    {
      unsigned int size_x = new_map->info.width, size_y = new_map->info.height;
    
      ROS_DEBUG("Received a %d X %d map at %f m/pix", size_x, size_y, new_map->info.resolution);
    
      // resize costmap if size, resolution or origin do not match
      //这里判断master map的尺寸是否和获取到的static map一致,如果不一致,则应该修改master map
      Costmap2D* master = layered_costmap_->getCostmap();
      if (!layered_costmap_->isRolling() && (master->getSizeInCellsX() != size_x ||
          master->getSizeInCellsY() != size_y ||
          master->getResolution() != new_map->info.resolution ||
          master->getOriginX() != new_map->info.origin.position.x ||
          master->getOriginY() != new_map->info.origin.position.y ||
          !layered_costmap_->isSizeLocked()))
      {
        // Update the size of the layered costmap (and all layers, including this one)
        ROS_INFO("Resizing costmap to %d X %d at %f m/pix", size_x, size_y, new_map->info.resolution);
        layered_costmap_->resizeMap(size_x, size_y, new_map->info.resolution, new_map->info.origin.position.x, new_map->info.origin.position.y, true);//修改了master map
      }
      //如果本层的数据和订阅到的map尺寸不一致,则更新本层的尺寸
      else if (size_x_ != size_x || size_y_ != size_y ||
               resolution_ != new_map->info.resolution ||
               origin_x_ != new_map->info.origin.position.x ||
               origin_y_ != new_map->info.origin.position.y)
      {
        // only update the size of the costmap stored locally in this layer
        ROS_INFO("Resizing static layer to %d X %d at %f m/pix", size_x, size_y, new_map->info.resolution);
        resizeMap(size_x, size_y, new_map->info.resolution,new_map->info.origin.position.x, new_map->info.origin.position.y);
      }
    
      unsigned int index = 0;
    
      // initialize the costmap with static data
      //这里将订阅拿到的map数据拷贝到了本层static map的数据成员`costmap_`
      for (unsigned int i = 0; i < size_y; ++i)
      {
        for (unsigned int j = 0; j < size_x; ++j)
        {
          unsigned char value = new_map->data[index];
          costmap_[index] = interpretValue(value);
          ++index;
        }
      }
      map_frame_ = new_map->header.frame_id;
    
      // we have a new map, update full size of map
      x_ = y_ = 0;
      width_ = size_x_;
      height_ = size_y_;
      map_received_ = true;
      has_updated_data_ = true;
    
      // shutdown the map subscrber if firt_map_only_ flag is on
      if (first_map_only_)
      {
        map_sub_.shutdown();
      }
    }
    

    函数 updateBounds 这里设定为整张static map的大小:

    void StaticLayer::updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y,
                                   double* max_x, double* max_y)
    {
    
      if( !layered_costmap_->isRolling() ){
        if (!map_received_ || !(has_updated_data_ || has_extra_bounds_))
          return;
      }
    
      useExtraBounds(min_x, min_y, max_x, max_y);
    
      double wx, wy;
    
      mapToWorld(x_, y_, wx, wy);
      *min_x = std::min(wx, *min_x);
      *min_y = std::min(wy, *min_y);
    
      mapToWorld(x_ + width_, y_ + height_, wx, wy);
      *max_x = std::max(wx, *max_x);
      *max_y = std::max(wy, *max_y);
    
      has_updated_data_ = false;
    }
    

    函数 updateCosts

    void StaticLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
    {
      if (!map_received_)
        return;
    
      if (!layered_costmap_->isRolling())
      {
        // if not rolling, the layered costmap (master_grid) has same coordinates as this layer这里如果不是rolling 选项,则直接将本层数据copy到master map,因为它们尺寸也一样
        if (!use_maximum_)
          updateWithTrueOverwrite(master_grid, min_i, min_j, max_i, max_j);
        else
          updateWithMax(master_grid, min_i, min_j, max_i, max_j);
      }
      else
      {
        // If rolling window, the master_grid is unlikely to have same coordinates as this layer
        unsigned int mx, my;
        double wx, wy;
        // Might even be in a different frame
        //首先获得map坐标系相对于global坐标系的位置,这个时候的map坐标系是随着机器人运动而运动的。
        tf::StampedTransform transform;
        try
        {
          tf_->lookupTransform(map_frame_, global_frame_, ros::Time(0), transform);
        }
        catch (tf::TransformException ex)
        {
          ROS_ERROR("%s", ex.what());
          return;
        }
        // Copy map data given proper transformations
        for (unsigned int i = min_i; i < max_i; ++i)
        {
          for (unsigned int j = min_j; j < max_j; ++j)
          {
            // Convert master_grid coordinates (i,j) into global_frame_(wx,wy) coordinates
            layered_costmap_->getCostmap()->mapToWorld(i, j, wx, wy);
            // Transform from global_frame_ to map_frame_
            tf::Point p(wx, wy, 0);
            p = transform(p);
            // Set master_grid with cell from map
            if (worldToMap(p.x(), p.y(), mx, my))
            {
              if (!use_maximum_)
                master_grid.setCost(i, j, getCost(mx, my));
              else
                master_grid.setCost(i, j, std::max(getCost(mx, my), master_grid.getCost(i, j)));
            }
          }
        }
      }
    }
    

    重点是这两句:

    if (worldToMap(p.x(), p.y(), mx, my))
    {
      if (!use_maximum_)
         master_grid.setCost(i, j, getCost(mx, my));
    

    将static map层的每一点(i,j),都找到对应的master map的(mx,my),这样就可以直接更改master map的对应点了。 


    OK,静态地图分析到此为止~接下来分析Obstacle 层,这个略微要难点。

  • 相关阅读:
    VC:文件串行化(CFileDialog类、CFile类、CArchive类、Edit控件)
    实例说明optimize table在优化mysql时很重要
    文件备份,同步工具rsync服务器端的安装及配置
    log4cxx does not compile on kernel 2.6.29.6
    CentOS桌面安装
    编译 apachelog4cxx0.10.0inputstreamreader.cpp:66: error: ‘memmove’ was not declared in this sco
    解决/usr/bin/ld: cannot find lmysqlclient错误
    mysql 复制表数据,表结构的3种方法
    php 动态添加OPENSSL模块
    mysql开启慢查询方法
  • 原文地址:https://www.cnblogs.com/flyinggod/p/9083416.html
Copyright © 2011-2022 走看看