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 层,这个略微要难点。
ROS naviagtion analysis: costmap_2d--StaticLayer的更多相关文章
- ROS naviagtion analysis: costmap_2d--Costmap2DROS
博客转载自:https://blog.csdn.net/u013158492/article/details/50485418 在上一篇文章中moveBase就有关于costmap_2d的使用: pl ...
- ROS naviagtion analysis: move_base
博客转载自:https://blog.csdn.net/u013158492/article/details/50483123 这是navigation的第一篇文章,主要通过分析ROS代码级实现,了解 ...
- ROS naviagtion analysis: costmap_2d--LayeredCostmap
博客转自:https://blog.csdn.net/u013158492/article/details/50490490 在数据成员中,有两个重要的变量:Costmap2D costmap_和 s ...
- ROS naviagtion analysis: costmap_2d--ObstacleLayer
博客转载自:https://blog.csdn.net/u013158492/article/details/50493676 构造函数 ObstacleLayer() { costmap_ = NU ...
- ROS naviagtion analysis: costmap_2d--CostmapLayer
博客转自:https://blog.csdn.net/u013158492/article/details/50493220 这个类是为ObstacleLayer StaticLayer voxelL ...
- ROS naviagtion analysis: costmap_2d--Layer
博客转载自:https://blog.csdn.net/u013158492/article/details/50493113 这个类中有一个LayeredCostmap* layered_costm ...
- ROS naviagtion analysis: costmap_2d--Costmap2D
博客转载自:https://blog.csdn.net/u013158492/article/details/50492506 Costmap2D是存储地图数据的父类.真正的地图数据就存储在数据成员u ...
- ROS 教程之 navigation :在 catkin 环境下创建costmap layer plugin
在做机器人导航的时候,肯定见到过global_costmap和local_costmap.global_costmap是为了全局路径规划服务的,如从这个房间到那个房间该怎么走.local_costma ...
- ROS探索总结(十三)——导航与定位框架
导航与定位是机器人研究中的重要部分. 一般机器人在陌生的环境下需要使用激光传感器(或者深度传感器转换成激光数据),先进行地图建模,然后在根据建立的地图进行导航.定位.在ROS中也有很多 ...
随机推荐
- 关于public static void main(String[] args)相关知识
main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同.比如方法的名字必须是main,方法必须是public ...
- EMMC架构
现在EMMC盛行,分析总结还是很有必要的.以下以全志a64为实例切入主题. 这里a64有三个sdc0~2,硬件上sdc2是连接EMMC,这里只分析sdc2的代码. 初始化的代码在linux-3.10/ ...
- (转)android - anim translate中 fromXDelta、toXDelta、fromYDelta、toXDelta属性
2012-03-23 15:51 16144人阅读 评论(5) 收藏 举报 android <set xmlns:android="http://schemas.android.com ...
- SpringMvc入门四----rest风格Url
知识点: REST风格URL简介 SpringMvc对rest风格的支持 @PathVariable 获取 Url 变量 SpringMvc对静态资源的处理 REST风格URL简介: 我们平时看到的s ...
- 数据科学:numpy.where() 的用法
原文出处:numpy.where() 用法讲解 原创作者:massquantity numpy.where() 有两种用法: 1. np.where(condition, x, y) 满足条件(con ...
- mysql实战优化之六:Order by优化 sql优化、索引优化
在MySQL中的ORDER BY有两种排序实现方式: 1.利用有序索引获取有序数据 2.文件排序 在使用explain分析查询的时候,利用有序索引获取有序数据显示Using index.而文件排序显示 ...
- 过河卒(Noip2002)(dp)
过河卒(Noip2002) 时间限制: 1 Sec 内存限制: 128 MB提交: 7 解决: 6[提交][状态][讨论版][命题人:quanxing] 题目描述 棋盘上A点有一个过河卒,需要走到 ...
- 迭代器-迭代对象-dir(a)可以查看该数据类型有多少种方法。range(10)在py3里就是一个迭代器,for循环实际就是迭代器的应用
迭代器 我们已经知道,可以直接作用于for循环的数据烈性有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str,bytes等: 一类是generator,数据结构,包括生成 ...
- win10下默认使用福昕打开PDF
win10为了推他的edge浏览器, 将默认的pdf打开设置为了edge浏览器, 非常令人反感, 做浏览器就好好做浏览器, 为什么要默认打开pdf? 而且修改默认为福昕后, 下次打开pdf文件, 他又 ...
- Android Binder机制中的异步回调
“Binder通信是同步而不是异步的”,但是在实际使用时,是设计成客户端同步而服务端异步. 看看Framwork层的各service类java源码便会知道,在客户端调用服务端的各种方法时,通常会传递一 ...