35 #include <pcl/common/transforms.h> 47 UFATAL(
"This function should not be used with octomap >= 1.8");
55 UFATAL(
"This function should not be used with octomap >= 1.8");
64 if (!this->collapsible())
return false;
70 for (
unsigned int i=0;i<8;i++) {
77 UFATAL(
"This function should not be used with octomap >= 1.8");
84 assert(!hasChildren());
85 for (
unsigned int k=0; k<8; k++) {
91 UFATAL(
"This function should not be used with octomap >= 1.8");
102 UFATAL(
"This function should not be used with octomap >= 1.8");
124 #ifndef OCTOMAP_PRE_18 135 for (
unsigned int i=0;i<8;i++) {
143 UFATAL(
"This function should not be used with octomap < 1.8");
149 #ifndef OCTOMAP_PRE_18 159 for (
unsigned int i = 1; i<8; i++) {
167 UFATAL(
"This function should not be used with octomap < 1.8");
179 RtabmapColorOcTreeNode::Color prev_color = n->
getColor();
180 n->
setColor((prev_color.r + r)/2, (prev_color.g + g)/2, (prev_color.b + b)/2);
196 RtabmapColorOcTreeNode::Color prev_color = n->
getColor();
199 + (double) r * (0.99-node_prob));
201 + (double) g * (0.99-node_prob));
203 + (double) b * (0.99-node_prob));
219 #ifndef OCTOMAP_PRE_18 224 for (
unsigned int i=0; i<8; i++) {
235 if (node->hasChildren()){
238 for (
unsigned int i=0; i<8; i++) {
239 if (node->childExists(i)) {
253 #ifndef OCTOMAP_PRE_18 257 AbstractOcTree::registerTreeType(tree);
267 fullUpdate_(
Parameters::defaultGridGlobalFullUpdate()),
268 updateError_(
Parameters::defaultGridGlobalUpdateError()),
270 rayTracing_(
Parameters::defaultGridRayTracing())
272 float cellSize = Parameters::defaultGridCellSize();
279 float occupancyThr = Parameters::defaultGridGlobalOccupancyThr();
280 float probHit = Parameters::defaultGridGlobalProbHit();
281 float probMiss = Parameters::defaultGridGlobalProbMiss();
282 float clampingMin = Parameters::defaultGridGlobalProbClampingMin();
283 float clampingMax = Parameters::defaultGridGlobalProbClampingMax();
284 Parameters::parse(parameters, Parameters::kGridGlobalOccupancyThr(), occupancyThr);
287 Parameters::parse(parameters, Parameters::kGridGlobalProbClampingMin(), clampingMin);
288 Parameters::parse(parameters, Parameters::kGridGlobalProbClampingMax(), clampingMax);
291 if(occupancyThr <= 0.0
f)
293 UWARN(
"Cannot set %s to null for OctoMap, using default value %f instead.",
294 Parameters::kGridGlobalOccupancyThr().c_str(),
295 Parameters::defaultGridGlobalOccupancyThr());
296 occupancyThr = Parameters::defaultGridGlobalOccupancyThr();
298 octree_->setOccupancyThres(occupancyThr);
300 octree_->setProbMiss(probMiss);
301 octree_->setClampingThresMin(clampingMin);
302 octree_->setClampingThresMax(clampingMax);
320 octree_->setOccupancyThres(occupancyThr);
344 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & ground,
345 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & obstacles,
346 const pcl::PointXYZ & viewPoint)
348 UDEBUG(
"nodeId=%d", nodeId);
350 cacheClouds_.insert(std::make_pair(nodeId, std::make_pair(ground, obstacles)));
354 const cv::Mat & ground,
355 const cv::Mat & obstacles,
356 const cv::Mat & empty,
357 const cv::Point3f & viewPoint)
359 UASSERT_MSG(ground.empty() || ground.type() == CV_32FC3 || ground.type() == CV_32FC(4) || ground.type() == CV_32FC(6),
uFormat(
"Are local occupancy grids not 3d? (opencv type=%d)", ground.type()).c_str());
360 UASSERT_MSG(obstacles.empty() || obstacles.type() == CV_32FC3 || obstacles.type() == CV_32FC(4) || obstacles.type() == CV_32FC(6),
uFormat(
"Are local occupancy grids not 3d? (opencv type=%d)", obstacles.type()).c_str());
361 UASSERT_MSG(empty.empty() || empty.type() == CV_32FC3 || empty.type() == CV_32FC(4) || empty.type() == CV_32FC(6),
uFormat(
"Are local occupancy grids not 3d? (opencv type=%d)", empty.type()).c_str());
362 UDEBUG(
"nodeId=%d", nodeId);
363 uInsert(
cache_, std::make_pair(nodeId, std::make_pair(std::make_pair(ground, obstacles), empty)));
369 UDEBUG(
"Update (poses=%d addedNodes_=%d)", (
int)poses.size(), (int)
addedNodes_.size());
372 bool graphOptimized =
false;
374 std::map<int, Transform> transforms;
375 std::map<int, Transform> updatedAddedNodes;
379 std::map<int, Transform>::const_iterator jter = poses.find(iter->first);
380 if(jter != poses.end())
382 graphChanged =
false;
383 UASSERT(!iter->second.isNull() && !jter->second.isNull());
385 if(iter->second.getDistanceSquared(jter->second) > updateErrorSqrd)
387 t = jter->second * iter->second.inverse();
388 graphOptimized =
true;
390 transforms.insert(std::make_pair(jter->first, t));
391 updatedAddedNodes.insert(std::make_pair(jter->first, jter->second));
395 UDEBUG(
"Updated pose for node %d is not found, some points may not be copied. Use negative ids to just update cell values without adding new ones.", jter->first);
398 if(graphOptimized || graphChanged)
402 UWARN(
"Graph has changed! The whole map should be rebuilt.");
406 UINFO(
"Graph optimized!");
431 std::map<int, Transform>::iterator jter = transforms.find(nOld.
getNodeRefId());
432 if(jter != transforms.end())
447 cv::Point3f cvPt(pt.
x(), pt.
y(), pt.
z());
484 UERROR(
"Could not update node at (%f,%f,%f)", cvPt.x, cvPt.y, cvPt.z);
489 UERROR(
"Could not find key for (%f,%f,%f)", cvPt.x, cvPt.y, cvPt.z);
492 else if(jter == transforms.end())
499 UINFO(
"Graph optimization detected, moved %d/%d in %fs", copied, count, t.
ticks());
511 std::list<std::pair<int, Transform> > orderedPoses;
514 UDEBUG(
"Last id = %d", lastId);
517 for(std::map<int, Transform>::const_iterator iter=poses.upper_bound(0); iter!=poses.end(); ++iter)
521 orderedPoses.push_back(*iter);
526 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
530 orderedPoses.push_back(*iter);
538 UDEBUG(
"orderedPoses = %d", (
int)orderedPoses.size());
541 for(std::list<std::pair<int, Transform> >::const_iterator iter=orderedPoses.begin(); iter!=orderedPoses.end(); ++iter)
543 std::map<int, std::pair<const pcl::PointCloud<pcl::PointXYZRGB>::Ptr,
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr> >::iterator cloudIter;
544 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator occupancyIter;
545 std::map<int, cv::Point3f>::iterator viewPointIter;
547 occupancyIter =
cache_.find(iter->first);
554 octomap::point3d sensorOrigin(iter->second.x(), iter->second.y(), iter->second.z());
555 sensorOrigin +=
octomap::point3d(viewPointIter->second.x, viewPointIter->second.y, viewPointIter->second.z);
563 UERROR(
"Could not generate Key for origin ", sensorOrigin.x(), sensorOrigin.y(), sensorOrigin.z());
566 bool computeRays =
rayTracing_ && (occupancyIter ==
cache_.end() || occupancyIter->second.second.empty());
571 unsigned int maxGroundPts = occupancyIter !=
cache_.end()?occupancyIter->second.first.first.cols:cloudIter->second.first->size();
572 UDEBUG(
"%d: compute free cells (from %d ground points)", iter->first, (
int)maxGroundPts);
573 Eigen::Affine3f t = iter->second.toEigen3f();
575 if(occupancyIter !=
cache_.end())
580 for (
unsigned int i=0; i<maxGroundPts; ++i)
583 if(occupancyIter !=
cache_.end())
593 bool ignoreOccupiedCell =
false;
594 if(rangeMaxSqrd > 0.0
f)
596 octomap::point3d v(pt.x - cellSize - sensorOrigin.x(), pt.y - cellSize - sensorOrigin.y(), pt.z - cellSize - sensorOrigin.z());
597 if(v.norm_sq() > rangeMaxSqrd)
602 point = sensorOrigin + v;
603 ignoreOccupiedCell=
true;
607 if(!ignoreOccupiedCell)
613 if(iter->first >0 && iter->first<lastId)
628 if(!
hasColor_ && !(pt.r ==0 && pt.g == 0 && pt.b == 0) && !(pt.r ==255 && pt.g == 255 && pt.b == 255))
645 (iter->first < 0 || iter->first>lastId) &&
651 UDEBUG(
"%d: ground cells=%d free cells=%d", iter->first, (
int)maxGroundPts, (
int)free_cells.size());
654 unsigned int maxObstaclePts = occupancyIter !=
cache_.end()?occupancyIter->second.first.second.cols:cloudIter->second.second->size();
655 UDEBUG(
"%d: compute occupied cells (from %d obstacle points)", iter->first, (
int)maxObstaclePts);
657 if(occupancyIter !=
cache_.end())
660 UASSERT(tmpObstacle.
size() == (int)maxObstaclePts);
662 for (
unsigned int i=0; i<maxObstaclePts; ++i)
665 if(occupancyIter !=
cache_.end())
677 bool ignoreOccupiedCell =
false;
678 if(rangeMaxSqrd > 0.0
f)
680 octomap::point3d v(pt.x - cellSize - sensorOrigin.x(), pt.y - cellSize - sensorOrigin.y(), pt.z - cellSize - sensorOrigin.z());
681 if(v.norm_sq() > rangeMaxSqrd)
686 point = sensorOrigin + v;
687 ignoreOccupiedCell=
true;
691 if(!ignoreOccupiedCell)
697 if(iter->first >0 && iter->first<lastId)
712 if(!
hasColor_ && !(pt.r ==0 && pt.g == 0 && pt.b == 0) && !(pt.r ==255 && pt.g == 255 && pt.b == 255))
729 (iter->first < 0 || iter->first>lastId) &&
735 UDEBUG(
"%d: occupied cells=%d free cells=%d", iter->first, (
int)maxObstaclePts, (
int)free_cells.size());
739 for(octomap::KeySet::iterator it = free_cells.begin(), end=free_cells.end(); it!= end; ++it)
763 if(occupancyIter !=
cache_.end() && occupancyIter->second.second.cols)
765 unsigned int maxEmptyPts = occupancyIter->second.second.cols;
766 UDEBUG(
"%d: compute free cells (from %d empty points)", iter->first, (
int)maxEmptyPts);
769 for (
unsigned int i=0; i<maxEmptyPts; ++i)
777 bool ignoreCell =
false;
778 if(rangeMaxSqrd > 0.0
f)
780 octomap::point3d v(pt.x - sensorOrigin.x(), pt.y - sensorOrigin.y(), pt.z - sensorOrigin.z());
781 if(v.norm_sq() > rangeMaxSqrd)
827 UDEBUG(
"%d: end", iter->first);
831 UDEBUG(
"Did not find %d in cache", iter->first);
884 q = v * ( 1 - s * f );
885 t = v * ( 1 - s * ( 1 - f ) );
921 unsigned int treeDepth,
922 std::vector<int> * obstacleIndices,
923 std::vector<int> * emptyIndices,
924 std::vector<int> * groundIndices,
925 bool originalRefPoints)
const 927 UASSERT(treeDepth <= octree_->getTreeDepth());
928 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZRGB>);
929 UDEBUG(
"depth=%d (maxDepth=%d) octree = %d",
953 bool addAllPoints = obstacleIndices == 0 && groundIndices == 0 && emptyIndices == 0;
961 if(
octree_->isNodeOccupied(*it) && (obstacleIndices != 0 || groundIndices != 0 || addAllPoints))
966 (*cloud)[oi] = pcl::PointXYZRGB(it->getColor().r, it->getColor().g, it->getColor().b);
971 float H = (maxZ - pt.
z())*299.0
f/(maxZ-minZ);
974 (*cloud)[oi].r = r*255.0f;
975 (*cloud)[oi].g = g*255.0f;
976 (*cloud)[oi].b = b*255.0f;
979 if(originalRefPoints && it->getOccupancyType() > 0)
982 (*cloud)[oi].
x = p.
x();
983 (*cloud)[oi].y = p.
y();
984 (*cloud)[oi].z = p.
z();
988 (*cloud)[oi].x = pt.
x()-halfCellSize;
989 (*cloud)[oi].y = pt.
y()-halfCellSize;
990 (*cloud)[oi].z = pt.
z();
997 groundIndices->at(gi++) = oi;
1000 else if(obstacleIndices)
1002 obstacleIndices->at(si++) = oi;
1007 else if(!
octree_->isNodeOccupied(*it) && (emptyIndices != 0 || addAllPoints))
1010 (*cloud)[oi] = pcl::PointXYZRGB(it->getColor().r, it->getColor().g, it->getColor().b);
1011 (*cloud)[oi].x = pt.
x()-halfCellSize;
1012 (*cloud)[oi].y = pt.
y()-halfCellSize;
1013 (*cloud)[oi].z = pt.
z();
1016 emptyIndices->at(ei++) = oi;
1025 obstacleIndices->resize(si);
1026 UDEBUG(
"obstacle=%d", si);
1030 emptyIndices->resize(ei);
1035 groundIndices->resize(gi);
1045 UDEBUG(
"minGridSize=%f, treeDepth=%d", minGridSize, (
int)treeDepth);
1046 UASSERT(treeDepth <= octree_->getTreeDepth());
1053 float halfCellSize = gridCellSize/2.0f;
1055 cv::Mat obstaclesMat = cv::Mat(1, (
int)
octree_->
size(), CV_32FC2);
1056 cv::Mat groundMat = cv::Mat(1, (
int)
octree_->
size(), CV_32FC2);
1059 cv::Vec2f * oPtr = obstaclesMat.ptr<cv::Vec2f>(0,0);
1060 cv::Vec2f * gPtr = groundMat.ptr<cv::Vec2f>(0,0);
1067 oPtr[oi][0] = pt.
x()-halfCellSize;
1068 oPtr[oi][1] = pt.
y()-halfCellSize;
1074 gPtr[gi][0] = pt.
x()-halfCellSize;
1075 gPtr[gi][1] = pt.
y()-halfCellSize;
1082 std::map<int, Transform> poses;
1084 std::map<int, std::pair<cv::Mat, cv::Mat> > maps;
1085 maps.insert(std::make_pair(1, std::make_pair(groundMat, obstaclesMat)));
1100 return octree_->writeBinary(path);
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
iterator begin(unsigned char maxDepth=0) const
ColorOcTreeNode::Color getAverageChildColor() const
cv::Mat RTABMAP_EXP create2DMapFromOccupancyLocalMaps(const std::map< int, Transform > &poses, const std::map< int, std::pair< cv::Mat, cv::Mat > > &occupancy, float cellSize, float &xMin, float &yMin, float minMapSize=0.0f, bool erode=false, float footprintRadius=0.0f)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
RtabmapColorOcTreeNode * averageNodeColor(const octomap::OcTreeKey &key, uint8_t r, uint8_t g, uint8_t b)
static StaticMemberInitializer RtabmapColorOcTreeMemberInit
static member to ensure static initialization (only once)
static void HSVtoRGB(float *r, float *g, float *b, float h, float s, float v)
void updateMinMax(const octomap::point3d &point)
const unsigned int tree_depth
void update(const std::map< int, Transform > &poses)
virtual NODE * updateNode(const OcTreeKey &key, float log_odds_update, bool lazy_eval=false)
std::map< int, Transform > addedNodes_
void updateColorChildren()
const iterator end() const
void deleteNodeChild(RtabmapColorOcTreeNode *node, unsigned int childIdx)
bool createChild(unsigned int i)
std::map< int, cv::Point3f > cacheViewPoints_
RtabmapColorOcTreeNode * getChild(unsigned int i)
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
std::map< std::string, std::string > ParametersMap
RtabmapColorOcTreeNode * search(double x, double y, double z, unsigned int depth=0) const
pcl::PointXYZ RTABMAP_EXP laserScanToPoint(const LaserScan &laserScan, int index)
unsigned int getTreeDepth() const
void updateOccupancyChildren()
virtual bool isNodeCollapsible(const RtabmapColorOcTreeNode *node) const
bool coordToKeyChecked(const point3d &coord, OcTreeKey &key) const
void setPointRef(const octomap::point3d &point)
void setNodeRefId(int nodeRefId)
RtabmapColorOcTreeNode * getNodeChild(RtabmapColorOcTreeNode *node, unsigned int childIdx) const
#define UASSERT(condition)
Wrappers of STL for convenient functions.
bool computeRayKeys(const point3d &origin, const point3d &end, KeyRay &ray) const
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
std::map< int, std::pair< std::pair< cv::Mat, cv::Mat >, cv::Mat > > cache_
const octomap::point3d & getPointRef() const
RtabmapColorOcTreeNode * integrateNodeColor(const octomap::OcTreeKey &key, uint8_t r, uint8_t g, uint8_t b)
int getOccupancyType() const
std::map< int, std::pair< const pcl::PointCloud< pcl::PointXYZRGB >::Ptr, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr > > cacheClouds_
GLM_FUNC_DECL genType floor(genType const &x)
AbstractOcTreeNode ** children
#define UASSERT_MSG(condition, msg_str)
bool nodeHasChildren(const RtabmapColorOcTreeNode *node) const
void updateInnerOccupancy()
RtabmapColorOcTree * octree_
pcl::PointXYZRGB RTABMAP_EXP laserScanToPointRGB(const LaserScan &laserScan, int index, unsigned char r=255, unsigned char g=255, unsigned char b=255)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr createCloud(unsigned int treeDepth=0, std::vector< int > *obstacleIndices=0, std::vector< int > *emptyIndices=0, std::vector< int > *groundIndices=0, bool originalRefPoints=true) const
unordered_ns::unordered_set< OcTreeKey, OcTreeKey::KeyHash > KeySet
RtabmapColorOcTree(double resolution)
Default constructor, sets resolution of leafs.
double getOccupancy() const
void setOccupancyType(char type)
void updateInnerOccupancyRecurs(RtabmapColorOcTreeNode *node, unsigned int depth)
double getResolution() const
bool writeBinary(const std::string &path)
octomath::Vector3 point3d
RtabmapColorOcTreeNode * root
StaticMemberInitializer()
ULogger class and convenient macros.
bool nodeChildExists(const RtabmapColorOcTreeNode *node, unsigned int childIdx) const
OctoMap(const ParametersMap ¶meters)
double getNodeSize(unsigned depth) const
RtabmapColorOcTreeNode * setNodeColor(const octomap::OcTreeKey &key, uint8_t r, uint8_t g, uint8_t b)
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
std::string UTILITE_EXP uFormat(const char *fmt,...)
virtual bool pruneNode(RtabmapColorOcTreeNode *node)
static LaserScan backwardCompatibility(const cv::Mat &oldScanFormat, int maxPoints=0, int maxRange=0, const Transform &localTransform=Transform::getIdentity())
virtual size_t size() const
void copyData(const ColorOcTreeNode &from)
double keyToCoord(key_type key, unsigned depth) const
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)