GridMap2D.cpp
Go to the documentation of this file.
00001 /*
00002  * A simple 2D gridmap structure
00003  *
00004  * Copyright 2011 Armin Hornung, University of Freiburg
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the University of Freiburg nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include "gridmap_2d/GridMap2D.h"
00032 #include <ros/console.h>
00033 
00034 namespace gridmap_2d{
00035 
00036 GridMap2D::GridMap2D()
00037 : m_frameId("/map")
00038 {
00039 
00040 }
00041 
00042 GridMap2D::GridMap2D(const nav_msgs::OccupancyGridConstPtr& gridMap, bool unknown_as_obstacle) {
00043 
00044   setMap(gridMap, unknown_as_obstacle);
00045 
00046 }
00047 
00048 GridMap2D::GridMap2D(const GridMap2D& other)
00049  : m_binaryMap(other.m_binaryMap.clone()),
00050    m_distMap(other.m_distMap.clone()),
00051    m_mapInfo(other.m_mapInfo),
00052    m_frameId(other.m_frameId)
00053 {
00054 
00055 }
00056 
00057 GridMap2D::~GridMap2D() {
00058 
00059 }
00060 
00061 void GridMap2D::updateDistanceMap(){
00062   cv::distanceTransform(m_binaryMap, m_distMap, CV_DIST_L2, CV_DIST_MASK_PRECISE);
00063   // distance map now contains distance in meters:
00064   m_distMap = m_distMap * m_mapInfo.resolution;
00065 }
00066 
00067 void GridMap2D::setMap(const nav_msgs::OccupancyGridConstPtr& grid_map, bool unknown_as_obstacle){
00068   m_mapInfo = grid_map->info;
00069   m_frameId = grid_map->header.frame_id;
00070   // allocate map structs so that x/y in the world correspond to x/y in the image
00071   // (=> cv::Mat is rotated by 90 deg, because it's row-major!)
00072   m_binaryMap = cv::Mat(m_mapInfo.width, m_mapInfo.height, CV_8UC1);
00073   m_distMap = cv::Mat(m_binaryMap.size(), CV_32FC1);
00074 
00075   std::vector<signed char>::const_iterator mapDataIter = grid_map->data.begin();
00076 
00077   //TODO check / param
00078   unsigned char map_occ_thres = 70;
00079 
00080   // iterate over map, store in image
00081   // (0,0) is lower left corner of OccupancyGrid
00082   for(unsigned int j = 0; j < m_mapInfo.height; ++j){
00083     for(unsigned int i = 0; i < m_mapInfo.width; ++i){
00084       if (*mapDataIter > map_occ_thres
00085           || (unknown_as_obstacle && *mapDataIter < 0))
00086       {
00087         m_binaryMap.at<uchar>(i,j) = OCCUPIED;
00088       } else{
00089         m_binaryMap.at<uchar>(i,j) = FREE;
00090       }
00091       ++mapDataIter;
00092     }
00093   }
00094 
00095   updateDistanceMap();
00096 
00097   ROS_INFO("GridMap2D created with %d x %d cells at %f resolution.", m_mapInfo.width, m_mapInfo.height, m_mapInfo.resolution);
00098 }
00099 
00100 nav_msgs::OccupancyGrid GridMap2D::toOccupancyGridMsg() const{
00101   nav_msgs::OccupancyGrid msg;
00102   msg.header.frame_id = m_frameId;
00103   msg.header.stamp = ros::Time::now();
00104   msg.info = m_mapInfo;
00105   msg.data.resize(msg.info.height*msg.info.width);
00106 
00107   // iterate over map, store in data
00108   std::vector<signed char>::iterator mapDataIter = msg.data.begin();
00109   // (0,0) is lower left corner of OccupancyGrid
00110   for(unsigned int j = 0; j < m_mapInfo.height; ++j){
00111     for(unsigned int i = 0; i < m_mapInfo.width; ++i){
00112       if (m_binaryMap.at<uchar>(i,j) == OCCUPIED)
00113         *mapDataIter = 100;
00114       else
00115         *mapDataIter = 0;
00116 
00117       ++mapDataIter;
00118     }
00119   }
00120 
00121   return msg;
00122 }
00123 
00124 void GridMap2D::setMap(const cv::Mat& binaryMap){
00125   m_binaryMap = binaryMap.clone();
00126   m_distMap = cv::Mat(m_binaryMap.size(), CV_32FC1);
00127 
00128   cv::distanceTransform(m_binaryMap, m_distMap, CV_DIST_L2, CV_DIST_MASK_PRECISE);
00129   // distance map now contains distance in meters:
00130   m_distMap = m_distMap * m_mapInfo.resolution;
00131 
00132   ROS_INFO("GridMap2D copied from existing cv::Mat with %d x %d cells at %f resolution.", m_mapInfo.width, m_mapInfo.height, m_mapInfo.resolution);
00133 
00134 }
00135 
00136 void GridMap2D::inflateMap(double inflationRadius){
00137   m_binaryMap = (m_distMap > inflationRadius );
00138   // recompute distance map with new binary map:
00139   cv::distanceTransform(m_binaryMap, m_distMap, CV_DIST_L2, CV_DIST_MASK_PRECISE);
00140   m_distMap = m_distMap * m_mapInfo.resolution;
00141 }
00142 
00143 // See costmap2D for mapToWorld / worldToMap implementations:
00144 
00145 void GridMap2D::mapToWorld(unsigned int mx, unsigned int my, double& wx, double& wy) const {
00146   wx = m_mapInfo.origin.position.x + (mx+0.5) * m_mapInfo.resolution;
00147   wy = m_mapInfo.origin.position.y + (my+0.5) * m_mapInfo.resolution;
00148 }
00149 
00150 
00151 
00152 void GridMap2D::worldToMapNoBounds(double wx, double wy, unsigned int& mx, unsigned int& my) const {
00153   mx = (int) ((wx - m_mapInfo.origin.position.x) / m_mapInfo.resolution);
00154   my = (int) ((wy - m_mapInfo.origin.position.y) / m_mapInfo.resolution);
00155 }
00156 
00157 bool GridMap2D::worldToMap(double wx, double wy, unsigned int& mx, unsigned int& my) const {
00158   if(wx < m_mapInfo.origin.position.x || wy < m_mapInfo.origin.position.y)
00159     return false;
00160 
00161   mx = (int) ((wx - m_mapInfo.origin.position.x) / m_mapInfo.resolution);
00162   my = (int) ((wy - m_mapInfo.origin.position.y) / m_mapInfo.resolution);
00163 
00164   if(mx < m_mapInfo.width && my < m_mapInfo.height)
00165     return true;
00166 
00167   return false;
00168 }
00169 
00170 bool GridMap2D::inMapBounds(double wx, double wy) const{
00171   unsigned mx, my;
00172   return worldToMap(wx,wy,mx,my);
00173 }
00174 
00175 float GridMap2D::distanceMapAt(double wx, double wy) const{
00176   unsigned mx, my;
00177 
00178   if (worldToMap(wx, wy, mx, my))
00179     return m_distMap.at<float>(mx, my);
00180   else
00181     return -1.0f;
00182 }
00183 
00184 
00185 uchar GridMap2D::binaryMapAt(double wx, double wy) const{
00186   unsigned mx, my;
00187 
00188   if (worldToMap(wx, wy, mx, my))
00189     return m_binaryMap.at<uchar>(mx, my);
00190   else
00191     return 0;
00192 }
00193 
00194 float GridMap2D::distanceMapAtCell(unsigned int mx, unsigned int my) const{
00195   return m_distMap.at<float>(mx, my);
00196 }
00197 
00198 
00199 uchar GridMap2D::binaryMapAtCell(unsigned int mx, unsigned int my) const{
00200   return m_binaryMap.at<uchar>(mx, my);
00201 }
00202 
00203 uchar& GridMap2D::binaryMapAtCell(unsigned int mx, unsigned int my){
00204   return m_binaryMap.at<uchar>(mx, my);
00205 }
00206 
00207 
00208 bool GridMap2D::isOccupiedAtCell(unsigned int mx, unsigned int my) const{
00209   return (m_binaryMap.at<uchar>(mx, my) < 255);
00210 }
00211 
00212 
00213 bool GridMap2D::isOccupiedAt(double wx, double wy) const{
00214   unsigned mx, my;
00215   if (worldToMap(wx, wy, mx, my))
00216     return isOccupiedAtCell(mx, my);
00217   else
00218     return true;
00219 }
00220 
00221 }
00222 
00223 


gridmap_2d
Author(s): Armin Hornung
autogenerated on Sat Jun 8 2019 20:21:01