ROS costmap2d 不断发布global_costmap

博主最近在做自主全局规划时需要实时获得全局不断更新的global_costmap。

搜索costmap_2d的roswiki官方文档,发现costmap_2d会发布以下两个话题:

然而,经过实际测试,我们订阅第一个话题:/move_base/global_costmap/costmap 却只能收到一次消息,而第二个话题/move_base/global_costmap/costmap_updates在不断发布,但只发布更新部分,也就是只在地图中的一部分。我们如果要手动更新再拼接,会非常麻烦。

初步阅读costmap_2d的源码后,我发现publish函数在此定义:

costmap_2d_publisher.cpp

void Costmap2DPublisher::publishCostmap()
{
  if (costmap_pub_.getNumSubscribers() == 0)
  {
    // No subscribers, so why do any work?
    return;
  }

  boost::unique_lock<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
  float resolution = costmap_->getResolution();

  if (always_send_full_costmap_ || grid_.info.resolution != resolution ||
      grid_.info.width != costmap_->getSizeInCellsX() ||
      grid_.info.height != costmap_->getSizeInCellsY() ||
      saved_origin_x_ != costmap_->getOriginX() ||
      saved_origin_y_ != costmap_->getOriginY())
  {
    prepareGrid();
    costmap_pub_.publish(grid_);
  }
  else if (x0_ < xn_)
  {
    // Publish Just an Update
    map_msgs::OccupancyGridUpdate update;
    update.header.stamp = ros::Time::now();
    update.header.frame_id = global_frame_;
    update.x = x0_;
    update.y = y0_;
    update.width = xn_ - x0_;
    update.height = yn_ - y0_;
    update.data.resize(update.width * update.height);

    unsigned int i = 0;
    for (unsigned int y = y0_; y < yn_; y++)
    {
      for (unsigned int x = x0_; x < xn_; x++)
      {
        unsigned char cost = costmap_->getCost(x, y);
        update.data[i++] = cost_translation_table_[ cost ];
      }
    }
    costmap_update_pub_.publish(update);
  }

  xn_ = yn_ = 0;
  x0_ = costmap_->getSizeInCellsX();
  y0_ = costmap_->getSizeInCellsY();
}

其中costmap_pub_就对应第一个发布话题,costmap_update_pub_对应第二个发布话题。

从源码中可以发现,只有当always_send_full_costmap_参数为真或者地图的参数(原点、高宽、resolution)发生改变时,才会重新发布。然而always_send_full_costmap_在代码中默认定义为假:

private_nh.param("always_send_full_costmap", always_send_full_costmap, false);

这就可以解释为什么不会一直发布全局costmap。

最简单的修改方式是在if语句中加一个true:

if (true || always_send_full_costmap_ || grid_.info.resolution != resolution ||
      grid_.info.width != costmap_->getSizeInCellsX() ||
      grid_.info.height != costmap_->getSizeInCellsY() ||
      saved_origin_x_ != costmap_->getOriginX() ||
      saved_origin_y_ != costmap_->getOriginY())
  {
    prepareGrid();
    costmap_pub_.publish(grid_);
  }

经过测试,全局costmap也会一直发布。

note:博主发现发布频率跟不上设定频率,有可能是算力受限,可能需要将全局地图缩小。一直发布也可能占用一些算力。

---------------------------------------------------------------------------------------------------------------------------------更新:博主发现可以直接改参数QAQ

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
给下列程序添加注释:void DWAPlannerROS::initialize( std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) { if (! isInitialized()) { ros::NodeHandle private_nh("~/" + name); g_plan_pub_ = private_nh.advertise<nav_msgs::Path>("global_plan", 1); l_plan_pub_ = private_nh.advertise<nav_msgs::Path>("local_plan", 1); tf_ = tf; costmap_ros_ = costmap_ros; costmap_ros_->getRobotPose(current_pose_); // make sure to update the costmap we'll use for this cycle costmap_2d::Costmap2D* costmap = costmap_ros_->getCostmap(); planner_util_.initialize(tf, costmap, costmap_ros_->getGlobalFrameID()); //create the actual planner that we'll use.. it'll configure itself from the parameter server dp_ = boost::shared_ptr<DWAPlanner>(new DWAPlanner(name, &planner_util_)); if( private_nh.getParam( "odom_topic", odom_topic_ )) { odom_helper_.setOdomTopic( odom_topic_ ); } initialized_ = true; // Warn about deprecated parameters -- remove this block in N-turtle nav_core::warnRenamedParameter(private_nh, "max_vel_trans", "max_trans_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_trans", "min_trans_vel"); nav_core::warnRenamedParameter(private_nh, "max_vel_theta", "max_rot_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_theta", "min_rot_vel"); nav_core::warnRenamedParameter(private_nh, "acc_lim_trans", "acc_limit_trans"); nav_core::warnRenamedParameter(private_nh, "theta_stopped_vel", "rot_stopped_vel"); dsrv_ = new dynamic_reconfigure::Server<DWAPlannerConfig>(private_nh); dynamic_reconfigure::Server<DWAPlannerConfig>::CallbackType cb = boost::bind(&DWAPlannerROS::reconfigureCB, this, _1, 2); dsrv->setCallback(cb); } else{ ROS_WARN("This planner has already been initialized, doing nothing."); } }
06-12
/** * @brief 初始化DWAPlannerROS的函数 * * @param name: 节点名字 * @param tf: tf2_ros::Buffer类型指针,用于获取tf信息 * @param costmap_ros: costmap_2d::Costmap2DROS类型指针,用于获取costmap信息 */ void DWAPlannerROS::initialize(std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) { // 判断是否已经初始化 if (!isInitialized()) { // 创建私有命名空间 ros::NodeHandle private_nh("~/" + name); // 创建两个Publisher,用于发布全局规划和局部规划 g_plan_pub_ = private_nh.advertise<nav_msgs::Path>("global_plan", 1); l_plan_pub_ = private_nh.advertise<nav_msgs::Path>("local_plan", 1); // 获取tf信息和costmap信息 tf_ = tf; costmap_ros_ = costmap_ros; costmap_ros_->getRobotPose(current_pose_); // 更新costmap costmap_2d::Costmap2D* costmap = costmap_ros_->getCostmap(); // 初始化planner_util_ planner_util_.initialize(tf, costmap, costmap_ros_->getGlobalFrameID()); // 创建DWAPlanner对象,从参数服务器上获取参数 dp_ = boost::shared_ptr<DWAPlanner>(new DWAPlanner(name, &planner_util_)); if (private_nh.getParam("odom_topic", odom_topic_)) { odom_helper_.setOdomTopic(odom_topic_); } // 设置initialized_为true initialized_ = true; // 警告已经被弃用的参数 nav_core::warnRenamedParameter(private_nh, "max_vel_trans", "max_trans_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_trans", "min_trans_vel"); nav_core::warnRenamedParameter(private_nh, "max_vel_theta", "max_rot_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_theta", "min_rot_vel"); nav_core::warnRenamedParameter(private_nh, "acc_lim_trans", "acc_limit_trans"); nav_core::warnRenamedParameter(private_nh, "theta_stopped_vel", "rot_stopped_vel"); // 创建dynamic_reconfigure::Server对象,用于动态参数配置 dsrv_ = new dynamic_reconfigure::Server<DWAPlannerConfig>(private_nh); dynamic_reconfigure::Server<DWAPlannerConfig>::CallbackType cb = boost::bind(&DWAPlannerROS::reconfigureCB, this, _1, 2); dsrv_->setCallback(cb); } else { // 如果已经初始化,输出警告信息 ROS_WARN("This planner has already been initialized, doing nothing."); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值