dynamicEDTOctomap.cpp
Go to the documentation of this file.
00001 
00009 /*
00010  * Copyright (c) 2011-2012, C. Sprunk, B. Lau, W. Burgard, University of Freiburg
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *
00016  *     * Redistributions of source code must retain the above copyright
00017  *       notice, this list of conditions and the following disclaimer.
00018  *     * Redistributions in binary form must reproduce the above copyright
00019  *       notice, this list of conditions and the following disclaimer in the
00020  *       documentation and/or other materials provided with the distribution.
00021  *     * Neither the name of the University of Freiburg nor the names of its
00022  *       contributors may be used to endorse or promote products derived from
00023  *       this software without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  * POSSIBILITY OF SUCH DAMAGE.
00036  */
00037 
00038 #include <dynamicEDT3D/dynamicEDTOctomap.h>
00039 
00040 float DynamicEDTOctomap::distanceValue_Error = -1.0;
00041 int DynamicEDTOctomap::distanceInCellsValue_Error = -1;
00042 
00043 DynamicEDTOctomap::DynamicEDTOctomap(float maxdist, octomap::OcTree* _octree, octomap::point3d bbxMin, octomap::point3d bbxMax, bool treatUnknownAsOccupied)
00044 : DynamicEDT3D(((int) (maxdist/_octree->getResolution()+1)*((int) (maxdist/_octree->getResolution()+1)))), octree(_octree), unknownOccupied(treatUnknownAsOccupied)
00045 {
00046         treeDepth = octree->getTreeDepth();
00047         treeResolution = octree->getResolution();
00048         initializeOcTree(bbxMin, bbxMax);
00049         octree->enableChangeDetection(true);
00050 }
00051 
00052 DynamicEDTOctomap::~DynamicEDTOctomap() {
00053 
00054 }
00055 
00056 
00057 void DynamicEDTOctomap::update(bool updateRealDist){
00058 
00059         for(octomap::KeyBoolMap::const_iterator it = octree->changedKeysBegin(), end=octree->changedKeysEnd(); it!=end; ++it){
00060                 //the keys in this list all go down to the lowest level!
00061 
00062                 octomap::OcTreeKey key = it->first;
00063 
00064                 //ignore changes outside of bounding box
00065                 if(key[0] < boundingBoxMinKey[0] || key[1] < boundingBoxMinKey[1] || key[2] < boundingBoxMinKey[2])
00066                         continue;
00067                 if(key[0] > boundingBoxMaxKey[0] || key[1] > boundingBoxMaxKey[1] || key[2] > boundingBoxMaxKey[2])
00068                         continue;
00069 
00070                 octomap::OcTreeNode* node = octree->search(key);
00071                 assert(node);
00072                 //"node" is not necessarily at lowest level, BUT: the occupancy value of this node
00073                 //has to be the same as of the node indexed by the key *it
00074 
00075                 updateMaxDepthLeaf(key, octree->isNodeOccupied(node));
00076         }
00077         octree->resetChangeDetection();
00078 
00079         DynamicEDT3D::update(updateRealDist);
00080 }
00081 
00082 void DynamicEDTOctomap::initializeOcTree(octomap::point3d bbxMin, octomap::point3d bbxMax){
00083 
00084     boundingBoxMinKey = octree->coordToKey(bbxMin);
00085     boundingBoxMaxKey = octree->coordToKey(bbxMax);
00086 
00087         offsetX = -boundingBoxMinKey[0];
00088         offsetY = -boundingBoxMinKey[1];
00089         offsetZ = -boundingBoxMinKey[2];
00090 
00091         int _sizeX = boundingBoxMaxKey[0] - boundingBoxMinKey[0] + 1;
00092         int _sizeY = boundingBoxMaxKey[1] - boundingBoxMinKey[1] + 1;
00093         int _sizeZ = boundingBoxMaxKey[2] - boundingBoxMinKey[2] + 1;
00094 
00095         initializeEmpty(_sizeX, _sizeY, _sizeZ, false);
00096 
00097 
00098         if(unknownOccupied == false){
00099                 for(octomap::OcTree::leaf_bbx_iterator it = octree->begin_leafs_bbx(bbxMin,bbxMax), end=octree->end_leafs_bbx(); it!= end; ++it){
00100                         if(octree->isNodeOccupied(*it)){
00101                                 int nodeDepth = it.getDepth();
00102                                 if( nodeDepth == treeDepth){
00103                                         insertMaxDepthLeafAtInitialize(it.getKey());
00104                                 } else {
00105                                         int cubeSize = 1 << (treeDepth - nodeDepth);
00106                                         octomap::OcTreeKey key=it.getIndexKey();
00107                                         for(int dx = 0; dx < cubeSize; dx++)
00108                                                 for(int dy = 0; dy < cubeSize; dy++)
00109                                                         for(int dz = 0; dz < cubeSize; dz++){
00110                                                                 unsigned short int tmpx = key[0]+dx;
00111                                                                 unsigned short int tmpy = key[1]+dy;
00112                                                                 unsigned short int tmpz = key[2]+dz;
00113 
00114                                                                 if(boundingBoxMinKey[0] > tmpx || boundingBoxMinKey[1] > tmpy || boundingBoxMinKey[2] > tmpz)
00115                                                                         continue;
00116                                                                 if(boundingBoxMaxKey[0] < tmpx || boundingBoxMaxKey[1] < tmpy || boundingBoxMaxKey[2] < tmpz)
00117                                                                         continue;
00118 
00119                                                                 insertMaxDepthLeafAtInitialize(octomap::OcTreeKey(tmpx, tmpy, tmpz));
00120                                                         }
00121                                 }
00122                         }
00123                 }
00124         } else {
00125                 octomap::OcTreeKey key;
00126                 for(int dx=0; dx<sizeX; dx++){
00127                         key[0] = boundingBoxMinKey[0] + dx;
00128                         for(int dy=0; dy<sizeY; dy++){
00129                                 key[1] = boundingBoxMinKey[1] + dy;
00130                                 for(int dz=0; dz<sizeZ; dz++){
00131                                         key[2] = boundingBoxMinKey[2] + dz;
00132 
00133                                         octomap::OcTreeNode* node = octree->search(key);
00134                                         if(!node || octree->isNodeOccupied(node)){
00135                                                 insertMaxDepthLeafAtInitialize(key);
00136                                         }
00137                                 }
00138                         }
00139                 }
00140         }
00141 }
00142 
00143 void DynamicEDTOctomap::insertMaxDepthLeafAtInitialize(octomap::OcTreeKey key){
00144         bool isSurrounded = true;
00145 
00146 
00147         for(int dx=-1; dx<=1; dx++)
00148                 for(int dy=-1; dy<=1; dy++)
00149                         for(int dz=-1; dz<=1; dz++){
00150                                 if(dx==0 && dy==0 && dz==0)
00151                                         continue;
00152                                 octomap::OcTreeNode* node = octree->search(octomap::OcTreeKey(key[0]+dx, key[1]+dy, key[2]+dz));
00153                                 if((!unknownOccupied && node==NULL) || ((node!=NULL) && (octree->isNodeOccupied(node)==false))){
00154                                         isSurrounded = false;
00155                                         break;
00156                                 }
00157                         }
00158 
00159         if(isSurrounded){
00160                 //obstacles that are surrounded by obstacles do not need to be put in the queues,
00161                 //hence this initialization
00162                 dataCell c;
00163                 int x = key[0]+offsetX;
00164                 int y = key[1]+offsetY;
00165                 int z = key[2]+offsetZ;
00166                 c.obstX = x;
00167                 c.obstY = y;
00168                 c.obstZ = z;
00169                 c.sqdist = 0;
00170                 c.dist = 0.0;
00171                 c.queueing = fwProcessed;
00172                 c.needsRaise = false;
00173                 data[x][y][z] = c;
00174         } else {
00175                 setObstacle(key[0]+offsetX, key[1]+offsetY, key[2]+offsetZ);
00176         }
00177 }
00178 
00179 void DynamicEDTOctomap::updateMaxDepthLeaf(octomap::OcTreeKey& key, bool occupied){
00180         if(occupied)
00181                 setObstacle(key[0]+offsetX, key[1]+offsetY, key[2]+offsetZ);
00182         else
00183                 removeObstacle(key[0]+offsetX, key[1]+offsetY, key[2]+offsetZ);
00184 }
00185 
00186 void DynamicEDTOctomap::worldToMap(const octomap::point3d &p, int &x, int &y, int &z) const {
00187         octomap::OcTreeKey key = octree->coordToKey(p);
00188         x = key[0] + offsetX;
00189         y = key[1] + offsetY;
00190         z = key[2] + offsetZ;
00191 }
00192 
00193 void DynamicEDTOctomap::mapToWorld(int x, int y, int z, octomap::point3d &p) const {
00194         p = octree->keyToCoord(octomap::OcTreeKey(x-offsetX, y-offsetY, z-offsetZ));
00195 }
00196 
00197 void DynamicEDTOctomap::mapToWorld(int x, int y, int z, octomap::OcTreeKey &key) const {
00198         key = octomap::OcTreeKey(x-offsetX, y-offsetY, z-offsetZ);
00199 }
00200 
00201 
00202 void DynamicEDTOctomap::getDistanceAndClosestObstacle(const octomap::point3d& p, float &distance, octomap::point3d& closestObstacle) const {
00203         int x,y,z;
00204         worldToMap(p, x, y, z);
00205         if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
00206                 dataCell c= data[x][y][z];
00207 
00208                 distance = c.dist*treeResolution;
00209                 if(c.obstX != invalidObstData){
00210                         mapToWorld(c.obstX, c.obstY, c.obstZ, closestObstacle);
00211                 } else {
00212                   //If we are at maxDist, it can very well be that there is no valid closest obstacle data for this cell, this is not an error.
00213                 }
00214         } else {
00215           distance = distanceValue_Error;
00216         }
00217 }
00218 
00219 
00220 void DynamicEDTOctomap::getDistanceAndClosestObstacle_unsafe(const octomap::point3d& p, float &distance, octomap::point3d& closestObstacle) const {
00221         int x,y,z;
00222         worldToMap(p, x, y, z);
00223 
00224         dataCell c= data[x][y][z];
00225 
00226         distance = c.dist*treeResolution;
00227         if(c.obstX != invalidObstData){
00228                 mapToWorld(c.obstX, c.obstY, c.obstZ, closestObstacle);
00229         } else {
00230                 //If we are at maxDist, it can very well be that there is no valid closest obstacle data for this cell, this is not an error.
00231         }
00232 }
00233 
00234 
00235 float DynamicEDTOctomap::getDistance(const octomap::point3d& p) const {
00236   int x,y,z;
00237   worldToMap(p, x, y, z);
00238   if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
00239       return data[x][y][z].dist*treeResolution;
00240   } else {
00241       return distanceValue_Error;
00242   }
00243 }
00244 
00245 float DynamicEDTOctomap::getDistance_unsafe(const octomap::point3d& p) const {
00246   int x,y,z;
00247   worldToMap(p, x, y, z);
00248   return data[x][y][z].dist*treeResolution;
00249 }
00250 
00251 
00252 float DynamicEDTOctomap::getDistance(const octomap::OcTreeKey& k) const {
00253   int x = k[0] + offsetX;
00254   int y = k[1] + offsetY;
00255   int z = k[2] + offsetZ;
00256 
00257   if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
00258       return data[x][y][z].dist*treeResolution;
00259   } else {
00260       return distanceValue_Error;
00261   }
00262 }
00263 
00264 
00265 float DynamicEDTOctomap::getDistance_unsafe(const octomap::OcTreeKey& k) const {
00266   int x = k[0] + offsetX;
00267   int y = k[1] + offsetY;
00268   int z = k[2] + offsetZ;
00269 
00270   return data[x][y][z].dist*treeResolution;
00271 }
00272 
00273 
00274 int DynamicEDTOctomap::getSquaredDistanceInCells(const octomap::point3d& p) const {
00275   int x,y,z;
00276   worldToMap(p, x, y, z);
00277   if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
00278     return data[x][y][z].sqdist;
00279   } else {
00280     return distanceInCellsValue_Error;
00281   }
00282 }
00283 
00284 int DynamicEDTOctomap::getSquaredDistanceInCells_unsafe(const octomap::point3d& p) const {
00285   int x,y,z;
00286   worldToMap(p, x, y, z);
00287   return data[x][y][z].sqdist;
00288 }
00289 
00290 
00291 bool DynamicEDTOctomap::checkConsistency() const {
00292 
00293         for(octomap::KeyBoolMap::const_iterator it = octree->changedKeysBegin(), end=octree->changedKeysEnd(); it!=end; ++it){
00294                 //std::cerr<<"Cannot check consistency, you must execute the update() method first."<<std::endl;
00295                 return false;
00296         }
00297 
00298         for(int x=0; x<sizeX; x++){
00299                 for(int y=0; y<sizeY; y++){
00300                         for(int z=0; z<sizeZ; z++){
00301 
00302                                 octomap::point3d point;
00303                                 mapToWorld(x,y,z,point);
00304                                 octomap::OcTreeNode* node = octree->search(point);
00305 
00306                                 bool mapOccupied = isOccupied(x,y,z);
00307                                 bool treeOccupied = false;
00308                                 if(node){
00309                                         treeOccupied = octree->isNodeOccupied(node);
00310                                 } else {
00311                                         if(unknownOccupied)
00312                                                 treeOccupied = true;
00313                                 }
00314 
00315                                 if(mapOccupied != treeOccupied){
00316                                         //std::cerr<<"OCCUPANCY MISMATCH BETWEEN TREE AND MAP at "<<x<<","<<y<<","<<z<<std::endl;
00317                                         //std::cerr<<"Tree "<<treeOccupied<<std::endl;
00318                                         //std::cerr<<"Map "<<mapOccupied<<std::endl;
00319                                         return false;
00320                                 }
00321                         }
00322                 }
00323         }
00324 
00325         return true;
00326 }
00327 
00328 
00329 


dynamicEDT3D
Author(s): Christoph Sprunk
autogenerated on Thu Feb 11 2016 23:51:18