00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
00071
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
00078 unsigned char map_occ_thres = 70;
00079
00080
00081
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
00108 std::vector<signed char>::iterator mapDataIter = msg.data.begin();
00109
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
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
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
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