MapExtractor.cpp
Go to the documentation of this file.
00001 
00053 #include <octomap/octomap.h>
00054 #include <octomap/OcTree.h>
00055 #include <iomanip>
00056 #include "MapExtractor.h"
00057 
00058 using namespace std;
00059 using namespace roboearth;
00060 
00061 MapExtractor::MapExtractor(const std::string& filename) :
00062         m_gridmap(NULL), m_octoMap(NULL), m_res(0.025), m_treeDepth(0) {
00063 
00064         cout << "Loading 3d octomap '" << filename.c_str() << "':" << endl << "  ";
00065         cout << setprecision(3);
00066 
00067         m_octoMap = new octomap::OcTree(m_res);
00068         if (m_octoMap->readBinary(filename)) {
00069 
00070                 m_treeDepth = m_octoMap->getTreeDepth();
00071                 m_res = m_octoMap->getResolution();
00072                 m_gridmap = new OccupancyGrid;
00073                 m_gridmap->resolution = m_res;
00074 
00075         } else {
00076                 cout << endl;
00077                 exit(-1);
00078         }
00079 
00080 }
00081 
00082 MapExtractor::~MapExtractor() {
00083 
00084         delete m_octoMap;
00085         delete m_gridmap;
00086 
00087 }
00088 
00089 bool MapExtractor::isSpeckleNode(const octomap::OcTreeKey& nKey) const {
00090         octomap::OcTreeKey key;
00091         bool neighborFound = false;
00092         for (key[2] = nKey[2] - 1; !neighborFound && key[2] <= nKey[2] + 1; ++key[2]) {
00093                 for (key[1] = nKey[1] - 1; !neighborFound && key[1] <= nKey[1] + 1; ++key[1]) {
00094                         for (key[0] = nKey[0] - 1; !neighborFound && key[0] <= nKey[0] + 1; ++key[0]) {
00095                                 if (key != nKey) {
00096                                         octomap::OcTreeNode* node = m_octoMap->search(key);
00097                                         if (node && m_octoMap->isNodeOccupied(node)) {
00098                                                 neighborFound = true;
00099                                         }
00100                                 }
00101                         }
00102                 }
00103         }
00104 
00105         return !neighborFound;
00106 }
00107 
00108 bool MapExtractor::calc2dSlice(double occupancyMinZ, double occupancyMaxZ,
00109                 bool filterSpeckles, double minSizeX, double minSizeY) {
00110 
00111         // This tree implementation currently has a maximum depth of 16
00112         // nodes. For this reason, coordinates values have to be, e.g.,
00113         // below +/- 327.68 meters (2^15) at a maximum resolution of 0.01m.
00114 
00115         double minX, minY, minZ, maxX, maxY, maxZ;
00116         m_octoMap->getMetricMin(minX, minY, minZ);
00117         m_octoMap->getMetricMax(maxX, maxY, maxZ);
00118 
00119         cout << "  min - x: " << minX << " y: " << minY << " z: " << minZ << endl;
00120         cout << "  max - x: " << maxX << " y: " << maxY << " z: " << maxZ << endl;
00121 
00122         octomap::point3d minPt(minX, minY, minZ);
00123         octomap::point3d maxPt(maxX, maxY, maxZ);
00124         octomap::OcTreeKey minKey, maxKey, curKey;
00125 
00126         if (!m_octoMap->genKey(minPt, minKey)) {
00127                 cout << "  Creating min octree key (x: " << minPt.x() << ", y: "
00128                                 << minPt.y() << ", z: " << minPt.z() << ") failed." << endl;
00129                 return false;
00130         }
00131         if (!m_octoMap->genKey(maxPt, maxKey)) {
00132                 cout << "  Creating max octree key (x: " << maxPt.x() << ", y: "
00133                                 << maxPt.y() << ", z: " << maxPt.z() << ") failed." << endl;
00134                 return false;
00135         }
00136 
00137         cout << "  min key - x: " << minKey[0] << " y: " << minKey[1] << " z: "
00138                         << minKey[2] << endl;
00139         cout << "  max key - x: " << maxKey[0] << " y: " << maxKey[1] << " z: "
00140                         << maxKey[2] << endl;
00141 
00142         // pad to min size
00143         double halfPaddedX = 0.5 * minSizeX;
00144         double halfPaddedY = 0.5 * minSizeY;
00145         minX = std::min(minX, -halfPaddedX);
00146         maxX = std::max(maxX, halfPaddedX);
00147         minY = std::min(minY, -halfPaddedY);
00148         maxY = std::max(maxY, halfPaddedY);
00149         minPt = octomap::point3d(minX, minY, minZ);
00150         maxPt = octomap::point3d(maxX, maxY, maxZ);
00151         octomap::OcTreeKey paddedMinKey, paddedMaxKey;
00152 
00153         if (!m_octoMap->genKey(minPt, paddedMinKey)) {
00154                 cout << "  Creating padded min octree key (x: " << minPt.x() << ", y: "
00155                                 << minPt.y() << ", z: " << minPt.z() << ") failed." << endl;
00156                 return false;
00157         }
00158         if (!m_octoMap->genKey(maxPt, paddedMaxKey)) {
00159                 cout << "  Creating padded max octree key (x: " << maxPt.x() << ", y: "
00160                                 << maxPt.y() << ", z: " << maxPt.z() << ") failed." << endl;
00161                 return false;
00162         }
00163 
00164         if (paddedMinKey[0] != minKey[0] || paddedMinKey[1] != minKey[1]) {
00165                 cout << "  padded min key - x: " << paddedMinKey[0] << " y: "
00166                                 << paddedMinKey[1] << " z: " << paddedMinKey[2] << endl;
00167                 cout << "  padded max key - x: " << paddedMaxKey[0] << " y: "
00168                                 << paddedMaxKey[1] << " z: " << paddedMaxKey[2] << endl;
00169 
00170                 assert(paddedMaxKey[0] >= maxKey[0] && paddedMaxKey[1] >= maxKey[1]);
00171         }
00172 
00173         m_gridmap->width = paddedMaxKey[0] - paddedMinKey[0] + 1;
00174         m_gridmap->height = paddedMaxKey[1] - paddedMinKey[1] + 1;
00175         int mapOriginX = minKey[0] - paddedMinKey[0];
00176         int mapOriginY = minKey[1] - paddedMinKey[1];
00177 
00178         octomap::point3d origin;
00179         m_octoMap->genCoords(paddedMinKey, m_treeDepth, origin);
00180         m_gridmap->orientation.x = origin.x() - m_res * 0.5;
00181         m_gridmap->orientation.y = origin.y() - m_res * 0.5;
00182         m_gridmap->orientation.yaw = 0; //TODO calc yaw for grid map
00183 
00184         // allocate space for grid map, init with -1 (occupancy unknown)
00185         m_gridmap->data.resize(m_gridmap->width * m_gridmap->height, -1);
00186 
00187         // run through all leafs of the tree
00188         for (octomap::OcTree::leaf_iterator it = m_octoMap->begin(), end =
00189                         m_octoMap->end(); it != end; ++it) {
00190 
00191                 if (m_octoMap->isNodeOccupied(*it)) { // node is occupied
00192 
00193                         double z = it.getZ();
00194                         if (z > occupancyMinZ && z < occupancyMaxZ) {
00195 
00196                                 double size = it.getSize();
00197                                 double x = it.getX();
00198                                 double y = it.getY();
00199                                 octomap::OcTreeKey nKey = it.getKey();
00200 
00201                                 // optionally ignore single occupied nodes without direct neighbors
00202                                 if (filterSpeckles && (it.getDepth() == m_treeDepth + 1)
00203                                                 && isSpeckleNode(nKey)) {
00204                                         cout << "Ignoring single occupied node - x: " << x
00205                                                         << " y: " << y << " z: " << z << endl;
00206                                         continue;
00207                                 }
00208 
00209                                 if (it.getDepth() == m_treeDepth) {
00210                                         octomap::OcTreeKey nKey = it.getKey();
00211                                         int i = nKey[0] - paddedMinKey[0];
00212                                         int j = nKey[1] - paddedMinKey[1];
00213                                         m_gridmap->data[m_gridmap->width * j + i] = 100; //occupied
00214                                 } else {
00215                                         int intSize = 1 << (m_treeDepth - it.getDepth());
00216                                         octomap::OcTreeKey minKey = it.getIndexKey();
00217                                         for (int dx = 0; dx < intSize; dx++) {
00218                                                 int i = minKey[0] + dx - paddedMinKey[0];
00219                                                 for (int dy = 0; dy < intSize; dy++) {
00220                                                         int j = minKey[1] + dy - paddedMinKey[1];
00221                                                         m_gridmap->data[m_gridmap->width * j + i] = 100;
00222                                                 }
00223                                         }
00224                                 }
00225 
00226                         }
00227 
00228                 } else { // node is free
00229 
00230                         if (it.getDepth() == m_treeDepth) {
00231 
00232                                 octomap::OcTreeKey nKey = it.getKey();
00233                                 int i = nKey[0] - paddedMinKey[0];
00234                                 int j = nKey[1] - paddedMinKey[1];
00235                                 if (m_gridmap->data[m_gridmap->width * j + i] == -1) {
00236                                         m_gridmap->data[m_gridmap->width * j + i] = 0; // free
00237                                 }
00238 
00239                         } else {
00240 
00241                                 int intSize = 1 << (m_treeDepth - it.getDepth());
00242                                 octomap::OcTreeKey minKey = it.getIndexKey();
00243                                 for (int dx = 0; dx < intSize; dx++) {
00244                                         int i = minKey[0] + dx - paddedMinKey[0];
00245                                         for (int dy = 0; dy < intSize; dy++) {
00246                                                 int j = minKey[1] + dy - paddedMinKey[1];
00247                                                 if (m_gridmap->data[m_gridmap->width * j + i] == -1) {
00248                                                         m_gridmap->data[m_gridmap->width * j + i] = 0;
00249                                                 }
00250                                         }
00251                                 }
00252 
00253                         }
00254 
00255                 }
00256 
00257         }
00258 
00259         return true;
00260 
00261 }
00262 
00263 bool MapExtractor::save2dMap(const std::string& mapName, double z,
00264                 bool filterSpeckles, double minSizeX, double minSizeY) {
00265 
00266         return save2dMap(mapName, z - m_res, z + m_res, filterSpeckles, minSizeX,
00267                         minSizeY);
00268 
00269 }
00270 
00271 bool MapExtractor::save2dMap(const std::string& mapName, double minZ,
00272                 double maxZ, bool filterSpeckles, double minSizeX, double minSizeY) {
00273 
00274         if (!calc2dSlice(minZ, maxZ, filterSpeckles, minSizeX, minSizeY)) {
00275                 return false;
00276         }
00277 
00278         cout << "  size: " << m_gridmap->width << " x " << m_gridmap->height
00279                         << ", resolution: " << m_gridmap->resolution << " m/pixel" << endl;
00280 
00281         string mapFilename = mapName + ".pgm";
00282         FILE* outMap = fopen(mapFilename.c_str(), "w");
00283         if (!outMap) {
00284                 cout << "couldn't save map to '" << mapFilename.c_str() << "'" << endl;
00285                 return false;
00286         }
00287 
00288         fprintf(outMap, "P5\n# CREATOR: MapExtractor.cpp %.3f m/pix\n%d %d\n255\n",
00289                         m_gridmap->resolution, m_gridmap->width, m_gridmap->height);
00290 
00291         for (unsigned int y = 0; y < m_gridmap->height; y++) {
00292                 for (unsigned int x = 0; x < m_gridmap->width; x++) {
00293                         unsigned int i = x + (m_gridmap->height - y - 1) * m_gridmap->width;
00294                         if (m_gridmap->data[i] == 0) {
00295                                 fputc(254, outMap);
00296                         } else if (m_gridmap->data[i] == +100) {
00297                                 fputc(000, outMap);
00298                         } else {
00299                                 fputc(205, outMap);
00300                         }
00301                 }
00302         }
00303 
00304         fclose(outMap);
00305 
00306         string metaFilename = mapName + ".yaml";
00307         FILE* outMeta = fopen(metaFilename.c_str(), "w");
00308         if (!outMeta) {
00309                 cout << "couldn't save meta data to '" << metaFilename.c_str() << "'"
00310                                 << endl;
00311                 return false;
00312         }
00313 
00314         std::string::size_type filename_begin = mapFilename.find_last_of('/');
00315         if (filename_begin == std::string::npos) {
00316                 filename_begin = 0;
00317         } else {
00318                 filename_begin++;
00319         }
00320         std::string::size_type filename_length = mapFilename.length() - filename_begin;
00321         mapFilename = mapFilename.substr(filename_begin, filename_length);
00322 
00323         fprintf(
00324                         outMeta,
00325                         "image: %s\nresolution: %f\norigin: [%f, %f, %f]\nnegate: 0\noccupied_thresh: 0.65\nfree_thresh: 0.196\n\n",
00326                         mapFilename.c_str(), m_gridmap->resolution,
00327                         m_gridmap->orientation.x, m_gridmap->orientation.y,
00328                         m_gridmap->orientation.yaw);
00329 
00330         fclose(outMeta);
00331 
00332         return true;
00333 
00334 }


re_2dmap_extractor
Author(s): Alexander Perzylo
autogenerated on Sun Jan 5 2014 11:28:08