movebase导航和地图数据的使用 - 10 static layer数据的生成和使用

Static layer的数据来源方式两种:

1. staticLayer可以从mapserver的maptopic直接接受数据。StaticLayer::incomingMap是callback.这种情况是直接使用已有的map数据。

2. 还有一种得到map数据的方法是从gmapping拿到实时发现的地图数据:

navigation/map_server/src/main.cpp:174: map_pub =n.advertise<nav_msgs::OccupancyGrid>("map",1, true);

slam_gmapping/gmapping/src/slam_gmapping.cpp:251: sst_ =node_.advertise<nav_msgs::OccupancyGrid>("map",1, true);

slam_gmapping/gmapping/src/slam_gmapping.cpp:266: sst_ =node_.advertise<nav_msgs::OccupancyGrid>("map", 1,true);





其中第2种方法中,slam_gmapping要监听scan数据,处理后,将地图发出发给maptopic:

SlamGMapping::laserCallback(constsensor_msgs::LaserScan::ConstPtr& scan)

→1. SlamGMapping::addScan(const sensor_msgs::LaserScan&scan, GMapping::OrientedPoint& gmap_pose)

将scan数据封装到GMapping::RangeReading里然后,调用boolGridSlamProcessor::processScan(const RangeReading & reading, intadaptParticles)处理这个scan.scan的数据会被保存到trajectorytree的节点里。

这里面设计到gridfast slam 算法,涉及到particle,Trajectory tree(由一些node构成),

2. SlamGMapping::updateMap(const sensor_msgs::LaserScan&scan)

使用上面保存到trajectorytree里面的数据。这个函数最终会发送地图。

首先先构建一个GMapping::ScanMatcherMap结构,这个结构用来包含地图的cell。如何填充它?是靠GMapping::ScanMatcher::registerScan来填充的。

具体填充过程貌似是要遍历trajectorytree中的节点,从节点取出range数据。依靠之前设置的角度,beam数量。来计算各个点的位置填充每个cell.Trajectory tree中每个节点保存了一些激光数据。这些激光数据在之前的处理中,保存到了trajectorytree的节点里面的。

最后发送地图。



初步怀疑trajectorytree中记录的是轨迹数据,一个轨迹中,有多个位置,每个位置关联了一组从那个位置发现的laserrange数据。是发散的。而且多个位置的发散的激光range数据覆盖的内容区域肯定有重复。遍历所有位置并依次处理他们发现的区域就可以构建地图数据。



在staticlayer中,onInitialize()函数会等待收到map数据后才会继续执行。



Static layer收到map数据后,久存处在自己的costmap_里面了。



staticlayer数据的使用:

staticlayer作为layeredCostMap的一个plugin,其包含的数据迟早要被layeredCostmap取出来和其他layer数据合并。数据合并后,会被发送出去,发给costmap这个topic.而rviz就会接受到该数据。



合并的方法是对每个layer调用其updateCosts.staticLayer和voxelLayer(继承子obstaclelayer)不同,他的坐标系和layeredCostmap的坐标系可能不同,甚至基于不同的frame.不同的坐标系,可能仅仅涉及到平移等等,而基于不同的frame可能会还必须要考虑到frame之间已有的transform.比如旋转,缩放什么(可能会有缩放)的。那么看下面代码看看staticlayer是如何将自己的数据和别的layer合并的:



void StaticLayer::updateCosts(costmap_2d::Costmap2D&master_grid, int min_i, int min_j, int max_i, int max_j)

{

//master_grid是layeredCostMap中的内容,他可能已经包含了其他layer的合并结果。staticlayer也要把述据合并到这里面。min_i, min_j, max_i,,,代表master_grid中的最小最大坐标索引,也就是2维数组的索引。

if (!map_received_)

return;



if (!layered_costmap_->isRolling())

{

// if not rolling, the layered costmap (master_grid) has samecoordinates as this layer

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 samecoordinates as this layer

unsigned int mx, my;

double wx, wy;

// Might even be in adifferent frame ,甚至frame都不同

//因为我们有很多layer要和并,那么以globalframe作为基准比较合适,而staticlayer是基于mapframe的,所以我们肯定要用到globalfram到mapframe的transform.

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)

{

//i, j 是mastergrid中的索引,是整数,并且这个索引不是ros坐标系中的坐标,ros坐标系中的坐标都是double类型,所以他们并不基于任何frame.只是一个2维数组的索引,需要把它转换成一个world的double类型的坐标。此外,更重要的是还需要注意这些2维数组索引对应的格子是有分辨率resolution的,所以需要调用mapToWorld().将格子索引坐标转换成world的基于米的真正坐标。得到的结果是基于global frame的world坐标系的坐标,转换如下:因为master_grida是layeredCostMap的,所以这里需要调用layeredCostMap的mapToWorld函数。

// Convert master_gridcoordinates (i,j) into global_frame_(wx,wy) coordinates

layered_costmap_->getCostmap()->mapToWorld(i, j, wx,wy);

// Transform fromglobal_frame_ to map_frame_

//因为staticlayer中的地图数据使用的是基于mapframe的(为什么这么说呢,因为StaticLayer::incomingMap这个函数收到的地图数据时,staiclayer的mapframe被赋值成这个地图数据携带的frameid)。所以要把基于globalframe的坐标转换成基于mapframe的坐标,才能对staticlayer中的数据有意义。所以要用到transform.

//global frame, 坐标=>map frame, 坐标

tf::Point p(wx, wy, 0);

p = transform(p);

// Set master_grid with cell from map

//再把基于mapframe的double的坐标转换成int的地图坐标,也就是转换成2维数组的索引坐标。这个转换需要处理resolution得到具体的格子数目。

那么,可以认为上述worldTomap和map2world操作更重要的意义是针对地图设置的分辨率,在double和int类型之间完成互相转换。而不是像transform那样进行坐标系的变幻。

if (worldToMap(p.x(),p.y(), mx, my))

{

//下面将数据取出,更新到对应位置的layerdCostMap里面

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)));

}

}

}

}

}





总结scan数据到地图数据各个layer的流程:

1. 建图时,slam_gmapping,监听/scantopic将数据处理保存后,发送给maptopic. 使用fastslam算法建图。

2.导航时,如果不建图,没有启动gmapping的话,需要给mapserver配置地图。那么mapserver启动后,加载地图文件后,会向maptopic发送地图。

3. movebase的costmap2d模块的staticlayer会监听map和map_update topic, 得到地图,和地图更新。这个staticlayer位于globalcostmap内部。

4. movebase有建立2个costmap2dros,他们都有自己的layeredcostmap,costmap2dros有一个线程,循环调用layeredCostMap::updateMap,它把各个layer的地图数据合并,然后向costmaptopic发送出去。



【移动机器人技术】move_base参数配置方法及含义 配置文件的加载方法 在launch文件中加载yaml的配置文件,文件中有参数的赋值,参数加载后就成为ros中的参数。 <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen"> <rosparam command="delete" ns="move_base" /> <rosparam file="$(find wheel_chair)/config/c 阅读详情

相关推荐

C++实现Shp格式地图文件的显示

C++程序实训shp文件格式的读取,能进行对Shp文件的空间分析操作。

实现nav_在ROS中实现A*路径规划

在ROS中实现自己的路径规划算法需要以plugin的方式,并且继承nav_core::BaseGlobalPlanner C++ 接口。下面将逐步介绍如何实现A*算法在ROS中的路径规划。1.核心代码1.1 initialize void AstarPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_...

weixin_29159613的博客 2184

c语言写的地图导航软件

华中科技大学c语言课程设计,地图导航系统。下载就知道了! http://hi.baidu.com/wzwahl36

机器人基于ROS的move_base导航功能的部署(代价地图)

预备知识 move_base的基本框架 ROS中用于导航避障的功能包为move_base,代码链接为 https://github.com/ros-planning/navigation.git。 关于导航与避障的总体配置可以参考: http://wiki.ros.org/navigation/Tutorials/RobotSetup move_base的核心代码为 nav_core,代码链接为 https://wiki.ros.org/nav_core, 利用nav_core::BaseGlo

walleva96的博客 5026

最新打赏系统打赏源码麒麟最新打赏源码喜盈门打赏知识付费课程教程直播讲解

打赏源码打赏系统

qq_41095398的博客 2042

VIO实战前传:手把手教你解读Kalibr双目IMU标定报告与参数应用

本文详细解析Kalibr双目IMU联合标定报告的核心参数与应用方法,涵盖重投影误差分析、IMU误差指标解读、关键变换矩阵原理及VINS-Fusion实战配置。通过手把手教学帮助开发者准确理解标定结果,解决VIO算法落地中的参数配置难题,提升视觉惯性里程计的系统稳定性与精度。

weixin_42699679的博客 336

ROS Navigation源代码剖析(1)-move_base 线程框架

Navigation是机器人最基本的功能之一,ROS为我们提供了一整套Navigation的解决方案,包括全局与局部的路径规划、代价地图、异常行为恢复、地图服务器等等,这些开源工具包极大地方便了移动机器人导航功能的开发和部署。 ROS的导航功能是如何实现的?如果想基于ROS开发自己的导航功能包应该如何做呢? 本系列文章会从源代码分析的角度深入剖析ROS Navigation功能包,来加深对ROS 导航的理解和认识。基于的ROS版本是 ROS kinetic,Globa...

Robin's Home 2498

具身智能端侧硬件选型实战:从算力需求到芯片对比与避坑指南

在边缘计算和嵌入式AI快速发展的今天,端侧智能设备的落地不再单纯比拼芯片的标称算力。TOPS数值只是初筛指标,真实的推理性能还受内存带宽、数据精度、稀疏性以及散热功耗等多重因素制约。理解不同视觉感知、决策规划与语言交互任务对算力的差异化需求,是选型的第一步。本文从技术原理出发,剖析了Jetson Orin、地平线征程、RK3588等主流平台的实测表现,并揭示了散热设计、供电链路与软件生态这三个极易被忽略的隐形瓶颈。通过完整的部署调优实录,展示了量化、缓存与电源模式优化如何提升端侧推理效率,为具身智能、无人车

weixin_29164185的博客 365

costmap_2d详解5:static_layer.cpp分析

关键变量 std::string global_frame_; //global_costmap时为map, local_costmap时为odom_combined std::string map_frame_; bool subscribe_to_updates_; bool map_received_; bool has_updated_data_; /* *在...

feidaji的博客 1521

Git救援:如何从误操作中恢复未提交的更改

摘要:本文探讨了误操作git reset --hard导致未提交更改丢失后的恢复方法。首先分析git reflog的局限性,随后介绍利用IDE本地历史记录(如IntelliJ IDEA和VS Code)进行文件恢复的具体步骤。最后建议使用文件系统恢复工具(如Linux的extundelete或Windows的Recuva)作为备选方案。文章强调定期提交的重要性,同时提供了意外发生时可行的恢复策略,帮助开发者尽可能挽回丢失的工作内容。(149字)

2501_90323865的博客 131

BAT031:按列表名单将路径a下的文件夹批量剪切到路径b

摘要:按列表名单将路径a下的文件夹批量剪切到路径b。

qq_31762031的博客 1220

costmap_2d 之 static layer

static_layer作为一个地图层,具备基本的更新边界和更新代价的功能,同时肩负着。StaticLayer主要是在实现Layer层要求实现的接口。

m0_53316604的博客 552

详解AUTOSAR:AUTOSAR架构中的配置文件(拓展篇—7)

查看AUTOSAR代码包时会发现一些这样格式的文件:xxx_PBcfg.c、xxx_Lcfg.c和xxx_Cfg.h,本篇博文讲一讲这几个配置文件的作用和特点。

不脱发的程序猿 2148

movebase导航和地图数据的使用 - 9 地图数据的构成

rviz中能看到map,global map, local map.三种地图,其实map就是fastslam建立的地图,数据来自雷达。globalmap和localmap都是costmap,他们都由各自的layers合并而成。 1. rviz中的map来自gamapping发送的/maptopic 数据,或者也可以是来自mapserver发送的/maptopic 数据,具体看是在建图还是在导

1217

华为OD机试2025A卷 - 分苹果(Java & Python& JS & C++ & C )

华为OD机试2025A卷 - 分苹果(Java & Python& JS & C++ & C )

算法大师! 721

彻底摆脱文献只能读开头的痛苦!这款文献检索神器真能帮你跨越文献付费限制(附实操演示)

大家是不是有过这样的经历,好不容易通过关键词搜到了和自己主题高度相关的文献,想要快速获取文献信息,推进研究进度,却又因为付费或者需订阅才能下载PDF,而被劝退。粘贴完成后,点击搜索,搜索结果页面会显示这篇文献的相关信息,有的文献有“下载PDF”,有的文献则只有“求助PDF”,不管是哪种情况,直接点击进入;我这里点击的是“下载PDF”,接着它会跳转页面。我用 Book 学术下载过不少付费文献,实测下来 80% 左右的文献,都能通过它的求助方式成功获取到,只有少部分文献等待的时间会稍微久一些或者没办法下载。

qq_64378896的博客 167

move_base配置参数解析

move_base实际需要设置6部分参数: move_base自身参数 全局代价地图(global_costmap) 局部代价地图(local_costmap) 全局规划器(global_planner) 局部规划器(local_planner) 恢复机制(recovery_behaviors) 以上参数在move_base节点加载时全部加载,用以下参数文件格式: <launch> <node pkg="move_base" type="move_base" respawn="fa

酸梅果茶的博客 7273

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

move base全解

之前我们专门有一节讲到了《主要介绍了MoveBase基类中函数的大概意思以及调用的方式。move_base是ROS下关于机器人路径规划的中心枢纽。它通过订阅激光雷达、map地图、amcl的定位等数据,然后规划出全局和局部路径,再将路径转化为机器人的速度信息,最终实现机器人导航。下面是move_base的整个框架。

lovely_yoshino的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

ROS Navigation源代码剖析(6)-move_base 代价地图costmap_2d工作流程

4.2.4 costmap_2d工作过程 http://wiki.ros.org/costmap_2d/ 4.2.0节描述了MoveBase启动过程中创建和初始化global planner的costmap的过程。 planner_costmap_ros_ = new costmap_2d::Costmap2DROS("global_costmap", tf_); planner_costmap_ros_->pause(); //先暂定运行 costmap的动态库位于 /opt/ros/k.

Robin's Home 3690

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

costmap代价地图学习

为什么要有costmap ROS里的地图的概念,地图就是/map这个topic,它也是一张图片,一个像素代表了实际的一块面积,用灰度值来表示障碍物存在的可能性。然而在实际的导航任务中,光有一张地图是不够的,机器人需要能动态的把障碍物加入,或者清楚已经不存在的障碍物,有些时候还要在地图上标出危险区域,为路径规划提供更有用的信息。 因为导航的需要,所以出现了代价地图。你可以将代价地图理解为,在/map...

单线程的Daniel的博客 4598

costmap_2d详解7:costmap_2d.cpp分析

关键变量 unsigned int size_x_; //像素坐标系表示的坐标 unsigned int size_y_; double resolution_; double origin_x_; double origin_y_; unsigned char* costmap_; unsigned char default_value_; 关键函数: ...

feidaji的博客 2731

【ROS-Navigation】Costmap2D代价地图源码解读-静态层StaticLayer

记录学习阅读ROS Navigation源码的理解,本文为Costmap2D代价地图源码学习记录,以文字总结、绘制结构图说明、代码注释为主。仍在学习过程中,有错误欢迎指正,共同进步。 本篇记录静态地图部分的内容,主要是开启地图的订阅,以及bound和cost的更新。静态地图默认只更新一次,地图的边界也只更新一次,对于rolling地图,需要随着机器人的运动位置不断更新附近的cost,而对于非r...

NEO's NOTEBOOK 3279

带你理清:ROS机器人导航功能实现、解析、以及参数说明

在ROS中,进行导航需要使用到的三个包是: (1) move_base:根据参照的消息进行路径规划,使移动机器人到达指定的位置; (2) gmapping:根据激光数据(或者深度数据模拟的激光数据)建立地图; (3) amcl:根据已经有的地图进行定位。 move_base,它接收了地图数据等,通过代价地图等进行路径规划 AMCL,通过已有的数据进行定位 ...

旺仔馒头 2万+

ROS Navigation-----costmap_2d之staticmap层简介

costmap_2d之staticmap层简介

倔强不倒翁的博客 2660

move_base参数配置

move_base使用前需要配置一些参数:运行成本、机器人半径、到达目标位置的距离,机器人移动的速度等,这些参数由以下几个配置文件中: base_local_planner_params.yaml costmap_common_params.yaml global_costmap_params.yaml local_costmap_params.yaml ...

qq_34911636的博客 9404

costmap解析及笔记 优快云

costmap_2d包提供了一种可配置框架来维护机器人在代价地图上应该如何导航的信息。代价地图使用来自传感器的数据和来自静态地图中的信息,通过costmap_2d::Costmap2DROS 来存储和更新现实世界中的障碍物信息。costmap_2d::Costmap2DROS给用户提供了纯2D的接口,这意味着障碍只能在列上进行。例如,在XY平面上位于同一位置的桌子和鞋,虽然在Z方向上有差异但是他们在costmap_2d::Costmap2DROS对象代价地图中对应的cell上拥有相同的代价值。这种设计对平面

qq_43355922的博客 2028
上一篇: movebase导航和地图数据的使用 - 9 地图数据的构成
下一篇: movebase导航和地图数据的使用 - 11 voxel layer数据的生成和使用
csshell2002
博客等级 码龄11年 30粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值