39 #include <rtabmap/core/Version.h> 42 #include <pcl/search/kdtree.h> 44 #include <nav_msgs/OccupancyGrid.h> 49 #ifdef WITH_OCTOMAP_MSGS 50 #ifdef RTABMAP_OCTOMAP 60 cloudOutputVoxelized_(
true),
61 cloudSubtractFiltering_(
false),
62 cloudSubtractFilteringMinNeighbors_(2),
63 mapFilterRadius_(0.0),
64 mapFilterAngle_(30.0),
65 mapCacheCleanup_(
true),
66 alwaysUpdateMap_(
false),
67 scanEmptyRayTracing_(
true),
73 octomapTreeDepth_(16),
74 octomapUpdated_(
true),
86 if(pnh.
hasParam(
"map_negative_poses_ignored"))
88 ROS_WARN(
"Parameter \"map_negative_poses_ignored\" has been " 89 "removed. Use \"map_always_update\" instead.");
90 if(!pnh.
hasParam(
"map_always_update"))
93 pnh.
getParam(
"map_negative_poses_ignored", negPosesIgnored);
99 if(pnh.
hasParam(
"map_negative_scan_empty_ray_tracing"))
101 ROS_WARN(
"Parameter \"map_negative_scan_empty_ray_tracing\" has been " 102 "removed. Use \"map_empty_ray_tracing\" instead.");
103 if(!pnh.
hasParam(
"map_empty_ray_tracing"))
110 if(pnh.
hasParam(
"scan_output_voxelized"))
112 ROS_WARN(
"Parameter \"scan_output_voxelized\" has been " 113 "removed. Use \"cloud_output_voxelized\" instead.");
114 if(!pnh.
hasParam(
"cloud_output_voxelized"))
132 #ifdef WITH_OCTOMAP_MSGS 133 #ifdef RTABMAP_OCTOMAP 138 ROS_WARN(
"octomap_tree_depth maximum is 16");
143 ROS_WARN(
"octomap_tree_depth cannot be negative, set to 16 instead");
157 if(usePublicNamespace)
183 #ifdef WITH_OCTOMAP_MSGS 184 #ifdef RTABMAP_OCTOMAP 210 #ifdef WITH_OCTOMAP_MSGS 211 #ifdef RTABMAP_OCTOMAP 223 const std::string & rosName,
224 const std::string & parameterName,
229 ParametersMap::const_iterator iter = Parameters::getDefaultParameters().find(parameterName);
230 if(iter != Parameters::getDefaultParameters().end())
232 ROS_WARN(
"Parameter \"%s\" has moved from " 233 "rtabmap_ros to rtabmap library. Use " 234 "parameter \"%s\" instead. The value is still " 235 "copied to new parameter name.",
237 parameterName.c_str());
238 std::string type = Parameters::getType(parameterName);
239 if(type.compare(
"float") || type.compare(
"double"))
245 else if(type.compare(
"int") || type.compare(
"unsigned int"))
251 else if(type.compare(
"bool"))
255 if(rosName.compare(
"grid_incremental") == 0)
264 ROS_ERROR(
"Not handled type \"%s\" for parameter \"%s\"", type.c_str(), parameterName.c_str());
269 ROS_ERROR(
"Parameter \"%s\" not found in default parameters.", parameterName.c_str());
277 if(pnh.
hasParam(
"cloud_frustum_culling"))
279 ROS_WARN(
"Parameter \"cloud_frustum_culling\" has been removed. OctoMap topics " 280 "already do it. You can remove it from your launch file.");
284 parameterMoved(pnh,
"cloud_decimation", Parameters::kGridDepthDecimation(), parameters);
285 parameterMoved(pnh,
"cloud_max_depth", Parameters::kGridRangeMax(), parameters);
286 parameterMoved(pnh,
"cloud_min_depth", Parameters::kGridRangeMin(), parameters);
287 parameterMoved(pnh,
"cloud_voxel_size", Parameters::kGridCellSize(), parameters);
288 parameterMoved(pnh,
"cloud_floor_culling_height", Parameters::kGridMaxGroundHeight(), parameters);
289 parameterMoved(pnh,
"cloud_ceiling_culling_height", Parameters::kGridMaxObstacleHeight(), parameters);
290 parameterMoved(pnh,
"cloud_noise_filtering_radius", Parameters::kGridNoiseFilteringRadius(), parameters);
291 parameterMoved(pnh,
"cloud_noise_filtering_min_neighbors", Parameters::kGridNoiseFilteringMinNeighbors(), parameters);
292 parameterMoved(pnh,
"scan_decimation", Parameters::kGridScanDecimation(), parameters);
293 parameterMoved(pnh,
"scan_voxel_size", Parameters::kGridCellSize(), parameters);
294 parameterMoved(pnh,
"proj_max_ground_angle", Parameters::kGridMaxGroundAngle(), parameters);
295 parameterMoved(pnh,
"proj_min_cluster_size", Parameters::kGridMinClusterSize(), parameters);
296 parameterMoved(pnh,
"proj_max_height", Parameters::kGridMaxObstacleHeight(), parameters);
297 parameterMoved(pnh,
"proj_max_obstacles_height", Parameters::kGridMaxObstacleHeight(), parameters);
298 parameterMoved(pnh,
"proj_max_ground_height", Parameters::kGridMaxGroundHeight(), parameters);
300 parameterMoved(pnh,
"proj_detect_flat_obstacles", Parameters::kGridFlatObstacleDetected(), parameters);
301 parameterMoved(pnh,
"proj_map_frame", Parameters::kGridMapFrameProjection(), parameters);
302 parameterMoved(pnh,
"grid_unknown_space_filled", Parameters::kGridScan2dUnknownSpaceFilled(), parameters);
303 parameterMoved(pnh,
"grid_cell_size", Parameters::kGridCellSize(), parameters);
304 parameterMoved(pnh,
"grid_incremental", Parameters::kGridGlobalFullUpdate(), parameters);
305 parameterMoved(pnh,
"grid_size", Parameters::kGridGlobalMinSize(), parameters);
306 parameterMoved(pnh,
"grid_eroded", Parameters::kGridGlobalEroded(), parameters);
307 parameterMoved(pnh,
"grid_footprint_radius", Parameters::kGridGlobalFootprintRadius(), parameters);
309 #ifdef WITH_OCTOMAP_MSGS 310 #ifdef RTABMAP_OCTOMAP 311 parameterMoved(pnh,
"octomap_ground_is_obstacle", Parameters::kGridGroundIsObstacle(), parameters);
312 parameterMoved(pnh,
"octomap_occupancy_thr", Parameters::kGridGlobalOccupancyThr(), parameters);
322 #ifdef WITH_OCTOMAP_MSGS 323 #ifdef RTABMAP_OCTOMAP 339 const std::map<int, rtabmap::Transform> & poses,
346 for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
348 std::map<int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter =
gridMaps_.find(iter->first);
352 data = memory->
getNodeData(iter->first,
false,
false,
false,
true);
355 ROS_WARN(
"Local occupancy grid doesn't exist for node %d", iter->first);
359 cv::Mat ground, obstacles, emptyCells;
369 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
395 #ifdef WITH_OCTOMAP_MSGS 396 #ifdef RTABMAP_OCTOMAP 400 for(std::map<void*, bool>::iterator iter=
latched_.begin(); iter!=
latched_.end(); ++iter)
402 iter->second =
false;
433 return std::map<int, Transform>();
437 const std::map<int, rtabmap::Transform> & posesIn,
441 const std::map<int, rtabmap::Signature> & signatures)
443 bool updateGridCache = updateGrid || updateOctomap;
444 if(!updateGrid && !updateOctomap)
461 updateGridCache = updateOctomap || updateGrid ||
468 #ifndef WITH_OCTOMAP_MSGS 469 updateOctomap =
false;
471 #ifndef RTABMAP_OCTOMAP 472 updateOctomap =
false;
479 UDEBUG(
"Updating map caches...");
481 if(!memory && signatures.size() == 0)
483 ROS_ERROR(
"Memory and signatures should not be both null!?");
484 return std::map<int, rtabmap::Transform>();
488 std::map<int, rtabmap::Transform> poses;
489 if(posesIn.begin()->first < 0)
491 poses.insert(posesIn.lower_bound(0), posesIn.end());
497 std::map<int, rtabmap::Transform> filteredPoses;
505 UDEBUG(
"Filter nodes...");
508 if(poses.find(0) != poses.end())
511 filteredPoses.insert(*poses.find(0));
516 filteredPoses = poses;
521 filteredPoses.erase(0);
524 bool longUpdate =
false;
526 if(filteredPoses.size() > 20)
528 if(updateGridCache &&
gridMaps_.size() < 5)
530 ROS_WARN(
"Many occupancy grids should be loaded (~%d), this may take a while to update the map(s)...",
int(filteredPoses.size()-
gridMaps_.size()));
533 #ifdef WITH_OCTOMAP_MSGS 534 #ifdef RTABMAP_OCTOMAP 537 ROS_WARN(
"Many clouds should be added to octomap (~%d), this may take a while to update the map(s)...",
int(filteredPoses.size()-
octomap_->
addedNodes().size()));
546 for(std::map<int, rtabmap::Transform>::iterator iter=filteredPoses.begin(); iter!=filteredPoses.end(); ++iter)
548 if(!iter->second.isNull())
553 UDEBUG(
"Data required for %d", iter->first);
554 std::map<int, rtabmap::Signature>::const_iterator findIter = signatures.find(iter->first);
555 if(findIter != signatures.end())
557 data = findIter->second.sensorData();
564 UDEBUG(
"Adding grid map %d to cache...", iter->first);
565 cv::Point3f viewPoint;
566 cv::Mat ground, obstacles, emptyCells;
572 static bool warningShown =
false;
573 if(occupancySavedInDB && generateGrid && !warningShown)
576 UWARN(
"Occupancy grid for location %d should be added to global map (e..g, a ROS node is subscribed to " 577 "any occupancy grid output) but it cannot be found " 578 "in memory. For convenience, the occupancy " 579 "grid is regenerated. Make sure parameter \"%s\" is true to " 580 "avoid this warning for the next locations added to map. For older " 581 "locations already in database without an occupancy grid map, you can use the " 582 "\"rtabmap-databaseViewer\" to regenerate the missing occupancy grid maps and " 583 "save them back in the database for next sessions. This warning is only shown once.",
584 data.
id(), Parameters::kRGBDCreateOccupancyGrid().c_str());
586 if(memory && occupancySavedInDB && generateGrid)
597 generateGrid?0:&ground,
598 generateGrid?0:&obstacles,
599 generateGrid?0:&emptyCells);
606 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
612 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
620 bool unknownSpaceFilled = Parameters::defaultGridScan2dUnknownSpaceFilled();
621 Parameters::parse(
parameters_, Parameters::kGridScan2dUnknownSpaceFilled(), unknownSpaceFilled);
638 generateGrid?0:&ground,
639 generateGrid?0:&obstacles,
640 generateGrid?0:&emptyCells);
647 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
653 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
671 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter =
gridMaps_.find(iter->first);
674 if(!mter->second.first.first.empty() || !mter->second.first.second.empty() || !mter->second.second.empty())
681 #ifdef WITH_OCTOMAP_MSGS 682 #ifdef RTABMAP_OCTOMAP 687 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter =
gridMaps_.find(iter->first);
691 if((mter->second.first.first.empty() || mter->second.first.first.channels() > 2) &&
692 (mter->second.first.second.empty() || mter->second.first.second.channels() > 2) &&
693 (mter->second.second.empty() || mter->second.second.channels() > 2))
695 octomap_->
addToCache(iter->first, mter->second.first.first, mter->second.first.second, mter->second.second, pter->second);
697 else if(!mter->second.first.first.empty() && !mter->second.first.second.empty() && !mter->second.second.empty())
699 ROS_WARN(
"Node %d: Cannot update octomap with 2D occupancy grids. " 700 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 701 "all occupancy grid parameters.",
711 ROS_ERROR(
"Pose null for node %d", iter->first);
720 #ifdef WITH_OCTOMAP_MSGS 721 #ifdef RTABMAP_OCTOMAP 730 for(std::map<
int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=
gridMaps_.begin();
744 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
groundClouds_.begin();
757 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
obstacleClouds_.begin();
776 return filteredPoses;
780 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
783 int minNeighborsInRadius)
785 UASSERT(minNeighborsInRadius > 0);
788 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(
new pcl::PointCloud<pcl::PointXYZRGB>);
789 output->resize(cloud->size());
791 for(
unsigned int i=0; i<cloud->size(); ++i)
793 std::vector<std::vector<size_t> > kIndices;
794 std::vector<std::vector<float> > kDistances;
795 cv::Mat pt = (cv::Mat_<float>(1, 3) << cloud->at(i).x, cloud->at(i).y, cloud->at(i).z);
796 substractCloudIndex.
radiusSearch(pt, kIndices, kDistances, radiusSearch, minNeighborsInRadius, 32, 0,
false);
797 if(kIndices.size() == 1 && kIndices[0].size() < minNeighborsInRadius)
799 output->at(oi++) = cloud->at(i);
807 const std::map<int, rtabmap::Transform> & poses,
809 const std::string & mapFrameId)
811 UDEBUG(
"Publishing maps...");
827 ROS_WARN(
"/scan_map topic is deprecated! Subscribe to /cloud_map topic " 828 "instead with <param name=\"%s\" type=\"string\" value=\"false\"/>. " 829 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 830 "all occupancy grid parameters.",
831 Parameters::kGridFromDepth().c_str());
835 ROS_WARN(
"/scan_map topic is deprecated! Subscribe to /cloud_map topic instead.");
840 bool graphGroundOptimized =
false;
841 bool graphObstacleOptimized =
false;
848 bool graphGroundChanged = updateGround;
849 bool graphObstacleChanged = updateObstacles;
850 for(std::map<int, Transform>::const_iterator iter=poses.lower_bound(0); iter!=poses.end(); ++iter)
852 std::map<int, Transform>::const_iterator jter;
858 graphGroundChanged =
false;
859 UASSERT(!iter->second.isNull() && !jter->second.isNull());
860 if(iter->second.getDistanceSquared(jter->second) > 0.0001)
862 graphGroundOptimized =
true;
871 graphObstacleChanged =
false;
872 UASSERT(!iter->second.isNull() && !jter->second.isNull());
873 if(iter->second.getDistanceSquared(jter->second) > 0.0001)
875 graphObstacleOptimized =
true;
880 int countObstacles = 0;
881 int countGrounds = 0;
884 if(graphGroundOptimized || graphGroundChanged)
892 if(graphObstacleOptimized || graphObstacleChanged )
901 if(graphGroundOptimized || graphObstacleOptimized)
903 ROS_INFO(
"Graph has changed, updating clouds...");
905 cv::Mat tmpGroundPts;
906 cv::Mat tmpObstaclePts;
907 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
915 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator kter=
groundClouds_.find(iter->first);
918 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::transformPointCloud(kter->second, iter->second);
922 for(
unsigned int i=0; i<transformed->size(); ++i)
924 if(tmpGroundPts.empty())
926 tmpGroundPts = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
927 tmpGroundPts.reserve(previousIndexedGroundSize>0?previousIndexedGroundSize:100);
931 cv::Mat pt = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
932 tmpGroundPts.push_back(pt);
939 if(updateObstacles &&
943 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator kter=
obstacleClouds_.find(iter->first);
946 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::transformPointCloud(kter->second, iter->second);
950 for(
unsigned int i=0; i<transformed->size(); ++i)
952 if(tmpObstaclePts.empty())
954 tmpObstaclePts = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
955 tmpObstaclePts.reserve(previousIndexedObstacleSize>0?previousIndexedObstacleSize:100);
959 cv::Mat pt = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
960 tmpObstaclePts.push_back(pt);
969 double addingPointsTime = t.
ticks();
971 if(graphGroundOptimized && !tmpGroundPts.empty())
975 if(graphObstacleOptimized && !tmpObstaclePts.empty())
979 double indexingTime = t.
ticks();
980 UINFO(
"Graph optimized! Time recreating clouds (%d ground, %d obstacles) = %f s (indexing %fs)", countGrounds, countObstacles, addingPointsTime+indexingTime, indexingTime);
982 else if(graphGroundChanged || graphObstacleChanged)
984 UWARN(
"Graph has changed! The whole cloud is regenerated.");
987 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
989 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter =
gridMaps_.find(iter->first);
996 if(jter!=
gridMaps_.end() && jter->second.first.first.cols)
998 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::laserScanToPointCloudRGB(LaserScan::backwardCompatibility(jter->second.first.first), iter->second, 0, 255, 0);
999 pcl::PointCloud<pcl::PointXYZRGB>::Ptr subtractedCloud = transformed;
1006 if(subtractedCloud->size())
1009 cv::Mat pts(subtractedCloud->size(), 3, CV_32FC1);
1010 for(
unsigned int i=0; i<subtractedCloud->size(); ++i)
1012 pts.at<
float>(i, 0) = subtractedCloud->at(i).x;
1013 pts.at<
float>(i, 1) = subtractedCloud->at(i).y;
1014 pts.at<
float>(i, 2) = subtractedCloud->at(i).z;
1028 groundClouds_.insert(std::make_pair(iter->first, util3d::transformPointCloud(subtractedCloud, iter->second.inverse())));
1030 if(subtractedCloud->size())
1043 if(jter!=
gridMaps_.end() && jter->second.first.second.cols)
1045 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::laserScanToPointCloudRGB(LaserScan::backwardCompatibility(jter->second.first.second), iter->second, 255, 0, 0);
1046 pcl::PointCloud<pcl::PointXYZRGB>::Ptr subtractedCloud = transformed;
1053 if(subtractedCloud->size())
1056 cv::Mat pts(subtractedCloud->size(), 3, CV_32FC1);
1057 for(
unsigned int i=0; i<subtractedCloud->size(); ++i)
1059 pts.at<
float>(i, 0) = subtractedCloud->at(i).x;
1060 pts.at<
float>(i, 1) = subtractedCloud->at(i).y;
1061 pts.at<
float>(i, 2) = subtractedCloud->at(i).z;
1075 obstacleClouds_.insert(std::make_pair(iter->first, util3d::transformPointCloud(subtractedCloud, iter->second.inverse())));
1077 if(subtractedCloud->size())
1099 ROS_INFO(
"Assembled %d obstacle and %d ground clouds (%d points, %fs)",
1102 if( countGrounds > 0 ||
1103 countObstacles > 0 ||
1113 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1115 cloudMsg->header.stamp =
stamp;
1116 cloudMsg->header.frame_id = mapFrameId;
1122 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1124 cloudMsg->header.stamp =
stamp;
1125 cloudMsg->header.frame_id = mapFrameId;
1132 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1134 cloudMsg->header.stamp =
stamp;
1135 cloudMsg->header.frame_id = mapFrameId;
1154 size_t totalBytes = 0;
1155 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
groundClouds_.begin();iter!=
groundClouds_.end();++iter)
1157 totalBytes +=
sizeof(int) + iter->second->points.size()*
sizeof(pcl::PointXYZRGB);
1161 totalBytes +=
sizeof(int) + iter->second->points.size()*
sizeof(pcl::PointXYZRGB);
1167 ROS_INFO(
"MapsManager: cleanup point clouds (%ld points, %ld cached clouds, ~%ld MB)...",
1170 totalBytes/1048576);
1198 #ifdef WITH_OCTOMAP_MSGS 1199 #ifdef RTABMAP_OCTOMAP 1213 octomap_msgs::Octomap msg;
1215 msg.header.frame_id = mapFrameId;
1216 msg.header.stamp =
stamp;
1222 octomap_msgs::Octomap msg;
1224 msg.header.frame_id = mapFrameId;
1225 msg.header.stamp =
stamp;
1235 sensor_msgs::PointCloud2 msg;
1236 pcl::IndicesPtr obstacleIndices(
new std::vector<int>);
1237 pcl::IndicesPtr frontierIndices(
new std::vector<int>);
1238 pcl::IndicesPtr emptyIndices(
new std::vector<int>);
1239 pcl::IndicesPtr groundIndices(
new std::vector<int>);
1240 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud =
octomap_->
createCloud(
octomapTreeDepth_, obstacleIndices.get(), emptyIndices.get(), groundIndices.get(),
true, frontierIndices.get());
1244 pcl::PointCloud<pcl::PointXYZRGB> cloudOccupiedSpace;
1245 pcl::IndicesPtr indices = util3d::concatenate(obstacleIndices, groundIndices);
1246 pcl::copyPointCloud(*cloud, *indices, cloudOccupiedSpace);
1248 msg.header.frame_id = mapFrameId;
1249 msg.header.stamp =
stamp;
1255 pcl::PointCloud<pcl::PointXYZRGB> cloudFrontier;
1256 pcl::copyPointCloud(*cloud, *frontierIndices, cloudFrontier);
1258 msg.header.frame_id = mapFrameId;
1259 msg.header.stamp =
stamp;
1265 pcl::PointCloud<pcl::PointXYZRGB> cloudObstacles;
1266 pcl::copyPointCloud(*cloud, *obstacleIndices, cloudObstacles);
1268 msg.header.frame_id = mapFrameId;
1269 msg.header.stamp =
stamp;
1275 pcl::PointCloud<pcl::PointXYZRGB> cloudGround;
1276 pcl::copyPointCloud(*cloud, *groundIndices, cloudGround);
1278 msg.header.frame_id = mapFrameId;
1279 msg.header.stamp =
stamp;
1285 pcl::PointCloud<pcl::PointXYZRGB> cloudEmptySpace;
1286 pcl::copyPointCloud(*cloud, *emptyIndices, cloudEmptySpace);
1288 msg.header.frame_id = mapFrameId;
1289 msg.header.stamp =
stamp;
1297 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1303 nav_msgs::OccupancyGrid map;
1304 map.info.resolution = gridCellSize;
1305 map.info.origin.position.x = 0.0;
1306 map.info.origin.position.y = 0.0;
1307 map.info.origin.position.z = 0.0;
1308 map.info.origin.orientation.x = 0.0;
1309 map.info.origin.orientation.y = 0.0;
1310 map.info.origin.orientation.z = 0.0;
1311 map.info.origin.orientation.w = 1.0;
1313 map.info.width = pixels.cols;
1314 map.info.height = pixels.rows;
1315 map.info.origin.position.x = xMin;
1316 map.info.origin.position.y = yMin;
1317 map.data.resize(map.info.width * map.info.height);
1319 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1321 map.header.frame_id = mapFrameId;
1322 map.header.stamp =
stamp;
1327 else if(poses.size())
1329 ROS_WARN(
"Octomap projection map is empty! (poses=%d octomap nodes=%d). " 1330 "Make sure you activated \"%s\" and \"%s\" to true. " 1331 "See \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" for more info.",
1333 Parameters::kGrid3D().c_str(), Parameters::kGridFromDepth().c_str());
1350 ROS_INFO(
"MapsManager: cleanup octomap (%ld leaf nodes, ~%ld MB)...",
1404 ROS_WARN(
"/proj_map topic is deprecated! Subscribe to /grid_map topic " 1405 "instead with <param name=\"%s\" type=\"string\" value=\"true\"/>. " 1406 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 1407 "all occupancy grid parameters.",
1408 Parameters::kGridFromDepth().c_str());
1412 ROS_WARN(
"/proj_map topic is deprecated! Subscribe to /grid_map topic instead.");
1419 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1424 nav_msgs::OccupancyGrid map;
1425 map.info.resolution = gridCellSize;
1426 map.info.origin.position.x = 0.0;
1427 map.info.origin.position.y = 0.0;
1428 map.info.origin.position.z = 0.0;
1429 map.info.origin.orientation.x = 0.0;
1430 map.info.origin.orientation.y = 0.0;
1431 map.info.origin.orientation.z = 0.0;
1432 map.info.origin.orientation.w = 1.0;
1434 map.info.width = pixels.cols;
1435 map.info.height = pixels.rows;
1436 map.info.origin.position.x = xMin;
1437 map.info.origin.position.y = yMin;
1438 map.data.resize(map.info.width * map.info.height);
1440 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1442 map.header.frame_id = mapFrameId;
1443 map.header.stamp =
stamp;
1451 else if(poses.size())
1459 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1460 cv::Mat pixels = this->
getGridMap(xMin, yMin, gridCellSize);
1465 nav_msgs::OccupancyGrid map;
1466 map.info.resolution = gridCellSize;
1467 map.info.origin.position.x = 0.0;
1468 map.info.origin.position.y = 0.0;
1469 map.info.origin.position.z = 0.0;
1470 map.info.origin.orientation.x = 0.0;
1471 map.info.origin.orientation.y = 0.0;
1472 map.info.origin.orientation.z = 0.0;
1473 map.info.origin.orientation.w = 1.0;
1475 map.info.width = pixels.cols;
1476 map.info.height = pixels.rows;
1477 map.info.origin.position.x = xMin;
1478 map.info.origin.position.y = yMin;
1479 map.data.resize(map.info.width * map.info.height);
1481 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1483 map.header.frame_id = mapFrameId;
1484 map.header.stamp =
stamp;
1497 else if(poses.size())
1521 size_t totalBytes = 0;
1522 for(std::map<
int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=
gridMaps_.begin(); iter!=
gridMaps_.end(); ++iter)
1524 totalBytes+=
sizeof(int)+
1525 iter->second.first.first.total()*iter->second.first.first.elemSize() +
1526 iter->second.first.second.total()*iter->second.first.second.elemSize() +
1527 iter->second.second.total()*iter->second.second.elemSize();
1530 ROS_INFO(
"MapsManager: cleanup %ld grid maps (~%ld MB)...",
gridMaps_.size(), totalBytes/1048576);
1540 float & gridCellSize)
1549 float & gridCellSize)
std::map< int, cv::Point3f > gridMapsViewpoints_
void set2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize, const std::map< int, rtabmap::Transform > &poses, const rtabmap::Memory *memory=0)
float getMinMapSize() const
std::map< int, rtabmap::Transform > getFilteredPoses(const std::map< int, rtabmap::Transform > &poses)
int cloudSubtractFilteringMinNeighbors_
bool update(const std::map< int, Transform > &poses)
ros::Publisher octoMapObstacleCloud_
void setParameters(const rtabmap::ParametersMap ¶meters)
ros::Publisher cloudGroundPub_
float getCellSize() const
std::map< int, Transform > RTABMAP_EXP radiusPosesFiltering(const std::map< int, Transform > &poses, float radius, float angle, bool keepLatest=true)
void publish(const boost::shared_ptr< M > &message) const
double uStr2Double(const std::string &str)
ros::Publisher gridMapPub_
rtabmap::OccupancyGrid * occupancyGrid_
int uStrNumCmp(const std::string &a, const std::string &b)
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const
std::pair< std::string, std::string > ParametersPair
ros::Publisher scanMapPub_
static bool fullMapToMsg(const OctomapT &octomap, Octomap &msg)
bool cloudOutputVoxelized_
std::map< void *, bool > latched_
ros::Publisher octoMapCloud_
std::map< std::string, std::string > ParametersMap
cv::Mat getGridProbMap(float &xMin, float &yMin, float &gridCellSize)
float gridCellSize() const
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
sensor_msgs::PointCloud2 PointCloud
void radiusSearch(const cv::Mat &query, std::vector< std::vector< size_t > > &indices, std::vector< std::vector< float > > &dists, float radius, int maxNeighbors=0, int checks=32, float eps=0.0, bool sorted=true) const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledObstacles_
std::map< int, pcl::PointCloud< pcl::PointXYZRGB >::Ptr > groundClouds_
rtabmap::OctoMap * octomap_
std::string getDatabaseVersion() const
geometry_msgs::TransformStamped t
bool cloudSubtractFiltering_
static bool binaryMapToMsg(const OctomapT &octomap, Octomap &msg)
std::string uBool2Str(bool boolean)
void setMap(const cv::Mat &map, float xMin, float yMin, float cellSize, const std::map< int, Transform > &poses)
rtabmap::ParametersMap parameters_
ros::Publisher octoMapPubFull_
#define UASSERT(condition)
bool update(const std::map< int, Transform > &poses)
void init(ros::NodeHandle &nh, ros::NodeHandle &pnh, const std::string &name, bool usePublicNamespace)
void addToCache(int nodeId, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &ground, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &obstacles, const pcl::PointXYZ &viewPoint)
const std::map< int, Transform > & addedNodes() const
int uStr2Int(const std::string &str)
std::string uNumber2Str(unsigned int number)
void createLocalMap(const Signature &node, cv::Mat &groundCells, cv::Mat &obstacleCells, cv::Mat &emptyCells, cv::Point3f &viewPoint) const
ros::Publisher cloudMapPub_
ros::Publisher octoMapPubBin_
std::map< int, rtabmap::Transform > updateMapCaches(const std::map< int, rtabmap::Transform > &poses, const rtabmap::Memory *memory, bool updateGrid, bool updateOctomap, const std::map< int, rtabmap::Signature > &signatures=std::map< int, rtabmap::Signature >())
void addToCache(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty)
unsigned int indexedFeatures() const
std::map< int, std::pair< std::pair< cv::Mat, cv::Mat >, cv::Mat > > gridMaps_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
rtabmap::FlannIndex assembledGroundIndex_
void buildKDTreeSingleIndex(const cv::Mat &features, int leafMaxSize=10, bool reorder=true, bool useDistanceL1=false, float rebalancingFactor=2.0f)
ros::Publisher projMapPub_
const RtabmapColorOcTree * octree() const
cv::Mat getProbMap(float &xMin, float &yMin) const
QMap< QString, QVariant > ParametersMap
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool uStr2Bool(const char *str)
bool isFullUpdate() const
bool uContains(const std::list< V > &list, const V &value)
void setPose(const Transform &pose)
rtabmap::FlannIndex assembledObstacleIndex_
void publishMaps(const std::map< int, rtabmap::Transform > &poses, const ros::Time &stamp, const std::string &mapFrameId)
void parameterMoved(ros::NodeHandle &nh, const std::string &rosName, const std::string ¶meterName, ParametersMap ¶meters)
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
bool scanEmptyRayTracing_
uint32_t getNumSubscribers() const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr subtractFiltering(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, const rtabmap::FlannIndex &substractCloudIndex, float radiusSearch, int minNeighborsInRadius)
bool hasSubscribers() const
bool getParam(const std::string &key, std::string &s) const
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
ros::Publisher octoMapEmptySpace_
ros::Publisher octoMapFrontierCloud_
std::vector< unsigned int > addPoints(const cv::Mat &features)
ros::Publisher octoMapGroundCloud_
std::map< int, pcl::PointCloud< pcl::PointXYZRGB >::Ptr > obstacleClouds_
void parseParameters(const ParametersMap ¶meters)
float getUpdateError() const
cv::Mat getGridMap(float &xMin, float &yMin, float &gridCellSize)
ros::Publisher octoMapProj_
bool hasParam(const std::string &key) const
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledGround_
bool isGridFromDepth() const
ros::Publisher cloudObstaclesPub_
cv::Mat getMap(float &xMin, float &yMin) const
ros::Publisher gridProbMapPub_
const std::map< int, Transform > & addedNodes() const
const cv::Point3f & gridViewPoint() const
std::map< int, rtabmap::Transform > assembledGroundPoses_
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
std::map< int, rtabmap::Transform > assembledObstaclePoses_
void backwardCompatibilityParameters(ros::NodeHandle &pnh, rtabmap::ParametersMap ¶meters) const