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),
72 #ifdef WITH_OCTOMAP_MSGS
73 #ifdef RTABMAP_OCTOMAP
77 octomapTreeDepth_(16),
78 octomapUpdated_(
true),
90 if(pnh.
hasParam(
"map_negative_poses_ignored"))
92 ROS_WARN(
"Parameter \"map_negative_poses_ignored\" has been " 93 "removed. Use \"map_always_update\" instead.");
94 if(!pnh.
hasParam(
"map_always_update"))
97 pnh.
getParam(
"map_negative_poses_ignored", negPosesIgnored);
103 if(pnh.
hasParam(
"map_negative_scan_empty_ray_tracing"))
105 ROS_WARN(
"Parameter \"map_negative_scan_empty_ray_tracing\" has been " 106 "removed. Use \"map_empty_ray_tracing\" instead.");
107 if(!pnh.
hasParam(
"map_empty_ray_tracing"))
114 if(pnh.
hasParam(
"scan_output_voxelized"))
116 ROS_WARN(
"Parameter \"scan_output_voxelized\" has been " 117 "removed. Use \"cloud_output_voxelized\" instead.");
118 if(!pnh.
hasParam(
"cloud_output_voxelized"))
136 #ifdef WITH_OCTOMAP_MSGS 137 #ifdef RTABMAP_OCTOMAP 141 ROS_WARN(
"octomap_tree_depth maximum is 16");
146 ROS_WARN(
"octomap_tree_depth cannot be negative, set to 16 instead");
160 if(usePublicNamespace)
186 #ifdef WITH_OCTOMAP_MSGS 187 #ifdef RTABMAP_OCTOMAP 213 #ifdef WITH_OCTOMAP_MSGS 214 #ifdef RTABMAP_OCTOMAP 226 const std::string & rosName,
227 const std::string & parameterName,
232 ParametersMap::const_iterator iter = Parameters::getDefaultParameters().find(parameterName);
233 if(iter != Parameters::getDefaultParameters().
end())
235 ROS_WARN(
"Parameter \"%s\" has moved from " 236 "rtabmap_ros to rtabmap library. Use " 237 "parameter \"%s\" instead. The value is still " 238 "copied to new parameter name.",
240 parameterName.c_str());
241 std::string type = Parameters::getType(parameterName);
242 if(type.compare(
"float") || type.compare(
"double"))
248 else if(type.compare(
"int") || type.compare(
"unsigned int"))
254 else if(type.compare(
"bool"))
258 if(rosName.compare(
"grid_incremental") == 0)
267 ROS_ERROR(
"Not handled type \"%s\" for parameter \"%s\"", type.c_str(), parameterName.c_str());
272 ROS_ERROR(
"Parameter \"%s\" not found in default parameters.", parameterName.c_str());
280 if(pnh.
hasParam(
"cloud_frustum_culling"))
282 ROS_WARN(
"Parameter \"cloud_frustum_culling\" has been removed. OctoMap topics " 283 "already do it. You can remove it from your launch file.");
287 parameterMoved(pnh,
"cloud_decimation", Parameters::kGridDepthDecimation(), parameters);
288 parameterMoved(pnh,
"cloud_max_depth", Parameters::kGridRangeMax(), parameters);
289 parameterMoved(pnh,
"cloud_min_depth", Parameters::kGridRangeMin(), parameters);
290 parameterMoved(pnh,
"cloud_voxel_size", Parameters::kGridCellSize(), parameters);
291 parameterMoved(pnh,
"cloud_floor_culling_height", Parameters::kGridMaxGroundHeight(), parameters);
292 parameterMoved(pnh,
"cloud_ceiling_culling_height", Parameters::kGridMaxObstacleHeight(), parameters);
293 parameterMoved(pnh,
"cloud_noise_filtering_radius", Parameters::kGridNoiseFilteringRadius(), parameters);
294 parameterMoved(pnh,
"cloud_noise_filtering_min_neighbors", Parameters::kGridNoiseFilteringMinNeighbors(), parameters);
295 parameterMoved(pnh,
"scan_decimation", Parameters::kGridScanDecimation(), parameters);
296 parameterMoved(pnh,
"scan_voxel_size", Parameters::kGridCellSize(), parameters);
297 parameterMoved(pnh,
"proj_max_ground_angle", Parameters::kGridMaxGroundAngle(), parameters);
298 parameterMoved(pnh,
"proj_min_cluster_size", Parameters::kGridMinClusterSize(), parameters);
299 parameterMoved(pnh,
"proj_max_height", Parameters::kGridMaxObstacleHeight(), parameters);
300 parameterMoved(pnh,
"proj_max_obstacles_height", Parameters::kGridMaxObstacleHeight(), parameters);
301 parameterMoved(pnh,
"proj_max_ground_height", Parameters::kGridMaxGroundHeight(), parameters);
303 parameterMoved(pnh,
"proj_detect_flat_obstacles", Parameters::kGridFlatObstacleDetected(), parameters);
304 parameterMoved(pnh,
"proj_map_frame", Parameters::kGridMapFrameProjection(), parameters);
305 parameterMoved(pnh,
"grid_unknown_space_filled", Parameters::kGridScan2dUnknownSpaceFilled(), parameters);
306 parameterMoved(pnh,
"grid_cell_size", Parameters::kGridCellSize(), parameters);
307 parameterMoved(pnh,
"grid_incremental", Parameters::kGridGlobalFullUpdate(), parameters);
308 parameterMoved(pnh,
"grid_size", Parameters::kGridGlobalMinSize(), parameters);
309 parameterMoved(pnh,
"grid_eroded", Parameters::kGridGlobalEroded(), parameters);
310 parameterMoved(pnh,
"grid_footprint_radius", Parameters::kGridGlobalFootprintRadius(), parameters);
312 #ifdef WITH_OCTOMAP_MSGS 313 #ifdef RTABMAP_OCTOMAP 314 parameterMoved(pnh,
"octomap_ground_is_obstacle", Parameters::kGridGroundIsObstacle(), parameters);
315 parameterMoved(pnh,
"octomap_occupancy_thr", Parameters::kGridGlobalOccupancyThr(), parameters);
325 #ifdef WITH_OCTOMAP_MSGS 326 #ifdef RTABMAP_OCTOMAP 342 const std::map<int, rtabmap::Transform> & poses,
349 for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
351 std::map<int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter =
gridMaps_.find(iter->first);
355 data = memory->
getNodeData(iter->first,
false,
false,
false,
true);
358 ROS_WARN(
"Local occupancy grid doesn't exist for node %d", iter->first);
362 cv::Mat ground, obstacles, emptyCells;
372 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
398 #ifdef WITH_OCTOMAP_MSGS 399 #ifdef RTABMAP_OCTOMAP 403 for(std::map<void*, bool>::iterator iter=
latched_.begin(); iter!=
latched_.end(); ++iter)
405 iter->second =
false;
436 return std::map<int, Transform>();
440 const std::map<int, rtabmap::Transform> & posesIn,
444 const std::map<int, rtabmap::Signature> & signatures)
446 bool updateGridCache = updateGrid || updateOctomap;
447 if(!updateGrid && !updateOctomap)
464 updateGridCache = updateOctomap || updateGrid ||
471 #ifndef WITH_OCTOMAP_MSGS 472 updateOctomap =
false;
474 #ifndef RTABMAP_OCTOMAP 475 updateOctomap =
false;
482 UDEBUG(
"Updating map caches...");
484 if(!memory && signatures.size() == 0)
486 ROS_ERROR(
"Memory and signatures should not be both null!?");
487 return std::map<int, rtabmap::Transform>();
491 std::map<int, rtabmap::Transform> poses;
492 if(posesIn.begin()->first < 0)
494 poses.insert(posesIn.lower_bound(0), posesIn.end());
500 std::map<int, rtabmap::Transform> filteredPoses;
508 UDEBUG(
"Filter nodes...");
511 if(poses.find(0) != poses.end())
514 filteredPoses.insert(*poses.find(0));
519 filteredPoses = poses;
524 filteredPoses.erase(0);
527 bool longUpdate =
false;
529 if(filteredPoses.size() > 20)
531 if(updateGridCache &&
gridMaps_.size() < 5)
533 ROS_WARN(
"Many occupancy grids should be loaded (~%d), this may take a while to update the map(s)...",
int(filteredPoses.size()-
gridMaps_.size()));
536 #ifdef WITH_OCTOMAP_MSGS 537 #ifdef RTABMAP_OCTOMAP 540 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()));
549 for(std::map<int, rtabmap::Transform>::iterator iter=filteredPoses.begin(); iter!=filteredPoses.end(); ++iter)
551 if(!iter->second.isNull())
556 ROS_DEBUG(
"Data required for %d", iter->first);
557 std::map<int, rtabmap::Signature>::const_iterator findIter = signatures.find(iter->first);
558 if(findIter != signatures.end())
560 data = findIter->second.sensorData();
567 ROS_DEBUG(
"Adding grid map %d to cache...", iter->first);
568 cv::Point3f viewPoint;
569 cv::Mat ground, obstacles, emptyCells;
575 static bool warningShown =
false;
576 if(occupancySavedInDB && generateGrid && !warningShown)
579 UWARN(
"Occupancy grid for location %d should be added to global map (e..g, a ROS node is subscribed to " 580 "any occupancy grid output) but it cannot be found " 581 "in memory. For convenience, the occupancy " 582 "grid is regenerated. Make sure parameter \"%s\" is true to " 583 "avoid this warning for the next locations added to map. For older " 584 "locations already in database without an occupancy grid map, you can use the " 585 "\"rtabmap-databaseViewer\" to regenerate the missing occupancy grid maps and " 586 "save them back in the database for next sessions. This warning is only shown once.",
587 data.
id(), Parameters::kRGBDCreateOccupancyGrid().c_str());
589 if(memory && occupancySavedInDB && generateGrid)
600 generateGrid?0:&ground,
601 generateGrid?0:&obstacles,
602 generateGrid?0:&emptyCells);
609 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
615 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
623 bool unknownSpaceFilled = Parameters::defaultGridScan2dUnknownSpaceFilled();
624 Parameters::parse(
parameters_, Parameters::kGridScan2dUnknownSpaceFilled(), unknownSpaceFilled);
641 generateGrid?0:&ground,
642 generateGrid?0:&obstacles,
643 generateGrid?0:&emptyCells);
650 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
656 uInsert(
gridMaps_, std::make_pair(iter->first, std::make_pair(std::make_pair(ground, obstacles), emptyCells)));
674 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter =
gridMaps_.find(iter->first);
677 if(!mter->second.first.first.empty() || !mter->second.first.second.empty() || !mter->second.second.empty())
684 #ifdef WITH_OCTOMAP_MSGS 685 #ifdef RTABMAP_OCTOMAP 690 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator mter =
gridMaps_.find(iter->first);
694 if((mter->second.first.first.empty() || mter->second.first.first.channels() > 2) &&
695 (mter->second.first.second.empty() || mter->second.first.second.channels() > 2) &&
696 (mter->second.second.empty() || mter->second.second.channels() > 2))
698 octomap_->
addToCache(iter->first, mter->second.first.first, mter->second.first.second, mter->second.second, pter->second);
700 else if(!mter->second.first.first.empty() && !mter->second.first.second.empty() && !mter->second.second.empty())
702 ROS_WARN(
"Node %d: Cannot update octomap with 2D occupancy grids. " 703 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 704 "all occupancy grid parameters.",
714 ROS_ERROR(
"Pose null for node %d", iter->first);
723 #ifdef WITH_OCTOMAP_MSGS 724 #ifdef RTABMAP_OCTOMAP 733 for(std::map<
int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=
gridMaps_.begin();
747 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
groundClouds_.begin();
760 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
obstacleClouds_.begin();
779 return filteredPoses;
783 const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
786 int minNeighborsInRadius)
788 UASSERT(minNeighborsInRadius > 0);
791 pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(
new pcl::PointCloud<pcl::PointXYZRGB>);
792 output->resize(cloud->size());
794 for(
unsigned int i=0; i<cloud->size(); ++i)
796 std::vector<std::vector<size_t> > kIndices;
797 std::vector<std::vector<float> > kDistances;
798 cv::Mat
pt = (cv::Mat_<float>(1, 3) << cloud->at(i).x, cloud->at(i).y, cloud->at(i).z);
799 substractCloudIndex.
radiusSearch(pt, kIndices, kDistances, radiusSearch, minNeighborsInRadius, 32, 0,
false);
800 if(kIndices.size() == 1 && kIndices[0].size() < minNeighborsInRadius)
802 output->at(oi++) = cloud->at(i);
810 const std::map<int, rtabmap::Transform> & poses,
812 const std::string & mapFrameId)
814 ROS_DEBUG(
"Publishing maps... poses=%d", (
int)poses.size());
830 ROS_WARN(
"/scan_map topic is deprecated! Subscribe to /cloud_map topic " 831 "instead with <param name=\"%s\" type=\"string\" value=\"0\"/>. " 832 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 833 "all occupancy grid parameters.",
834 Parameters::kGridSensor().c_str());
838 ROS_WARN(
"/scan_map topic is deprecated! Subscribe to /cloud_map topic instead.");
843 bool graphGroundOptimized =
false;
844 bool graphObstacleOptimized =
false;
851 bool graphGroundChanged = updateGround;
852 bool graphObstacleChanged = updateObstacles;
854 for(std::map<int, Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
856 std::map<int, Transform>::const_iterator jter;
862 graphGroundChanged =
false;
863 UASSERT(!iter->second.isNull() && !jter->second.isNull());
864 if(iter->second.getDistanceSquared(jter->second) > updateErrorSqr)
866 graphGroundOptimized =
true;
875 graphObstacleChanged =
false;
876 UASSERT(!iter->second.isNull() && !jter->second.isNull());
877 if(iter->second.getDistanceSquared(jter->second) > updateErrorSqr)
879 graphObstacleOptimized =
true;
884 int countObstacles = 0;
885 int countGrounds = 0;
888 if(graphGroundOptimized || graphGroundChanged)
896 if(graphObstacleOptimized || graphObstacleChanged )
905 if(graphGroundOptimized || graphObstacleOptimized)
907 ROS_INFO(
"Graph has changed, updating clouds...");
909 cv::Mat tmpGroundPts;
910 cv::Mat tmpObstaclePts;
911 for(std::map<int, Transform>::const_iterator iter = poses.lower_bound(1); iter!=poses.end(); ++iter)
916 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator kter=
groundClouds_.find(iter->first);
920 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::transformPointCloud(kter->second, iter->second);
924 for(
unsigned int i=0; i<transformed->size(); ++i)
926 if(tmpGroundPts.empty())
928 tmpGroundPts = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
929 tmpGroundPts.reserve(previousIndexedGroundSize>0?previousIndexedGroundSize:100);
933 cv::Mat
pt = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
934 tmpGroundPts.push_back(pt);
941 if(updateObstacles &&
944 std::map<int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator kter=
obstacleClouds_.find(iter->first);
948 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::transformPointCloud(kter->second, iter->second);
952 for(
unsigned int i=0; i<transformed->size(); ++i)
954 if(tmpObstaclePts.empty())
956 tmpObstaclePts = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
957 tmpObstaclePts.reserve(previousIndexedObstacleSize>0?previousIndexedObstacleSize:100);
961 cv::Mat
pt = (cv::Mat_<float>(1, 3) << transformed->at(i).x, transformed->at(i).y, transformed->at(i).z);
962 tmpObstaclePts.push_back(pt);
970 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter =
gridMaps_.find(iter->first);
974 double addingPointsTime = t.
ticks();
976 if(graphGroundOptimized && !tmpGroundPts.empty())
980 if(graphObstacleOptimized && !tmpObstaclePts.empty())
984 double indexingTime = t.
ticks();
985 ROS_INFO(
"Graph optimized! Time recreating clouds (%d ground, %d obstacles) = %f s (indexing %fs)", countGrounds, countObstacles, addingPointsTime+indexingTime, indexingTime);
987 else if(graphGroundChanged || graphObstacleChanged)
989 ROS_WARN(
"Graph has changed! The whole cloud is regenerated.");
992 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
994 std::map<int, std::pair<std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator jter =
gridMaps_.find(iter->first);
1001 if(jter!=
gridMaps_.end() && jter->second.first.first.cols)
1003 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::laserScanToPointCloudRGB(LaserScan::backwardCompatibility(jter->second.first.first), iter->second, 0, 255, 0);
1004 pcl::PointCloud<pcl::PointXYZRGB>::Ptr subtractedCloud = transformed;
1011 if(subtractedCloud->size())
1014 cv::Mat pts(subtractedCloud->size(), 3, CV_32FC1);
1015 for(
unsigned int i=0; i<subtractedCloud->size(); ++i)
1017 pts.at<
float>(i, 0) = subtractedCloud->at(i).x;
1018 pts.at<
float>(i, 1) = subtractedCloud->at(i).y;
1019 pts.at<
float>(i, 2) = subtractedCloud->at(i).z;
1033 groundClouds_.insert(std::make_pair(iter->first, util3d::transformPointCloud(subtractedCloud, iter->second.inverse())));
1035 if(subtractedCloud->size())
1048 if(jter!=
gridMaps_.end() && jter->second.first.second.cols)
1050 pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed = util3d::laserScanToPointCloudRGB(LaserScan::backwardCompatibility(jter->second.first.second), iter->second, 255, 0, 0);
1051 pcl::PointCloud<pcl::PointXYZRGB>::Ptr subtractedCloud = transformed;
1058 if(subtractedCloud->size())
1061 cv::Mat pts(subtractedCloud->size(), 3, CV_32FC1);
1062 for(
unsigned int i=0; i<subtractedCloud->size(); ++i)
1064 pts.at<
float>(i, 0) = subtractedCloud->at(i).x;
1065 pts.at<
float>(i, 1) = subtractedCloud->at(i).y;
1066 pts.at<
float>(i, 2) = subtractedCloud->at(i).z;
1080 obstacleClouds_.insert(std::make_pair(iter->first, util3d::transformPointCloud(subtractedCloud, iter->second.inverse())));
1082 if(subtractedCloud->size())
1104 ROS_INFO(
"Assembled %d obstacle and %d ground clouds (%d points, %fs)",
1107 if( countGrounds > 0 ||
1108 countObstacles > 0 ||
1118 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1120 cloudMsg->header.stamp =
stamp;
1121 cloudMsg->header.frame_id = mapFrameId;
1127 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1129 cloudMsg->header.stamp =
stamp;
1130 cloudMsg->header.frame_id = mapFrameId;
1137 sensor_msgs::PointCloud2::Ptr cloudMsg(
new sensor_msgs::PointCloud2);
1139 cloudMsg->header.stamp =
stamp;
1140 cloudMsg->header.frame_id = mapFrameId;
1159 size_t totalBytes = 0;
1160 for(std::map<
int, pcl::PointCloud<pcl::PointXYZRGB>::Ptr >::iterator iter=
groundClouds_.begin();iter!=
groundClouds_.end();++iter)
1162 totalBytes +=
sizeof(int) + iter->second->points.size()*
sizeof(pcl::PointXYZRGB);
1166 totalBytes +=
sizeof(int) + iter->second->points.size()*
sizeof(pcl::PointXYZRGB);
1172 ROS_INFO(
"MapsManager: cleanup point clouds (%ld points, %ld cached clouds, ~%ld MB)...",
1175 totalBytes/1048576);
1203 #ifdef WITH_OCTOMAP_MSGS 1204 #ifdef RTABMAP_OCTOMAP 1218 octomap_msgs::Octomap msg;
1220 msg.header.frame_id = mapFrameId;
1221 msg.header.stamp =
stamp;
1227 octomap_msgs::Octomap msg;
1229 msg.header.frame_id = mapFrameId;
1230 msg.header.stamp =
stamp;
1240 sensor_msgs::PointCloud2 msg;
1241 pcl::IndicesPtr obstacleIndices(
new std::vector<int>);
1242 pcl::IndicesPtr frontierIndices(
new std::vector<int>);
1243 pcl::IndicesPtr emptyIndices(
new std::vector<int>);
1244 pcl::IndicesPtr groundIndices(
new std::vector<int>);
1245 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud =
octomap_->
createCloud(
octomapTreeDepth_, obstacleIndices.get(), emptyIndices.get(), groundIndices.get(),
true, frontierIndices.get(),0);
1249 pcl::PointCloud<pcl::PointXYZRGB> cloudOccupiedSpace;
1250 pcl::IndicesPtr indices = util3d::concatenate(obstacleIndices, groundIndices);
1251 pcl::copyPointCloud(*cloud, *indices, cloudOccupiedSpace);
1253 msg.header.frame_id = mapFrameId;
1254 msg.header.stamp =
stamp;
1260 pcl::PointCloud<pcl::PointXYZRGB> cloudFrontier;
1261 pcl::copyPointCloud(*cloud, *frontierIndices, cloudFrontier);
1263 msg.header.frame_id = mapFrameId;
1264 msg.header.stamp =
stamp;
1270 pcl::PointCloud<pcl::PointXYZRGB> cloudObstacles;
1271 pcl::copyPointCloud(*cloud, *obstacleIndices, cloudObstacles);
1273 msg.header.frame_id = mapFrameId;
1274 msg.header.stamp =
stamp;
1280 pcl::PointCloud<pcl::PointXYZRGB> cloudGround;
1281 pcl::copyPointCloud(*cloud, *groundIndices, cloudGround);
1283 msg.header.frame_id = mapFrameId;
1284 msg.header.stamp =
stamp;
1290 pcl::PointCloud<pcl::PointXYZRGB> cloudEmptySpace;
1291 pcl::copyPointCloud(*cloud, *emptyIndices, cloudEmptySpace);
1293 msg.header.frame_id = mapFrameId;
1294 msg.header.stamp =
stamp;
1302 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1308 nav_msgs::OccupancyGrid map;
1309 map.info.resolution = gridCellSize;
1310 map.info.origin.position.x = 0.0;
1311 map.info.origin.position.y = 0.0;
1312 map.info.origin.position.z = 0.0;
1313 map.info.origin.orientation.x = 0.0;
1314 map.info.origin.orientation.y = 0.0;
1315 map.info.origin.orientation.z = 0.0;
1316 map.info.origin.orientation.w = 1.0;
1318 map.info.width = pixels.cols;
1319 map.info.height = pixels.rows;
1320 map.info.origin.position.x = xMin;
1321 map.info.origin.position.y = yMin;
1322 map.data.resize(map.info.width * map.info.height);
1324 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1326 map.header.frame_id = mapFrameId;
1327 map.header.stamp =
stamp;
1332 else if(poses.size())
1334 ROS_WARN(
"Octomap projection map is empty! (poses=%d octomap nodes=%d). " 1335 "Make sure you enabled \"%s\" and set \"%s\"=1. " 1336 "See \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" for more info.",
1338 Parameters::kGrid3D().c_str(), Parameters::kGridSensor().c_str());
1355 ROS_INFO(
"MapsManager: cleanup octomap (%ld leaf nodes, ~%ld MB)...",
1409 ROS_WARN(
"/proj_map topic is deprecated! Subscribe to /grid_map topic " 1410 "instead with <param name=\"%s\" type=\"string\" value=\"1\"/>. " 1411 "Do \"$ rosrun rtabmap_ros rtabmap --params | grep Grid\" to see " 1412 "all occupancy grid parameters.",
1413 Parameters::kGridSensor().c_str());
1417 ROS_WARN(
"/proj_map topic is deprecated! Subscribe to /grid_map topic instead.");
1424 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1429 nav_msgs::OccupancyGrid map;
1430 map.info.resolution = gridCellSize;
1431 map.info.origin.position.x = 0.0;
1432 map.info.origin.position.y = 0.0;
1433 map.info.origin.position.z = 0.0;
1434 map.info.origin.orientation.x = 0.0;
1435 map.info.origin.orientation.y = 0.0;
1436 map.info.origin.orientation.z = 0.0;
1437 map.info.origin.orientation.w = 1.0;
1439 map.info.width = pixels.cols;
1440 map.info.height = pixels.rows;
1441 map.info.origin.position.x = xMin;
1442 map.info.origin.position.y = yMin;
1443 map.data.resize(map.info.width * map.info.height);
1445 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1447 map.header.frame_id = mapFrameId;
1448 map.header.stamp =
stamp;
1456 else if(poses.size())
1464 float xMin=0.0f, yMin=0.0f, gridCellSize = 0.05f;
1465 cv::Mat pixels = this->
getGridMap(xMin, yMin, gridCellSize);
1470 nav_msgs::OccupancyGrid map;
1471 map.info.resolution = gridCellSize;
1472 map.info.origin.position.x = 0.0;
1473 map.info.origin.position.y = 0.0;
1474 map.info.origin.position.z = 0.0;
1475 map.info.origin.orientation.x = 0.0;
1476 map.info.origin.orientation.y = 0.0;
1477 map.info.origin.orientation.z = 0.0;
1478 map.info.origin.orientation.w = 1.0;
1480 map.info.width = pixels.cols;
1481 map.info.height = pixels.rows;
1482 map.info.origin.position.x = xMin;
1483 map.info.origin.position.y = yMin;
1484 map.data.resize(map.info.width * map.info.height);
1486 memcpy(map.data.data(), pixels.data, map.info.width * map.info.height);
1488 map.header.frame_id = mapFrameId;
1489 map.header.stamp =
stamp;
1502 else if(poses.size())
1526 size_t totalBytes = 0;
1527 for(std::map<
int, std::pair< std::pair<cv::Mat, cv::Mat>, cv::Mat> >::iterator iter=
gridMaps_.begin(); iter!=
gridMaps_.end(); ++iter)
1529 totalBytes+=
sizeof(int)+
1530 iter->second.first.first.total()*iter->second.first.first.elemSize() +
1531 iter->second.first.second.total()*iter->second.first.second.elemSize() +
1532 iter->second.second.total()*iter->second.second.elemSize();
1535 ROS_INFO(
"MapsManager: cleanup %ld grid maps (~%ld MB)...",
gridMaps_.size(), totalBytes/1048576);
1545 float & gridCellSize)
1554 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)
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_
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
std::map< int, Transform > RTABMAP_EXP radiusPosesFiltering(const std::map< int, Transform > &poses, float radius, float angle, bool keepLatest=true)
float getCellSize() const
cv::Mat getProbMap(float &xMin, float &yMin) const
double uStr2Double(const std::string &str)
ros::Publisher gridMapPub_
rtabmap::OccupancyGrid * occupancyGrid_
int uStrNumCmp(const std::string &a, const std::string &b)
float getUpdateError() const
std::pair< std::string, std::string > ParametersPair
ros::Publisher scanMapPub_
bool isGridFromDepth() const
static bool fullMapToMsg(const OctomapT &octomap, Octomap &msg)
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
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)
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
sensor_msgs::PointCloud2 PointCloud
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledObstacles_
std::map< int, pcl::PointCloud< pcl::PointXYZRGB >::Ptr > groundClouds_
rtabmap::OctoMap * octomap_
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_
float gridCellSize() const
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)
int uStr2Int(const std::string &str)
std::string uNumber2Str(unsigned int number)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Publisher cloudMapPub_
void publish(const boost::shared_ptr< M > &message) const
const std::map< int, Transform > & addedNodes() const
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)
bool getParam(const std::string &key, std::string &s) const
std::map< int, std::pair< std::pair< cv::Mat, cv::Mat >, cv::Mat > > gridMaps_
rtabmap::FlannIndex assembledGroundIndex_
float getMinMapSize() const
void buildKDTreeSingleIndex(const cv::Mat &features, int leafMaxSize=10, bool reorder=true, bool useDistanceL1=false, float rebalancingFactor=2.0f)
ros::Publisher projMapPub_
unsigned int indexedFeatures() const
cv::Mat getMap(float &xMin, float &yMin) const
const RtabmapColorOcTree * octree() const
QMap< QString, QVariant > ParametersMap
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool uStr2Bool(const char *str)
bool uContains(const std::list< V > &list, const V &value)
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const
void setPose(const Transform &pose)
bool hasParam(const std::string &key) const
rtabmap::FlannIndex assembledObstacleIndex_
const std::map< int, Transform > & addedNodes() const
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)
const cv::Point3f & gridViewPoint() const
bool scanEmptyRayTracing_
pcl::PointCloud< pcl::PointXYZRGB >::Ptr subtractFiltering(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, const rtabmap::FlannIndex &substractCloudIndex, float radiusSearch, int minNeighborsInRadius)
std::string getDatabaseVersion() const
void createLocalMap(const Signature &node, cv::Mat &groundCells, cv::Mat &obstacleCells, cv::Mat &emptyCells, cv::Point3f &viewPoint)
void backwardCompatibilityParameters(ros::NodeHandle &pnh, rtabmap::ParametersMap ¶meters) 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)
cv::Mat getGridMap(float &xMin, float &yMin, float &gridCellSize)
ros::Publisher octoMapProj_
cv::Mat createProjectionMap(float &xMin, float &yMin, float &gridCellSize, float minGridSize=0.0f, unsigned int treeDepth=0)
uint32_t getNumSubscribers() const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr assembledGround_
bool hasSubscribers() const
ros::Publisher cloudObstaclesPub_
ros::Publisher gridProbMapPub_
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_