35 #ifdef RTABMAP_OCTOMAP 39 #include <pcl/io/pcd_io.h> 44 parameters_(parameters),
45 cloudDecimation_(
Parameters::defaultGridDepthDecimation()),
46 cloudMaxDepth_(
Parameters::defaultGridRangeMax()),
47 cloudMinDepth_(
Parameters::defaultGridRangeMin()),
49 footprintLength_(
Parameters::defaultGridFootprintLength()),
50 footprintWidth_(
Parameters::defaultGridFootprintWidth()),
51 footprintHeight_(
Parameters::defaultGridFootprintHeight()),
52 scanDecimation_(
Parameters::defaultGridScanDecimation()),
54 preVoxelFiltering_(
Parameters::defaultGridPreVoxelFiltering()),
55 occupancySensor_(
Parameters::defaultGridSensor()),
56 projMapFrame_(
Parameters::defaultGridMapFrameProjection()),
57 maxObstacleHeight_(
Parameters::defaultGridMaxObstacleHeight()),
58 normalKSearch_(
Parameters::defaultGridNormalK()),
59 groundNormalsUp_(
Parameters::defaultIcpPointToPlaneGroundNormalsUp()),
61 clusterRadius_(
Parameters::defaultGridClusterRadius()),
62 minClusterSize_(
Parameters::defaultGridMinClusterSize()),
63 flatObstaclesDetected_(
Parameters::defaultGridFlatObstacleDetected()),
64 minGroundHeight_(
Parameters::defaultGridMinGroundHeight()),
65 maxGroundHeight_(
Parameters::defaultGridMaxGroundHeight()),
66 normalsSegmentation_(
Parameters::defaultGridNormalsSegmentation()),
68 groundIsObstacle_(
Parameters::defaultGridGroundIsObstacle()),
69 noiseFilteringRadius_(
Parameters::defaultGridNoiseFilteringRadius()),
70 noiseFilteringMinNeighbors_(
Parameters::defaultGridNoiseFilteringMinNeighbors()),
71 scan2dUnknownSpaceFilled_(
Parameters::defaultGridScan2dUnknownSpaceFilled()),
72 rayTracing_(
Parameters::defaultGridRayTracing()),
73 fullUpdate_(
Parameters::defaultGridGlobalFullUpdate()),
74 minMapSize_(
Parameters::defaultGridGlobalMinSize()),
76 footprintRadius_(
Parameters::defaultGridGlobalFootprintRadius()),
77 updateError_(
Parameters::defaultGridGlobalUpdateError()),
78 occupancyThr_(
Parameters::defaultGridGlobalOccupancyThr()),
85 cloudAssembling_(
false),
86 assembledGround_(new
pcl::PointCloud<
pcl::PointXYZRGB>),
87 assembledObstacles_(new
pcl::PointCloud<
pcl::PointXYZRGB>),
88 assembledEmptyCells_(new
pcl::PointCloud<
pcl::PointXYZRGB>)
165 ParametersMap::const_iterator iter;
166 if((iter=parameters.find(Parameters::kGridDepthRoiRatios())) != parameters.end())
168 std::list<std::string> strValues =
uSplit(iter->second,
' ');
169 if(strValues.size() != 4)
171 ULOGGER_ERROR(
"The number of values must be 4 (%s=\"%s\")", iter->first.c_str(), iter->second.c_str());
175 std::vector<float> tmpValues(4);
177 for(std::list<std::string>::iterator jter = strValues.begin(); jter!=strValues.end(); ++jter)
183 if(tmpValues[0] >= 0 && tmpValues[0] < 1 && tmpValues[0] < 1.0
f-tmpValues[1] &&
184 tmpValues[1] >= 0 && tmpValues[1] < 1 && tmpValues[1] < 1.0
f-tmpValues[0] &&
185 tmpValues[2] >= 0 && tmpValues[2] < 1 && tmpValues[2] < 1.0
f-tmpValues[3] &&
186 tmpValues[3] >= 0 && tmpValues[3] < 1 && tmpValues[3] < 1.0
f-tmpValues[2])
192 ULOGGER_ERROR(
"The roi ratios are not valid (%s=\"%s\")", iter->first.c_str(), iter->second.c_str());
199 UWARN(
"\"%s\" should be not equal to 0 if not using normals " 200 "segmentation approach. Setting it to cell size (%f).",
201 Parameters::kGridMaxGroundHeight().c_str(),
cellSize_);
208 UWARN(
"\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
209 Parameters::kGridMaxGroundHeight().c_str(),
210 Parameters::kGridMaxObstacleHeight().c_str(),
211 Parameters::kGridMaxObstacleHeight().c_str());
218 UWARN(
"\"%s\" should be lower than \"%s\", setting \"%s\" to 0 (disabled).",
219 Parameters::kGridMinGroundHeight().c_str(),
220 Parameters::kGridMaxGroundHeight().c_str(),
221 Parameters::kGridMinGroundHeight().c_str());
226 void OccupancyGrid::setMap(
const cv::Mat & map,
float xMin,
float yMin,
float cellSize,
const std::map<int, Transform> & poses)
228 UDEBUG(
"map=%d/%d xMin=%f yMin=%f cellSize=%f poses=%d",
229 map.cols, map.rows, xMin, yMin, cellSize, (
int)poses.size());
231 if(!poses.empty() && !map.empty())
234 UASSERT(map.type() == CV_8SC1);
236 mapInfo_ = cv::Mat::zeros(map.size(), CV_32FC4);
237 for(
int i=0; i<map_.rows; ++i)
239 for(
int j=0; j<map_.cols; ++j)
241 const char value = map_.at<
char>(i,j);
242 float * info =
mapInfo_.ptr<
float>(i,j);
247 else if(value == 100)
256 addedNodes_.insert(poses.lower_bound(1), poses.end());
262 UASSERT_MSG(cellSize > 0.0
f,
uFormat(
"Param name is \"%s\"", Parameters::kGridCellSize().c_str()).c_str());
267 UWARN(
"Grid cell size has changed, the map is cleared!");
286 cv::Mat & groundCells,
287 cv::Mat & obstacleCells,
288 cv::Mat & emptyCells,
289 cv::Point3f & viewPoint)
291 UDEBUG(
"scan format=%s, occupancySensor_=%d normalsSegmentation_=%d grid3D_=%d",
298 viewPoint = cv::Point3f(
328 UDEBUG(
"ground=%d obstacles=%d channels=%d", emptyCells.cols, obstacleCells.cols, obstacleCells.cols?obstacleCells.channels():emptyCells.channels());
340 #ifdef RTABMAP_OCTOMAP 353 viewPoint = cv::Point3f(t.
x(), t.
y(), t.
z());
380 UWARN(
"Cannot create local map, scan is empty (node=%d, %s=0).", node.
id(), Parameters::kGridSensor().c_str());
386 pcl::IndicesPtr indices(
new std::vector<int>);
387 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
388 UDEBUG(
"Depth image : decimation=%d max=%f min=%f",
395 #ifdef RTABMAP_OCTOMAP 408 viewPoint = cv::Point3f(0,0,0);
418 viewPoint.x += t.
x();
419 viewPoint.y += t.
y();
420 viewPoint.z += t.
z();
440 viewPoint.x += t.
x();
441 viewPoint.y += t.
y();
442 viewPoint.z += t.
z();
454 cv::Mat scanGroundCells;
455 cv::Mat scanObstacleCells;
456 cv::Mat scanEmptyCells;
460 scanGroundCells = groundCells.clone();
461 scanObstacleCells = obstacleCells.clone();
462 scanEmptyCells = emptyCells.clone();
477 UDEBUG(
"groundCells, depth: size=%d channels=%d vs scan: size=%d channels=%d", groundCells.cols, groundCells.channels(), scanGroundCells.cols, scanGroundCells.channels());
478 UDEBUG(
"obstacleCells, depth: size=%d channels=%d vs scan: size=%d channels=%d", obstacleCells.cols, obstacleCells.channels(), scanObstacleCells.cols, scanObstacleCells.channels());
479 UDEBUG(
"emptyCells, depth: size=%d channels=%d vs scan: size=%d channels=%d", emptyCells.cols, emptyCells.channels(), scanEmptyCells.cols, scanEmptyCells.channels());
481 if(!groundCells.empty() && !scanGroundCells.empty())
482 cv::hconcat(groundCells, scanGroundCells, groundCells);
483 else if(!scanGroundCells.empty())
484 groundCells = scanGroundCells;
486 if(!obstacleCells.empty() && !scanObstacleCells.empty())
487 cv::hconcat(obstacleCells, scanObstacleCells, obstacleCells);
488 else if(!scanObstacleCells.empty())
489 obstacleCells = scanObstacleCells;
491 if(!emptyCells.empty() && !scanEmptyCells.empty())
492 cv::hconcat(emptyCells, scanEmptyCells, emptyCells);
493 else if(!scanEmptyCells.empty())
494 emptyCells = scanEmptyCells;
503 cv::Mat & groundCells,
504 cv::Mat & obstacleCells,
505 cv::Mat & emptyCells,
506 cv::Point3f & viewPointInOut)
const 513 Transform viewpointRotated =
Transform(0,0,0,roll,pitch,0) *
Transform(viewPointInOut.x, viewPointInOut.y, viewPointInOut.z, 0,0,0);
514 viewPointInOut.x = viewpointRotated.
x();
515 viewPointInOut.y = viewpointRotated.
y();
516 viewPointInOut.z = viewpointRotated.
z();
521 pcl::IndicesPtr groundIndices(
new std::vector<int>);
522 pcl::IndicesPtr obstaclesIndices(
new std::vector<int>);
524 cv::Mat obstaclesCloud;
529 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloudSegmented = segmentCloud<pcl::PointXYZRGBNormal>(cloud, pcl::IndicesPtr(
new std::vector<int>), pose, viewPointInOut, groundIndices, obstaclesIndices);
530 UDEBUG(
"groundIndices=%d, obstaclesIndices=%d", (
int)groundIndices->size(), (int)obstaclesIndices->size());
538 util3d::occupancy2DFromGroundObstacles<pcl::PointXYZRGBNormal>(cloudSegmented, groundIndices, obstaclesIndices, groundCells, obstacleCells,
cellSize_);
544 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudSegmented = segmentCloud<pcl::PointXYZRGB>(cloud, pcl::IndicesPtr(
new std::vector<int>), pose, viewPointInOut, groundIndices, obstaclesIndices);
545 UDEBUG(
"groundIndices=%d, obstaclesIndices=%d", (
int)groundIndices->size(), (int)obstaclesIndices->size());
553 util3d::occupancy2DFromGroundObstacles<pcl::PointXYZRGB>(cloudSegmented, groundIndices, obstaclesIndices, groundCells, obstacleCells,
cellSize_);
559 pcl::PointCloud<pcl::PointNormal>::Ptr cloudSegmented = segmentCloud<pcl::PointNormal>(cloud, pcl::IndicesPtr(
new std::vector<int>), pose, viewPointInOut, groundIndices, obstaclesIndices);
560 UDEBUG(
"groundIndices=%d, obstaclesIndices=%d", (
int)groundIndices->size(), (int)obstaclesIndices->size());
568 util3d::occupancy2DFromGroundObstacles<pcl::PointNormal>(cloudSegmented, groundIndices, obstaclesIndices, groundCells, obstacleCells,
cellSize_);
574 pcl::PointCloud<pcl::PointXYZ>::Ptr cloudSegmented = segmentCloud<pcl::PointXYZ>(cloud, pcl::IndicesPtr(
new std::vector<int>), pose, viewPointInOut, groundIndices, obstaclesIndices);
575 UDEBUG(
"groundIndices=%d, obstaclesIndices=%d", (
int)groundIndices->size(), (int)obstaclesIndices->size());
583 util3d::occupancy2DFromGroundObstacles<pcl::PointXYZ>(cloudSegmented, groundIndices, obstaclesIndices, groundCells, obstacleCells,
cellSize_);
587 if(
grid3D_ && (!obstaclesCloud.empty() || !groundCloud.empty()))
589 UDEBUG(
"ground=%d obstacles=%d", groundCloud.cols, obstaclesCloud.cols);
592 if(obstaclesCloud.empty())
594 obstaclesCloud = groundCloud;
595 groundCloud = cv::Mat();
599 UASSERT(obstaclesCloud.type() == groundCloud.type());
600 cv::Mat merged(1,obstaclesCloud.cols+groundCloud.cols, obstaclesCloud.type());
601 obstaclesCloud.copyTo(merged(
cv::Range::all(), cv::Range(0, obstaclesCloud.cols)));
602 groundCloud.copyTo(merged(
cv::Range::all(), cv::Range(obstaclesCloud.cols, obstaclesCloud.cols+groundCloud.cols)));
613 #ifdef RTABMAP_OCTOMAP 614 if(!groundCloud.empty() || !obstaclesCloud.empty())
622 octomap.
addToCache(1, groundCloud, obstaclesCloud, cv::Mat(), cv::Point3f(viewPointInOut.x, viewPointInOut.y, viewPointInOut.z));
623 std::map<int, Transform> poses;
627 pcl::IndicesPtr groundIndices(
new std::vector<int>);
628 pcl::IndicesPtr obstaclesIndices(
new std::vector<int>);
629 pcl::IndicesPtr emptyIndices(
new std::vector<int>);
630 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudWithRayTracing = octomap.
createCloud(0, obstaclesIndices.get(), emptyIndices.get(), groundIndices.get());
631 UDEBUG(
"ground=%d obstacles=%d empty=%d", (
int)groundIndices->size(), (int)obstaclesIndices->size(), (int)emptyIndices->size());
640 pcl::PointCloud<pcl::PointXYZ>::Ptr cloudWithRayTracing2(
new pcl::PointCloud<pcl::PointXYZ>);
641 pcl::copyPointCloud(*cloudWithRayTracing, *cloudWithRayTracing2);
650 UWARN(
"RTAB-Map is not built with OctoMap dependency, 3D ray tracing is ignored. Set \"%s\" to false to avoid this warning.", Parameters::kGridRayTracing().c_str());
661 cv::Mat laserScan = obstacleCells;
662 cv::Mat laserScanNoHit = groundCells;
663 obstacleCells = cv::Mat();
664 groundCells = cv::Mat();
676 UDEBUG(
"ground=%d obstacles=%d empty=%d, channels=%d", groundCells.cols, obstacleCells.cols, emptyCells.cols, obstacleCells.cols?obstacleCells.channels():groundCells.channels());
703 map = cv::Mat(map.size(), map.type());
705 for(
int i=0; i<map.rows; ++i)
707 for(
int j=0; j<map.cols; ++j)
709 const float * info =
mapInfo_.ptr<
float>(i, j);
712 map.at<
char>(i, j) = -1;
714 else if(info[3] >= occThr)
716 map.at<
char>(i, j) = 100;
720 map.at<
char>(i, j) = 0;
727 if(
erode_ && !map.empty())
744 for(
int i=0; i<map.rows; ++i)
746 for(
int j=0; j<map.cols; ++j)
748 const float * info =
mapInfo_.ptr<
float>(i, j);
751 map.at<
char>(i, j) = -1;
755 map.at<
char>(i, j) =
char(
probability(info[3])*100.0f);
762 UWARN(
"Map info is empty, cannot generate probabilistic occupancy grid");
769 const cv::Mat & ground,
770 const cv::Mat & obstacles,
771 const cv::Mat & empty)
773 UDEBUG(
"nodeId=%d (ground=%d obstacles=%d empty=%d)", nodeId, ground.cols, obstacles.cols, empty.cols);
776 UWARN(
"Cannot add nodes with negative id (nodeId=%d)", nodeId);
779 uInsert(
cache_, std::make_pair(nodeId==0?-1:nodeId, std::make_pair(std::make_pair(ground, obstacles), empty)));
785 UDEBUG(
"Update (poses=%d addedNodes_=%d)", (
int)posesIn.size(), (int)
addedNodes_.size());
794 std::map<int, cv::Mat> emptyLocalMaps;
795 std::map<int, cv::Mat> occupiedLocalMaps;
798 bool graphOptimized =
false;
800 std::map<int, Transform> transforms;
804 std::map<int, Transform>::const_iterator jter = posesIn.find(iter->first);
805 if(jter != posesIn.end())
807 graphChanged =
false;
809 UASSERT(!iter->second.isNull() && !jter->second.isNull());
811 if(iter->second.getDistanceSquared(jter->second) > updateErrorSqrd)
813 t = jter->second * iter->second.inverse();
814 graphOptimized =
true;
816 transforms.insert(std::make_pair(jter->first, t));
818 float x = jter->second.x();
819 float y =jter->second.y();
824 undefinedSize =
false;
841 UDEBUG(
"Updated pose for node %d is not found, some points may not be copied if graph has changed.", iter->first);
845 bool assembledGroundUpdated =
false;
846 bool assembledObstaclesUpdated =
false;
847 bool assembledEmptyCellsUpdated =
false;
849 if(graphOptimized || graphChanged)
853 UWARN(
"Graph has changed! The whole map should be rebuilt.");
857 UINFO(
"Graph optimized!");
871 std::map<int, std::pair<int, int> > tmpIndices;
872 for(std::map<
int, std::pair<int, int> >::iterator iter=
cellCount_.begin(); iter!=
cellCount_.end(); ++iter)
874 if(!
uContains(
cache_, iter->first) && transforms.find(iter->first) != transforms.end())
876 if(iter->second.first)
878 emptyLocalMaps.insert(std::make_pair( iter->first, cv::Mat(1, iter->second.first, CV_32FC2)));
880 if(iter->second.second)
882 occupiedLocalMaps.insert(std::make_pair( iter->first, cv::Mat(1, iter->second.second, CV_32FC2)));
884 tmpIndices.insert(std::make_pair(iter->first, std::make_pair(0,0)));
887 for(
int y=0; y<
map_.rows; ++y)
892 int nodeId = (int)info[0];
893 if(nodeId > 0 &&
map_.at<
char>(y,
x) >= 0)
895 if(tmpIndices.find(nodeId)!=tmpIndices.end())
897 std::map<int, Transform>::iterator tter = transforms.find(nodeId);
898 UASSERT(tter != transforms.end());
900 cv::Point3f pt(info[1], info[2], 0.0
f);
913 std::map<int, std::pair<int, int> >::iterator jter = tmpIndices.find(nodeId);
914 if(
map_.at<
char>(y,
x) == 0)
917 std::map<int, cv::Mat>::iterator iter = emptyLocalMaps.find(nodeId);
918 UASSERT(iter != emptyLocalMaps.end());
919 UASSERT(jter->second.first < iter->second.cols);
920 float * ptf = iter->second.ptr<
float>(0,jter->second.first++);
927 std::map<int, cv::Mat>::iterator iter = occupiedLocalMaps.find(nodeId);
928 UASSERT(iter != occupiedLocalMaps.end());
929 UASSERT(iter!=occupiedLocalMaps.end());
930 UASSERT(jter->second.second < iter->second.cols);
931 float * ptf = iter->second.ptr<
float>(0,jter->second.second++);
939 UERROR(
"Cell referred b node %d is unknown!?", nodeId);
945 for(std::map<
int, std::pair<int, int> >::iterator iter=tmpIndices.begin(); iter!=tmpIndices.end(); ++iter)
947 std::map<int, cv::Mat>::iterator jter = emptyLocalMaps.find(iter->first);
948 UASSERT_MSG((iter->second.first == 0 && (jter==emptyLocalMaps.end() || jter->second.empty())) ||
949 (iter->second.first != 0 && jter!=emptyLocalMaps.end() && jter->second.cols == iter->second.first),
950 uFormat(
"iter->second.first=%d jter->second.cols=%d", iter->second.first, jter!=emptyLocalMaps.end()?jter->second.cols:-1).c_str());
951 jter = occupiedLocalMaps.find(iter->first);
952 UASSERT_MSG((iter->second.second == 0 && (jter==occupiedLocalMaps.end() || jter->second.empty())) ||
953 (iter->second.second != 0 && jter!=occupiedLocalMaps.end() && jter->second.cols == iter->second.second),
954 uFormat(
"iter->second.first=%d jter->second.cols=%d", iter->second.first, jter!=emptyLocalMaps.end()?jter->second.cols:-1).c_str());
957 UDEBUG(
"min (%f,%f) max(%f,%f)", minX, minY, maxX, maxY);
967 else if(!
map_.empty())
974 undefinedSize =
false;
977 bool incrementalGraphUpdate = graphOptimized && !
fullUpdate_ && !graphChanged;
979 std::list<std::pair<int, Transform> > poses;
981 UDEBUG(
"Last id = %d", lastId);
984 for(std::map<int, Transform>::const_iterator iter=posesIn.lower_bound(1); iter!=posesIn.end(); ++iter)
988 UDEBUG(
"Pose %d not found in current added poses, it will be added to map", iter->first);
989 poses.push_back(*iter);
994 if(posesIn.find(0) != posesIn.end())
996 poses.push_back(std::make_pair(-1, posesIn.at(0)));
1001 for(std::list<std::pair<int, Transform> >::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
1003 UASSERT(!iter->second.isNull());
1005 float x = iter->second.x();
1006 float y =iter->second.y();
1011 undefinedSize =
false;
1029 UDEBUG(
"Updating from cache");
1030 for(std::list<std::pair<int, Transform> >::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
1034 const std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> & pair =
cache_.at(iter->first);
1036 UDEBUG(
"Adding grid %d: ground=%d obstacles=%d empty=%d", iter->first, pair.first.first.cols, pair.first.second.cols, pair.second.cols);
1040 if(pair.first.first.cols || pair.second.cols)
1042 ground = cv::Mat(1, pair.first.first.cols+pair.second.cols, CV_32FC2);
1044 if(pair.first.first.cols)
1046 if(pair.first.first.rows > 1 && pair.first.first.cols == 1)
1048 UFATAL(
"Occupancy local maps should be 1 row and X cols! (rows=%d cols=%d)", pair.first.first.rows, pair.first.first.cols);
1050 for(
int i=0; i<pair.first.first.cols; ++i)
1052 const float * vi = pair.first.first.ptr<
float>(0,i);
1053 float * vo = ground.ptr<
float>(0,i);
1055 if(pair.first.first.channels() != 2 && pair.first.first.channels() != 5)
1067 else if(maxX < vo[0])
1072 else if(maxY < vo[1])
1079 assembledGroundUpdated =
true;
1084 if(pair.second.cols)
1086 if(pair.second.rows > 1 && pair.second.cols == 1)
1088 UFATAL(
"Occupancy local maps should be 1 row and X cols! (rows=%d cols=%d)", pair.second.rows, pair.second.cols);
1090 for(
int i=0; i<pair.second.cols; ++i)
1092 const float * vi = pair.second.ptr<
float>(0,i);
1093 float * vo = ground.ptr<
float>(0,i+pair.first.first.cols);
1095 if(pair.second.channels() != 2 && pair.second.channels() != 5)
1107 else if(maxX < vo[0])
1112 else if(maxY < vo[1])
1119 assembledEmptyCellsUpdated =
true;
1122 uInsert(emptyLocalMaps, std::make_pair(iter->first, ground));
1125 if(pair.first.second.cols)
1127 if(pair.first.second.rows > 1 && pair.first.second.cols == 1)
1129 UFATAL(
"Occupancy local maps should be 1 row and X cols! (rows=%d cols=%d)", pair.first.second.rows, pair.first.second.cols);
1131 cv::Mat obstacles(1, pair.first.second.cols, CV_32FC2);
1132 for(
int i=0; i<obstacles.cols; ++i)
1134 const float * vi = pair.first.second.ptr<
float>(0,i);
1135 float * vo = obstacles.ptr<
float>(0,i);
1137 if(pair.first.second.channels() != 2 && pair.first.second.channels() != 5)
1149 else if(maxX < vo[0])
1154 else if(maxY < vo[1])
1157 uInsert(occupiedLocalMaps, std::make_pair(iter->first, obstacles));
1162 assembledObstaclesUpdated =
true;
1171 if(minX != maxX && minY != maxY)
1174 float xMin = minX-margin;
1176 float yMin = minY-margin;
1178 float xMax = maxX+margin;
1179 float yMax = maxY+margin;
1181 if(fabs((yMax - yMin) /
cellSize_) > 99999 ||
1182 fabs((xMax - xMin) /
cellSize_) > 99999)
1184 UERROR(
"Large map size!! map min=(%f, %f) max=(%f,%f). " 1185 "There's maybe an error with the poses provided! The map will not be created!",
1186 xMin, yMin, xMax, yMax);
1190 UDEBUG(
"map min=(%f, %f) odlMin(%f,%f) max=(%f,%f)", xMin, yMin,
xMin_,
yMin_, xMax, yMax);
1195 map = cv::Mat::ones(newMapSize, CV_8S)*-1;
1196 mapInfo = cv::Mat::zeros(newMapSize, CV_32FC4);
1201 newMapSize.width ==
map_.cols &&
1202 newMapSize.height ==
map_.rows)
1205 UDEBUG(
"Map same size!");
1231 UDEBUG(
"deltaX=%d, deltaY=%d", deltaX, deltaY);
1232 newMapSize.width = (xMax - xMin) /
cellSize_+0.5
f;
1233 newMapSize.height = (yMax - yMin) /
cellSize_+0.5
f;
1234 UDEBUG(
"%d/%d -> %d/%d",
map_.cols,
map_.rows, newMapSize.width, newMapSize.height);
1235 UASSERT(newMapSize.width >=
map_.cols && newMapSize.height >=
map_.rows);
1236 UASSERT(newMapSize.width >=
map_.cols+deltaX && newMapSize.height >=
map_.rows+deltaY);
1237 UASSERT(deltaX>=0 && deltaY>=0);
1238 map = cv::Mat::ones(newMapSize, CV_8S)*-1;
1239 mapInfo = cv::Mat::zeros(newMapSize,
mapInfo_.type());
1240 map_.copyTo(map(cv::Rect(deltaX, deltaY,
map_.cols,
map_.rows)));
1244 UASSERT(map.cols == mapInfo.cols && map.rows == mapInfo.rows);
1245 UDEBUG(
"map %d %d", map.cols, map.rows);
1248 UDEBUG(
"first pose= %d last pose=%d", poses.begin()->first, poses.rbegin()->first);
1250 for(std::list<std::pair<int, Transform> >::const_iterator kter = poses.begin(); kter!=poses.end(); ++kter)
1252 std::map<int, cv::Mat >::iterator iter = emptyLocalMaps.find(kter->first);
1253 std::map<int, cv::Mat >::iterator jter = occupiedLocalMaps.find(kter->first);
1254 if(iter != emptyLocalMaps.end() || jter!=occupiedLocalMaps.end())
1260 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(kter->first);
1261 if(cter ==
cellCount_.end() && kter->first > 0)
1263 cter =
cellCount_.insert(std::make_pair(kter->first, std::pair<int,int>(0,0))).first;
1265 if(iter!=emptyLocalMaps.end())
1267 for(
int i=0; i<iter->second.cols; ++i)
1269 float * ptf = iter->second.ptr<
float>(0,i);
1271 UASSERT_MSG(pt.y >=0 && pt.y < map.rows && pt.x >= 0 && pt.x < map.cols,
1272 uFormat(
"%d: pt=(%d,%d) map=%dx%d rawPt=(%f,%f) xMin=%f yMin=%f channels=%dvs%d (graph modified=%d)",
1273 kter->first, pt.x, pt.y, map.cols, map.rows, ptf[0], ptf[1], xMin, yMin, iter->second.channels(), mapInfo.channels()-1, (graphOptimized || graphChanged)?1:0).c_str());
1274 char & value = map.at<
char>(pt.y, pt.x);
1275 if(value != -2 && (!incrementalGraphUpdate || value==-1))
1277 float * info = mapInfo.ptr<
float>(pt.y, pt.x);
1278 int nodeId = (int)info[0];
1281 if(kter->first > 0 && (kter->first < nodeId || nodeId < 0))
1288 std::map<int, std::pair<int, int> >::iterator eter =
cellCount_.find(nodeId);
1292 eter->second.first -= 1;
1294 else if(value == 100)
1296 eter->second.second -= 1;
1300 eter->second.first += 1;
1306 info[0] = (float)kter->first;
1309 cter->second.first+=1;
1314 if(nodeId != kter->first)
1337 if(ptEnd.x >= map.cols)
1338 ptEnd.x = map.cols-1;
1342 if(ptEnd.y >= map.rows)
1343 ptEnd.y = map.rows-1;
1345 for(
int i=ptBegin.x; i<ptEnd.x; ++i)
1347 for(
int j=ptBegin.y; j<ptEnd.y; ++j)
1349 UASSERT(j < map.rows && i < map.cols);
1350 char & value = map.at<
char>(j, i);
1351 float * info = mapInfo.ptr<
float>(j, i);
1352 int nodeId = (int)info[0];
1355 if(kter->first > 0 && (kter->first < nodeId || nodeId < 0))
1362 std::map<int, std::pair<int, int> >::iterator eter =
cellCount_.find(nodeId);
1366 eter->second.first -= 1;
1368 else if(value == 100)
1370 eter->second.second -= 1;
1374 eter->second.first += 1;
1380 info[0] = (float)kter->first;
1384 cter->second.first+=1;
1391 if(jter!=occupiedLocalMaps.end())
1393 for(
int i=0; i<jter->second.cols; ++i)
1395 float * ptf = jter->second.ptr<
float>(0,i);
1397 UASSERT_MSG(pt.y>=0 && pt.y < map.rows && pt.x>=0 && pt.x < map.cols,
1398 uFormat(
"%d: pt=(%d,%d) map=%dx%d rawPt=(%f,%f) xMin=%f yMin=%f channels=%dvs%d (graph modified=%d)",
1399 kter->first, pt.x, pt.y, map.cols, map.rows, ptf[0], ptf[1], xMin, yMin, jter->second.channels(), mapInfo.channels()-1, (graphOptimized || graphChanged)?1:0).c_str());
1400 char & value = map.at<
char>(pt.y, pt.x);
1403 float * info = mapInfo.ptr<
float>(pt.y, pt.x);
1404 int nodeId = (int)info[0];
1407 if(kter->first > 0 && (kter->first < nodeId || nodeId < 0))
1414 std::map<int, std::pair<int, int> >::iterator eter =
cellCount_.find(nodeId);
1418 eter->second.first -= 1;
1420 else if(value == 100)
1422 eter->second.second -= 1;
1426 eter->second.second += 1;
1432 info[0] = (float)kter->first;
1435 cter->second.second+=1;
1439 if(nodeId != kter->first || value!=100)
1461 for(
int i=1; i<map.rows-1; ++i)
1463 for(
int j=1; j<map.cols-1; ++j)
1465 char & value = map.at<
char>(i, j);
1471 if(incrementalGraphUpdate && value == -1)
1473 float * info = mapInfo.ptr<
float>(i, j);
1476 if(map.at<
char>(i+1, j) == 100 && map.at<
char>(i-1, j) == 100)
1480 if(mapInfo.ptr<
float>(i+1, j)[0]>0.0f)
1482 info[0] = mapInfo.ptr<
float>(i+1, j)[0];
1485 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1487 cter->second.second+=1;
1489 else if(mapInfo.ptr<
float>(i-1, j)[0]>0.0f)
1491 info[0] = mapInfo.ptr<
float>(i-1, j)[0];
1494 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1496 cter->second.second+=1;
1499 else if(map.at<
char>(i, j+1) == 100 && map.at<
char>(i, j-1) == 100)
1503 if(mapInfo.ptr<
float>(i, j+1)[0]>0.0f)
1505 info[0] = mapInfo.ptr<
float>(i, j+1)[0];
1508 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1510 cter->second.second+=1;
1512 else if(mapInfo.ptr<
float>(i, j-1)[0]>0.0f)
1514 info[0] = mapInfo.ptr<
float>(i, j-1)[0];
1517 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1519 cter->second.second+=1;
1525 char sum = (map.at<
char>(i+1, j) == 0?1:0) +
1526 (map.at<
char>(i-1, j) == 0?1:0) +
1527 (map.at<
char>(i, j+1) == 0?1:0) +
1528 (map.at<
char>(i, j-1) == 0?1:0);
1533 if(map.at<
char>(i+1, j) != -1 && mapInfo.ptr<
float>(i+1, j)[0]>0.0
f)
1535 info[0] = mapInfo.ptr<
float>(i+1, j)[0];
1538 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1540 cter->second.first+=1;
1542 else if(map.at<
char>(i-1, j) != -1 && mapInfo.ptr<
float>(i-1, j)[0]>0.0
f)
1544 info[0] = mapInfo.ptr<
float>(i-1, j)[0];
1547 std::map<int, std::pair<int, int> >::iterator cter =
cellCount_.find(
int(info[0]));
1549 cter->second.first+=1;
1578 for(std::map<
int, std::pair<int, int> >::iterator iter=
cellCount_.begin(); iter!=
cellCount_.end();)
1580 UASSERT(iter->second.first >= 0 && iter->second.second >= 0);
1581 if(iter->second.first == 0 && iter->second.second == 0)
1617 for(std::map<
int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=
cache_.begin(); iter!=
cache_.end();)
1630 bool updated = !poses.empty() || graphOptimized || graphChanged;
1631 UDEBUG(
"Occupancy Grid update time = %f s (updated=%s)", timer.
ticks(), updated?
"true":
"false");
1640 memoryUsage +=
cache_.size()*(
sizeof(int) +
sizeof(std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat>) +
sizeof(std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator)) +
sizeof(std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >);
1641 for(std::map<
int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::const_iterator iter=
cache_.begin(); iter!=
cache_.end(); ++iter)
1643 memoryUsage += iter->second.first.first.total() * iter->second.first.first.elemSize();
1644 memoryUsage += iter->second.first.second.total() * iter->second.first.second.elemSize();
1645 memoryUsage += iter->second.second.total() * iter->second.second.elemSize();
1647 memoryUsage +=
map_.total() *
map_.elemSize();
1649 memoryUsage +=
cellCount_.size()*(
sizeof(int)*3 +
sizeof(std::pair<int, int>) +
sizeof(std::map<int, std::pair<int, int> >::iterator)) +
sizeof(std::map<int, std::pair<int, int> >);
1650 memoryUsage +=
addedNodes_.size()*(
sizeof(int) +
sizeof(
Transform)+
sizeof(float)*12 +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
bool update(const std::map< int, Transform > &poses)
unsigned int cloudDecimation_
cv::Mat RTABMAP_EXP erodeMap(const cv::Mat &map)
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, std::vector< int > *frontierIndices=0, std::vector< double > *cloudProb=0) const
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
std::vector< float > roiRatios_
cv::Mat getProbMap(float &xMin, float &yMin) const
static double probability(double logodds)
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
std::pair< std::string, std::string > ParametersPair
float UTILITE_EXP uStr2Float(const std::string &str)
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
const std::vector< StereoCameraModel > & stereoCameraModels() const
const cv::Mat & data() const
std::map< std::string, std::string > ParametersMap
void RTABMAP_EXP occupancy2DFromLaserScan(const cv::Mat &scanHit, const cv::Mat &scanNoHit, const cv::Point3f &viewpoint, cv::Mat &empty, cv::Mat &occupied, float cellSize, bool unknownSpaceFilled=false, float scanMaxRange=0.0f)
void setCellSize(float cellSize)
std::map< int, Transform > addedNodes_
Some conversion functions.
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
void setMap(const cv::Mat &map, float xMin, float yMin, float cellSize, const std::map< int, Transform > &poses)
LaserScan RTABMAP_EXP downsample(const LaserScan &cloud, int step)
#define UASSERT(condition)
bool update(const std::map< int, Transform > &poses)
Wrappers of STL for convenient functions.
std::list< std::string > uSplit(const std::string &str, char separator=' ')
unsigned long getMemoryUsed() const
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
const std::vector< CameraModel > & cameraModels() const
#define UASSERT_MSG(condition, msg_str)
OccupancyGrid(const ParametersMap ¶meters=ParametersMap())
LaserScan RTABMAP_EXP transformLaserScan(const LaserScan &laserScan, const Transform &transform)
void addToCache(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty)
static float logodds(double probability)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP cloudRGBFromSensorData(const SensorData &sensorData, int decimation=1, float maxDepth=0.0f, float minDepth=0.0f, std::vector< int > *validIndices=0, const ParametersMap &stereoParameters=ParametersMap(), const std::vector< float > &roiRatios=std::vector< float >())
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledGround_
std::map< int, std::pair< int, int > > cellCount_
cv::Mat getMap(float &xMin, float &yMin) const
LaserScan laserScanFromPointCloud(const PointCloud2T &cloud, bool filterNaNs, bool is2D, const Transform &transform)
std::map< int, std::pair< std::pair< cv::Mat, cv::Mat >, cv::Mat > > cache_
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledEmptyCells_
bool uContains(const std::list< V > &list, const V &value)
bool flatObstaclesDetected_
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledObstacles_
const LaserScan & laserScanRaw() const
SensorData & sensorData()
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
bool normalsSegmentation_
void createLocalMap(const Signature &node, cv::Mat &groundCells, cv::Mat &obstacleCells, cv::Mat &emptyCells, cv::Point3f &viewPoint)
const Transform & getPose() const
ULogger class and convenient macros.
ParametersMap parameters_
LaserScan RTABMAP_EXP rangeFiltering(const LaserScan &scan, float rangeMin, float rangeMax)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
float noiseFilteringRadius_
void parseParameters(const ParametersMap ¶meters)
float logodds(double probability)
static std::string formatName(const Format &format)
#define ULOGGER_ERROR(...)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP voxelize(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float voxelSize)
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
static LaserScan backwardCompatibility(const cv::Mat &oldScanFormat, int maxPoints=0, int maxRange=0, const Transform &localTransform=Transform::getIdentity())
Transform localTransform() const
void setCloudAssembling(bool enabled)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
bool scan2dUnknownSpaceFilled_
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)
int noiseFilteringMinNeighbors_