MainWindow: added timing stats on global map creation. Updated util3d::occupancy2DFromLaserScan() and util3d::create2DMap() interfaces (hit/noHit scans in opencv matrix format). Parameter default: Grid/ProjRayTracing=true, Grid/NormalK=true

This commit is contained in:
matlabbe
2017-04-06 12:27:12 -04:00
parent e415dd8504
commit 1d8952867d
13 changed files with 386 additions and 117 deletions
+2 -2
View File
@@ -490,7 +490,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Grid, MinGroundHeight, float, 0.0, "Minimum ground height (0=disabled)."); RTABMAP_PARAM(Grid, MinGroundHeight, float, 0.0, "Minimum ground height (0=disabled).");
RTABMAP_PARAM(Grid, MaxGroundHeight, float, 0.0, uFormat("Maximum ground height (0=disabled). Should be set if \"%s\" is true.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, MaxGroundHeight, float, 0.0, uFormat("Maximum ground height (0=disabled). Should be set if \"%s\" is true.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, MaxGroundAngle, float, 45, uFormat("[%s=true] Maximum angle (degrees) between point's normal to ground's normal to label it as ground. Points with higher angle difference are considered as obstacles.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, MaxGroundAngle, float, 45, uFormat("[%s=true] Maximum angle (degrees) between point's normal to ground's normal to label it as ground. Points with higher angle difference are considered as obstacles.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, NormalK, int, 10, uFormat("[%s=true] K neighbors to compute normals.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, NormalK, int, 20, uFormat("[%s=true] K neighbors to compute normals.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, ClusterRadius, float, 0.1, uFormat("[%s=true] Cluster maximum radius.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, ClusterRadius, float, 0.1, uFormat("[%s=true] Cluster maximum radius.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, MinClusterSize, int, 10, uFormat("[%s=true] Minimum cluster size to project the points.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, MinClusterSize, int, 10, uFormat("[%s=true] Minimum cluster size to project the points.", kGridNormalsSegmentation().c_str()));
RTABMAP_PARAM(Grid, FlatObstacleDetected, bool, true, uFormat("[%s=true] Flat obstacles detected.", kGridNormalsSegmentation().c_str())); RTABMAP_PARAM(Grid, FlatObstacleDetected, bool, true, uFormat("[%s=true] Flat obstacles detected.", kGridNormalsSegmentation().c_str()));
@@ -504,7 +504,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(Grid, NoiseFilteringMinNeighbors, int, 5, "Noise filtering minimum neighbors."); RTABMAP_PARAM(Grid, NoiseFilteringMinNeighbors, int, 5, "Noise filtering minimum neighbors.");
RTABMAP_PARAM(Grid, Scan2dUnknownSpaceFilled, bool, false, "Unknown space filled. Only used with 2D laser scans."); RTABMAP_PARAM(Grid, Scan2dUnknownSpaceFilled, bool, false, "Unknown space filled. Only used with 2D laser scans.");
RTABMAP_PARAM(Grid, Scan2dMaxFilledRange, float, 4.0, "Unknown space filled maximum range. If 0, the laser scan maximum range is used."); RTABMAP_PARAM(Grid, Scan2dMaxFilledRange, float, 4.0, "Unknown space filled maximum range. If 0, the laser scan maximum range is used.");
RTABMAP_PARAM(Grid, ProjRayTracing, bool, false, uFormat("[%s=false] 2D ray tracing is done for each projected obstacle, filling unknown space between the sensor and obstacles.", kGrid3D().c_str())); RTABMAP_PARAM(Grid, ProjRayTracing, bool, true, uFormat("[%s=false] 2D ray tracing is done for each projected obstacle, filling unknown space between the sensor and obstacles.", kGrid3D().c_str()));
public: public:
virtual ~Parameters(); virtual ~Parameters();
+2
View File
@@ -213,6 +213,8 @@ pcl::PointNormal RTABMAP_EXP laserScanToPointNormal(const cv::Mat & laserScan, i
// For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters. // For laserScan of type CV_32FC2, CV_32FC3 and CV_32FC6, rgb is set to default r,g,b parameters.
pcl::PointXYZRGB RTABMAP_EXP laserScanToPointRGB(const cv::Mat & laserScan, int index, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255); pcl::PointXYZRGB RTABMAP_EXP laserScanToPointRGB(const cv::Mat & laserScan, int index, unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
void RTABMAP_EXP getMinMax3D(const cv::Mat & laserScan, cv::Point3f & min, cv::Point3f & max);
void RTABMAP_EXP getMinMax3D(const cv::Mat & laserScan, pcl::PointXYZ & min, pcl::PointXYZ & max);
cv::Point3f RTABMAP_EXP projectDisparityTo3D( cv::Point3f RTABMAP_EXP projectDisparityTo3D(
const cv::Point2f & pt, const cv::Point2f & pt,
+22 -2
View File
@@ -51,13 +51,23 @@ RTABMAP_DEPRECATED(void RTABMAP_EXP occupancy2DFromLaserScan(
bool unknownSpaceFilled = false, bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f), "Use interface with \"viewpoint\" parameter to make sure the ray tracing origin is from the sensor and not the base."); float scanMaxRange = 0.0f), "Use interface with \"viewpoint\" parameter to make sure the ray tracing origin is from the sensor and not the base.");
void RTABMAP_EXP occupancy2DFromLaserScan( RTABMAP_DEPRECATED(void RTABMAP_EXP occupancy2DFromLaserScan(
const cv::Mat & scan, // in /base_link frame const cv::Mat & scan, // in /base_link frame
const cv::Point3f & viewpoint, // /base_link -> /base_scan const cv::Point3f & viewpoint, // /base_link -> /base_scan
cv::Mat & ground, cv::Mat & ground,
cv::Mat & obstacles, cv::Mat & obstacles,
float cellSize, float cellSize,
bool unknownSpaceFilled = false, bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f), "Use interface with scanHit/scanNoHit parameters: scanNoHit set to null matrix has the same functionality than this method.");
void RTABMAP_EXP occupancy2DFromLaserScan(
const cv::Mat & scanHit, // in /base_link frame
const cv::Mat & scanNoHit, // in /base_link frame
const cv::Point3f & viewpoint, // /base_link -> /base_scan
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize,
bool unknownSpaceFilled = false,
float scanMaxRange = 0.0f); // would be set if unknownSpaceFilled=true float scanMaxRange = 0.0f); // would be set if unknownSpaceFilled=true
cv::Mat RTABMAP_EXP create2DMapFromOccupancyLocalMaps( cv::Mat RTABMAP_EXP create2DMapFromOccupancyLocalMaps(
@@ -79,7 +89,7 @@ RTABMAP_DEPRECATED(cv::Mat RTABMAP_EXP create2DMap(const std::map<int, Transform
float minMapSize = 0.0f, float minMapSize = 0.0f,
float scanMaxRange = 0.0f), "Use interface with \"viewpoints\" parameter to make sure the ray tracing origin is from the sensor and not the base."); float scanMaxRange = 0.0f), "Use interface with \"viewpoints\" parameter to make sure the ray tracing origin is from the sensor and not the base.");
cv::Mat RTABMAP_EXP create2DMap(const std::map<int, Transform> & poses, RTABMAP_DEPRECATED(cv::Mat RTABMAP_EXP create2DMap(const std::map<int, Transform> & poses,
const std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > & scans, // in /base_link frame const std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > & scans, // in /base_link frame
const std::map<int, cv::Point3f > & viewpoints, // /base_link -> /base_scan const std::map<int, cv::Point3f > & viewpoints, // /base_link -> /base_scan
float cellSize, float cellSize,
@@ -87,6 +97,16 @@ cv::Mat RTABMAP_EXP create2DMap(const std::map<int, Transform> & poses,
float & xMin, float & xMin,
float & yMin, float & yMin,
float minMapSize = 0.0f, float minMapSize = 0.0f,
float scanMaxRange = 0.0f), "Use interface with cv::Mat scans.");
cv::Mat RTABMAP_EXP create2DMap(const std::map<int, Transform> & poses,
const std::map<int, std::pair<cv::Mat, cv::Mat> > & scans, // <id, <hit, no hit> >, in /base_link frame
const std::map<int, cv::Point3f > & viewpoints, // /base_link -> /base_scan
float cellSize,
bool unknownSpaceFilled,
float & xMin,
float & yMin,
float minMapSize = 0.0f,
float scanMaxRange = 0.0f); // would be set if unknownSpaceFilled=true float scanMaxRange = 0.0f); // would be set if unknownSpaceFilled=true
void RTABMAP_EXP rayTrace(const cv::Point2i & start, void RTABMAP_EXP rayTrace(const cv::Point2i & start,
+4
View File
@@ -208,6 +208,7 @@ void OccupancyGrid::createLocalMap(
util3d::occupancy2DFromLaserScan( util3d::occupancy2DFromLaserScan(
util3d::transformLaserScan(node.sensorData().laserScanRaw(), node.sensorData().laserScanInfo().localTransform()), util3d::transformLaserScan(node.sensorData().laserScanRaw(), node.sensorData().laserScanInfo().localTransform()),
cv::Mat(),
viewPoint, viewPoint,
ground, ground,
obstacles, obstacles,
@@ -345,9 +346,12 @@ void OccupancyGrid::createLocalMap(
if(projRayTracing_) if(projRayTracing_)
{ {
cv::Mat laserScan = obstacles; cv::Mat laserScan = obstacles;
cv::Mat laserScanNoHit = ground;
obstacles = cv::Mat(); obstacles = cv::Mat();
ground = cv::Mat();
util3d::occupancy2DFromLaserScan( util3d::occupancy2DFromLaserScan(
laserScan, laserScan,
laserScanNoHit,
viewPoint, viewPoint,
ground, ground,
obstacles, obstacles,
+1 -1
View File
@@ -107,7 +107,7 @@ void OctoMap::update(const std::map<int, Transform> & poses)
} }
else else
{ {
UWARN("Updated pose for node %d is not found, some points may not be copied.", jter->first); UWARN("Updated pose for node %d is not found, some points may not be copied. Use negative ids to just update cell values without adding new ones.", jter->first);
} }
} }
if(graphChanged) if(graphChanged)
+38
View File
@@ -1424,6 +1424,44 @@ pcl::PointXYZRGB laserScanToPointRGB(const cv::Mat & laserScan, int index, unsig
return output; return output;
} }
void getMinMax3D(const cv::Mat & laserScan, cv::Point3f & min, cv::Point3f & max)
{
UASSERT(!laserScan.empty());
UASSERT(laserScan.type() == CV_32FC2 || laserScan.type() == CV_32FC3 || laserScan.type() == CV_32FC(4) || laserScan.type() == CV_32FC(6));
const float * ptr = laserScan.ptr<float>(0, 0);
min.x = max.x = ptr[0];
min.y = max.y = ptr[1];
min.z = max.z = laserScan.channels() >= 3?ptr[2]:0.0f;
for(int i=1; i<laserScan.cols; ++i)
{
ptr = laserScan.ptr<float>(0, i);
if(ptr[0] < min.x) min.x = ptr[0];
else if(ptr[0] > max.x) max.x = ptr[0];
if(ptr[1] < min.y) min.y = ptr[1];
else if(ptr[1] > max.y) max.y = ptr[1];
if(laserScan.channels() >= 3)
{
if(ptr[2] < min.z) min.z = ptr[2];
else if(ptr[2] > max.z) max.z = ptr[2];
}
}
}
void getMinMax3D(const cv::Mat & laserScan, pcl::PointXYZ & min, pcl::PointXYZ & max)
{
cv::Point3f minCV, maxCV;
getMinMax3D(laserScan, minCV, maxCV);
min.x = minCV.x;
min.y = minCV.y;
min.z = minCV.z;
max.x = maxCV.x;
max.y = maxCV.y;
max.z = maxCV.z;
}
// inspired from ROS image_geometry/src/stereo_camera_model.cpp // inspired from ROS image_geometry/src/stereo_camera_model.cpp
cv::Point3f projectDisparityTo3D( cv::Point3f projectDisparityTo3D(
const cv::Point2f & pt, const cv::Point2f & pt,
+109 -61
View File
@@ -74,7 +74,20 @@ void occupancy2DFromLaserScan(
bool unknownSpaceFilled, bool unknownSpaceFilled,
float scanMaxRange) float scanMaxRange)
{ {
if(scan.empty()) occupancy2DFromLaserScan(scan, cv::Mat(), viewpoint, ground, obstacles, cellSize, unknownSpaceFilled, scanMaxRange);
}
void occupancy2DFromLaserScan(
const cv::Mat & scanHit,
const cv::Mat & scanNoHit,
const cv::Point3f & viewpoint,
cv::Mat & ground,
cv::Mat & obstacles,
float cellSize,
bool unknownSpaceFilled,
float scanMaxRange)
{
if(scanHit.empty() && scanNoHit.empty())
{ {
return; return;
} }
@@ -82,11 +95,8 @@ void occupancy2DFromLaserScan(
std::map<int, Transform> poses; std::map<int, Transform> poses;
poses.insert(std::make_pair(1, Transform::getIdentity())); poses.insert(std::make_pair(1, Transform::getIdentity()));
pcl::PointCloud<pcl::PointXYZ>::Ptr obstaclesCloud = util3d::laserScanToPointCloud(scan); std::map<int, std::pair<cv::Mat, cv::Mat> > scans;
//obstaclesCloud = util3d::voxelize<pcl::PointXYZ>(obstaclesCloud, cellSize); scans.insert(std::make_pair(1, std::make_pair(scanHit, scanNoHit)));
std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr> scans;
scans.insert(std::make_pair(1, obstaclesCloud));
std::map<int, cv::Point3f> viewpoints; std::map<int, cv::Point3f> viewpoints;
viewpoints.insert(std::make_pair(1, viewpoint)); viewpoints.insert(std::make_pair(1, viewpoint));
@@ -94,23 +104,6 @@ void occupancy2DFromLaserScan(
float xMin, yMin; float xMin, yMin;
cv::Mat map8S = create2DMap(poses, scans, viewpoints, cellSize, unknownSpaceFilled, xMin, yMin, 0.0f, scanMaxRange); cv::Mat map8S = create2DMap(poses, scans, viewpoints, cellSize, unknownSpaceFilled, xMin, yMin, 0.0f, scanMaxRange);
// If input ground has already values, add them to map
if(ground.rows == 1 && ground.cols>0 && ground.type() == CV_32FC2)
{
for(int i=0; i<ground.cols; ++i)
{
cv::Vec2f * ptr = ground.ptr<cv::Vec2f>();
// cell
cv::Point2i cell((ptr[i][0]-xMin)/cellSize, (ptr[i][1]-yMin)/cellSize);
if(cell.x>=0 && cell.x<map8S.cols && cell.y >= 0 && cell.y < map8S.rows && map8S.at<char>(cell.y, cell.x) == -1)
{
map8S.at<char>(cell.y, cell.x) = 0;
}
}
}
// find ground cells // find ground cells
std::list<int> groundIndices; std::list<int> groundIndices;
for(unsigned int i=0; i< map8S.total(); ++i) for(unsigned int i=0; i< map8S.total(); ++i)
@@ -139,17 +132,7 @@ void occupancy2DFromLaserScan(
} }
// copy directly obstacles precise positions // copy directly obstacles precise positions
obstacles = cv::Mat(); obstacles = scanHit.clone();
if(obstaclesCloud->size())
{
obstacles = cv::Mat(1, (int)obstaclesCloud->size(), CV_32FC2);
for(unsigned int i=0;i<obstaclesCloud->size(); ++i)
{
cv::Vec2f * ptr = obstacles.ptr<cv::Vec2f>();
ptr[i][0] = obstaclesCloud->at(i).x;
ptr[i][1] = obstaclesCloud->at(i).y;
}
}
} }
/** /**
@@ -510,8 +493,39 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
float scanMaxRange) float scanMaxRange)
{ {
std::map<int, cv::Point3f > viewpoints; std::map<int, cv::Point3f > viewpoints;
std::map<int, std::pair<cv::Mat, cv::Mat> > scansCv;
for(std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::const_iterator iter = scans.begin(); iter!=scans.end(); ++iter)
{
scansCv.insert(std::make_pair(iter->first, std::make_pair(util3d::laserScanFromPointCloud(*iter->second), cv::Mat())));
}
return create2DMap(poses, return create2DMap(poses,
scans, scansCv,
viewpoints,
cellSize,
unknownSpaceFilled,
xMin,
yMin,
minMapSize,
scanMaxRange);
}
cv::Mat create2DMap(const std::map<int, Transform> & poses,
const std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > & scans,
const std::map<int, cv::Point3f > & viewpoints,
float cellSize,
bool unknownSpaceFilled,
float & xMin,
float & yMin,
float minMapSize,
float scanMaxRange)
{
std::map<int, std::pair<cv::Mat, cv::Mat> > scansCv;
for(std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::const_iterator iter = scans.begin(); iter!=scans.end(); ++iter)
{
scansCv.insert(std::make_pair(iter->first, std::make_pair(util3d::laserScanFromPointCloud(*iter->second), cv::Mat())));
}
return create2DMap(poses,
scansCv,
viewpoints, viewpoints,
cellSize, cellSize,
unknownSpaceFilled, unknownSpaceFilled,
@@ -537,7 +551,7 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
* @param scanMaxRange laser scan maximum range, would be set if unknownSpaceFilled=true * @param scanMaxRange laser scan maximum range, would be set if unknownSpaceFilled=true
*/ */
cv::Mat create2DMap(const std::map<int, Transform> & poses, cv::Mat create2DMap(const std::map<int, Transform> & poses,
const std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > & scans, const std::map<int, std::pair<cv::Mat, cv::Mat> > & scans, // <id, <hit, no hit> >
const std::map<int, cv::Point3f > & viewpoints, const std::map<int, cv::Point3f > & viewpoints,
float cellSize, float cellSize,
bool unknownSpaceFilled, bool unknownSpaceFilled,
@@ -547,7 +561,7 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
float scanMaxRange) float scanMaxRange)
{ {
UDEBUG("poses=%d, scans = %d scanMaxRange=%f", poses.size(), scans.size(), scanMaxRange); UDEBUG("poses=%d, scans = %d scanMaxRange=%f", poses.size(), scans.size(), scanMaxRange);
std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr > localScans; std::map<int, std::pair<cv::Mat, cv::Mat> > localScans;
pcl::PointCloud<pcl::PointXYZ> minMax; pcl::PointCloud<pcl::PointXYZ> minMax;
if(minMapSize > 0.0f) if(minMapSize > 0.0f)
@@ -557,15 +571,25 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
} }
for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter) for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
{ {
std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::const_iterator jter=scans.find(iter->first); std::map<int, std::pair<cv::Mat, cv::Mat> >::const_iterator jter=scans.find(iter->first);
if(jter!=scans.end() && jter->second->size()) if(jter!=scans.end() && (jter->second.first.cols || jter->second.second.cols))
{ {
UASSERT(!iter->second.isNull()); UASSERT(!iter->second.isNull());
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = util3d::transformPointCloud(jter->second, iter->second); cv::Mat hit = util3d::transformLaserScan(jter->second.first, iter->second);
cv::Mat noHit = util3d::transformLaserScan(jter->second.second, iter->second);
pcl::PointXYZ min, max; pcl::PointXYZ min, max;
pcl::getMinMax3D(*cloud, min, max); if(!hit.empty())
{
util3d::getMinMax3D(hit, min, max);
minMax.push_back(min); minMax.push_back(min);
minMax.push_back(max); minMax.push_back(max);
}
if(!noHit.empty())
{
util3d::getMinMax3D(noHit, min, max);
minMax.push_back(min);
minMax.push_back(max);
}
minMax.push_back(pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z())); minMax.push_back(pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z()));
std::map<int, cv::Point3f>::const_iterator kter=viewpoints.find(iter->first); std::map<int, cv::Point3f>::const_iterator kter=viewpoints.find(iter->first);
@@ -574,7 +598,7 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
minMax.push_back(pcl::PointXYZ(iter->second.x()+kter->second.x, iter->second.y()+kter->second.y, iter->second.z()+kter->second.z)); minMax.push_back(pcl::PointXYZ(iter->second.x()+kter->second.x, iter->second.y()+kter->second.y, iter->second.z()+kter->second.z));
} }
localScans.insert(std::make_pair(iter->first, cloud)); localScans.insert(std::make_pair(iter->first, std::make_pair(hit, noHit)));
} }
} }
@@ -599,7 +623,7 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
map = cv::Mat::ones((yMax - yMin) / cellSize, (xMax - xMin) / cellSize, CV_8S)*-1; map = cv::Mat::ones((yMax - yMin) / cellSize, (xMax - xMin) / cellSize, CV_8S)*-1;
int j=0; int j=0;
for(std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator iter = localScans.begin(); iter!=localScans.end(); ++iter) for(std::map<int, std::pair<cv::Mat, cv::Mat> >::iterator iter = localScans.begin(); iter!=localScans.end(); ++iter)
{ {
const Transform & pose = poses.at(iter->first); const Transform & pose = poses.at(iter->first);
cv::Point3f viewpoint(0,0,0); cv::Point3f viewpoint(0,0,0);
@@ -609,15 +633,48 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
viewpoint = kter->second; viewpoint = kter->second;
} }
cv::Point2i start(((pose.x()+viewpoint.x)-xMin)/cellSize, ((pose.y()+viewpoint.y)-yMin)/cellSize); cv::Point2i start(((pose.x()+viewpoint.x)-xMin)/cellSize, ((pose.y()+viewpoint.y)-yMin)/cellSize);
for(unsigned int i=0; i<iter->second->size(); ++i)
// Set obstacles first
for(unsigned int i=0; i<iter->second.first.cols; ++i)
{ {
cv::Point2i end((iter->second->points[i].x-xMin)/cellSize, (iter->second->points[i].y-yMin)/cellSize); const float * ptr = iter->second.first.ptr<float>(0, i);
cv::Point2i end((ptr[0]-xMin)/cellSize, (ptr[1]-yMin)/cellSize);
if(end!=start) if(end!=start)
{ {
rayTrace(start, end, map, true); // trace free space
map.at<char>(end.y, end.x) = 100; // obstacle map.at<char>(end.y, end.x) = 100; // obstacle
} }
} }
// ray tracing for hits
for(unsigned int i=0; i<iter->second.first.cols; ++i)
{
const float * ptr = iter->second.first.ptr<float>(0, i);
cv::Point2i end((ptr[0]-xMin)/cellSize, (ptr[1]-yMin)/cellSize);
if(end!=start)
{
if(localScans.size() > 1 || map.at<char>(end.y, end.x) != 0)
{
rayTrace(start, end, map, true); // trace free space
}
}
}
// ray tracing for no hits
for(unsigned int i=0; i<iter->second.second.cols; ++i)
{
const float * ptr = iter->second.second.ptr<float>(0, i);
cv::Point2i end((ptr[0]-xMin)/cellSize, (ptr[1]-yMin)/cellSize);
if(end!=start)
{
if(localScans.size() > 1 || map.at<char>(end.y, end.x) != 0)
{
rayTrace(start, end, map, true); // trace free space
if(map.at<char>(end.y, end.x) == -1)
{
map.at<char>(end.y, end.x) = 0; // empty
}
}
}
}
++j; ++j;
} }
UDEBUG("Ray trace known space=%fs", timer.ticks()); UDEBUG("Ray trace known space=%fs", timer.ticks());
@@ -627,9 +684,9 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
{ {
j=0; j=0;
float a = CV_PI/256.0f; // angle increment float a = CV_PI/256.0f; // angle increment
for(std::map<int, pcl::PointCloud<pcl::PointXYZ>::Ptr >::iterator iter = localScans.begin(); iter!=localScans.end(); ++iter) for(std::map<int, std::pair<cv::Mat, cv::Mat> >::iterator iter = localScans.begin(); iter!=localScans.end(); ++iter)
{ {
if(iter->second->size() > 1) if(iter->second.first.cols > 1)
{ {
if(scanMaxRange > cellSize) if(scanMaxRange > cellSize)
{ {
@@ -650,19 +707,10 @@ cv::Mat create2DMap(const std::map<int, Transform> & poses,
cv::Mat origin(2,1,CV_32F), endFirst(2,1,CV_32F), endLast(2,1,CV_32F); cv::Mat origin(2,1,CV_32F), endFirst(2,1,CV_32F), endLast(2,1,CV_32F);
origin.at<float>(0) = pose.x()+viewpoint.x; origin.at<float>(0) = pose.x()+viewpoint.x;
origin.at<float>(1) = pose.y()+viewpoint.y; origin.at<float>(1) = pose.y()+viewpoint.y;
pcl::PointXYZ ptFirst = iter->second->points[0]; endFirst.at<float>(0) = iter->second.first.ptr<float>(0,0)[0];
pcl::PointXYZ ptLast = iter->second->points[iter->second->points.size()-1]; endFirst.at<float>(1) = iter->second.first.ptr<float>(0,0)[1];
//if(ptFirst.y > ptLast.y) endLast.at<float>(0) = iter->second.first.ptr<float>(0,iter->second.first.cols-1)[0];
//{ endLast.at<float>(1) = iter->second.first.ptr<float>(0,iter->second.first.cols-1)[1];
// swap to iterate counterclockwise
// pcl::PointXYZ tmp = ptLast;
// ptLast = ptFirst;
// ptFirst = tmp;
//}
endFirst.at<float>(0) = ptFirst.x;
endFirst.at<float>(1) = ptFirst.y;
endLast.at<float>(0) = ptLast.x;
endLast.at<float>(1) = ptLast.y;
//UWARN("origin = %f %f", origin.at<float>(0), origin.at<float>(1)); //UWARN("origin = %f %f", origin.at<float>(0), origin.at<float>(1));
//UWARN("endFirst = %f %f", endFirst.at<float>(0), endFirst.at<float>(1)); //UWARN("endFirst = %f %f", endFirst.at<float>(0), endFirst.at<float>(1));
//UWARN("endLast = %f %f", endLast.at<float>(0), endLast.at<float>(1)); //UWARN("endLast = %f %f", endLast.at<float>(0), endLast.at<float>(1));
+2 -1
View File
@@ -241,7 +241,8 @@ private:
const std::map<int, int> & mapIds, const std::map<int, int> & mapIds,
const std::map<int, std::string> & labels, const std::map<int, std::string> & labels,
const std::map<int, Transform> & groundTruths, const std::map<int, Transform> & groundTruths,
bool verboseProgress = false); bool verboseProgress = false,
std::map<std::string, float> * stats = 0);
std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> createAndAddCloudToMap(int nodeId, const Transform & pose, int mapId); std::pair<pcl::PointCloud<pcl::PointXYZRGB>::Ptr, pcl::IndicesPtr> createAndAddCloudToMap(int nodeId, const Transform & pose, int mapId);
void createAndAddScanToMap(int nodeId, const Transform & pose, int mapId); void createAndAddScanToMap(int nodeId, const Transform & pose, int mapId);
void createAndAddFeaturesToMap(int nodeId, const Transform & pose, int mapId); void createAndAddFeaturesToMap(int nodeId, const Transform & pose, int mapId);
@@ -171,6 +171,7 @@ public:
int getOctomapTreeDepth() const; int getOctomapTreeDepth() const;
bool isOctomapGroundAnObstacle() const; bool isOctomapGroundAnObstacle() const;
double getOctomapOccupancyThr() const; double getOctomapOccupancyThr() const;
int getOctomapPointSize() const;
int getCloudDecimation(int index) const; // 0=map, 1=odom int getCloudDecimation(int index) const; // 0=map, 1=odom
double getCloudMaxDepth(int index) const; // 0=map, 1=odom double getCloudMaxDepth(int index) const; // 0=map, 1=odom
double getCloudMinDepth(int index) const; // 0=map, 1=odom double getCloudMinDepth(int index) const; // 0=map, 1=odom
+34 -1
View File
@@ -1721,6 +1721,7 @@ void DatabaseViewer::regenerateLocalMaps()
rtabmap::ProgressDialog progressDialog(this); rtabmap::ProgressDialog progressDialog(this);
progressDialog.setMaximumSteps(ids_.size()); progressDialog.setMaximumSteps(ids_.size());
progressDialog.show(); progressDialog.show();
progressDialog.setCancelButtonVisible(true);
UPlot * plot = new UPlot(this); UPlot * plot = new UPlot(this);
plot->setWindowFlags(Qt::Window); plot->setWindowFlags(Qt::Window);
@@ -1730,10 +1731,19 @@ void DatabaseViewer::regenerateLocalMaps()
UPlotCurve * gridCreationCurve = plot->addCurve("Grid Creation"); UPlotCurve * gridCreationCurve = plot->addCurve("Grid Creation");
plot->show(); plot->show();
UPlot * plotCells = new UPlot(this);
plotCells->setWindowFlags(Qt::Window);
plotCells->setWindowTitle("Occupancy Cells");
plotCells->setAttribute(Qt::WA_DeleteOnClose);
UPlotCurve * totalCurve = plotCells->addCurve("Total");
UPlotCurve * groundCurve = plotCells->addCurve("Empty");
UPlotCurve * obstaclesCurve = plotCells->addCurve("Occupied");
plotCells->show();
double decompressionTime = 0; double decompressionTime = 0;
double gridCreationTime = 0; double gridCreationTime = 0;
for(int i =0; i<ids_.size(); ++i) for(int i =0; i<ids_.size() && !progressDialog.isCanceled(); ++i)
{ {
UTimer timer; UTimer timer;
SensorData data; SensorData data;
@@ -1758,6 +1768,10 @@ void DatabaseViewer::regenerateLocalMaps()
uInsert(generatedLocalMaps_, std::make_pair(data.id(), std::make_pair(ground, obstacles))); uInsert(generatedLocalMaps_, std::make_pair(data.id(), std::make_pair(ground, obstacles)));
uInsert(generatedLocalMapsInfo_, std::make_pair(data.id(), std::make_pair(grid.getCellSize(), viewpoint))); uInsert(generatedLocalMapsInfo_, std::make_pair(data.id(), std::make_pair(grid.getCellSize(), viewpoint)));
msg = QString("Generated local occupancy grid map %1/%2").arg(i+1).arg((int)ids_.size()); msg = QString("Generated local occupancy grid map %1/%2").arg(i+1).arg((int)ids_.size());
totalCurve->addValue(ids_.at(i), obstacles.cols+ground.cols);
groundCurve->addValue(ids_.at(i), ground.cols);
obstaclesCurve->addValue(ids_.at(i), obstacles.cols);
} }
progressDialog.appendText(msg); progressDialog.appendText(msg);
@@ -1772,8 +1786,17 @@ void DatabaseViewer::regenerateLocalMaps()
} }
} }
progressDialog.setValue(progressDialog.maximumSteps()); progressDialog.setValue(progressDialog.maximumSteps());
if(graphes_.size())
{
update3dView();
sliderIterationsValueChanged((int)graphes_.size()-1);
}
else
{
updateGrid(); updateGrid();
} }
}
void DatabaseViewer::regenerateCurrentLocalMaps() void DatabaseViewer::regenerateCurrentLocalMaps()
{ {
@@ -1826,8 +1849,17 @@ void DatabaseViewer::regenerateCurrentLocalMaps()
QApplication::processEvents(); QApplication::processEvents();
} }
progressDialog.setValue(progressDialog.maximumSteps()); progressDialog.setValue(progressDialog.maximumSteps());
if(graphes_.size())
{
update3dView();
sliderIterationsValueChanged((int)graphes_.size()-1);
}
else
{
updateGrid(); updateGrid();
} }
}
void DatabaseViewer::view3DMap() void DatabaseViewer::view3DMap()
{ {
@@ -3967,6 +3999,7 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
Qt::red); Qt::red);
occupancyGridViewer_->setCloudPointSize("obstaclesXYZ", 5); occupancyGridViewer_->setCloudPointSize("obstaclesXYZ", 5);
} }
occupancyGridViewer_->update();
} }
} }
} }
+95 -11
View File
@@ -586,6 +586,13 @@ MainWindow::MainWindow(PreferencesDialog * prefDialog, QWidget * parent) :
_ui->statsToolBox->updateStat("GUI/Refresh odom/ms", false); _ui->statsToolBox->updateStat("GUI/Refresh odom/ms", false);
_ui->statsToolBox->updateStat("GUI/RGB-D cloud/ms", false); _ui->statsToolBox->updateStat("GUI/RGB-D cloud/ms", false);
_ui->statsToolBox->updateStat("GUI/Graph Update/ms", false);
#ifdef RTABMAP_OCTOMAP
_ui->statsToolBox->updateStat("GUI/Octomap Update/ms", false);
_ui->statsToolBox->updateStat("GUI/Octomap Rendering/ms", false);
#endif
_ui->statsToolBox->updateStat("GUI/Grid Update/ms", false);
_ui->statsToolBox->updateStat("GUI/Grid Rendering/ms", false);
_ui->statsToolBox->updateStat("GUI/Refresh stats/ms", false); _ui->statsToolBox->updateStat("GUI/Refresh stats/ms", false);
_ui->statsToolBox->updateStat("GUI/Cache Data Size/MB", false); _ui->statsToolBox->updateStat("GUI/Cache Data Size/MB", false);
_ui->statsToolBox->updateStat("GUI/Cache Clouds Size/MB", false); _ui->statsToolBox->updateStat("GUI/Cache Clouds Size/MB", false);
@@ -1429,14 +1436,20 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
signature = stat.getSignatures().at(stat.refImageId()); signature = stat.getSignatures().at(stat.refImageId());
signature.sensorData().uncompressData(); // make sure data are uncompressed signature.sensorData().uncompressData(); // make sure data are uncompressed
if(!smallMovement && if( uStr2Bool(_preferencesDialog->getParameter(Parameters::kMemIncrementalMemory())) &&
uStr2Bool(_preferencesDialog->getParameter(Parameters::kMemIncrementalMemory())) &&
signature.getWeight()>=0) // ignore intermediate nodes for the cache signature.getWeight()>=0) // ignore intermediate nodes for the cache
{
if(smallMovement)
{
_cachedSignatures.insert(-1, signature); // negative means temporary
}
else
{ {
_cachedSignatures.insert(signature.id(), signature); _cachedSignatures.insert(signature.id(), signature);
_cachedMemoryUsage += signature.sensorData().getMemoryUsed(); _cachedMemoryUsage += signature.sensorData().getMemoryUsed();
} }
} }
}
// For intermediate empty nodes, keep latest image shown // For intermediate empty nodes, keep latest image shown
if(!signature.sensorData().imageRaw().empty() || signature.getWords().size()) if(!signature.sensorData().imageRaw().empty() || signature.getWords().size())
@@ -1675,8 +1688,6 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
//====================== //======================
// RGB-D Mapping stuff // RGB-D Mapping stuff
//====================== //======================
UTimer timerVis;
// update clouds // update clouds
if(stat.poses().size()) if(stat.poses().size())
{ {
@@ -1725,19 +1736,40 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
} }
} }
if(_cachedSignatures.contains(-1))
{
if(poses.find(stat.refImageId())!=poses.end())
{
poses.insert(std::make_pair(-1, poses.at(stat.refImageId())));
poses.erase(stat.refImageId());
}
if(groundTruth.find(stat.refImageId())!=groundTruth.end())
{
groundTruth.insert(std::make_pair(-1, groundTruth.at(stat.refImageId())));
groundTruth.erase(stat.refImageId());
}
}
std::map<std::string, float> updateCloudSats;
updateMapCloud( updateMapCloud(
poses, poses,
stat.constraints(), stat.constraints(),
mapIds, mapIds,
labels, labels,
groundTruth); groundTruth,
false,
&updateCloudSats);
_odometryReceived = false; _odometryReceived = false;
_odometryCorrection = groundTruthOffset * stat.mapCorrection(); _odometryCorrection = groundTruthOffset * stat.mapCorrection();
UDEBUG("time= %d ms", time.restart()); UDEBUG("time= %d ms", time.restart());
_ui->statsToolBox->updateStat("GUI/RGB-D cloud/ms", _preferencesDialog->isTimeUsedInFigures()?stat.stamp()-_firstStamp:stat.refImageId(), int(timerVis.elapsed()*1000.0f), _preferencesDialog->isCacheSavedInFigures());
for(std::map<std::string, float>::iterator iter=updateCloudSats.begin(); iter!=updateCloudSats.end(); ++iter)
{
_ui->statsToolBox->updateStat(iter->first.c_str(), _preferencesDialog->isTimeUsedInFigures()?stat.stamp()-_firstStamp:stat.refImageId(), int(iter->second), _preferencesDialog->isCacheSavedInFigures());
}
// loop closure view // loop closure view
if((stat.loopClosureId() > 0 || stat.proximityDetectionId() > 0) && if((stat.loopClosureId() > 0 || stat.proximityDetectionId() > 0) &&
@@ -1783,6 +1815,8 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
} }
UDEBUG(""); UDEBUG("");
_cachedSignatures.remove(-1); // remove tmp negative ids
// keep only compressed data in cache // keep only compressed data in cache
if(_cachedSignatures.contains(stat.refImageId())) if(_cachedSignatures.contains(stat.refImageId()))
{ {
@@ -1796,7 +1830,6 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
_cachedMemoryUsage += s.sensorData().getMemoryUsed(); _cachedMemoryUsage += s.sensorData().getMemoryUsed();
} }
UDEBUG(""); UDEBUG("");
} }
else if(!stat.extended() && stat.loopClosureId()>0) else if(!stat.extended() && stat.loopClosureId()>0)
@@ -1843,17 +1876,21 @@ void MainWindow::updateMapCloud(
const std::map<int, int> & mapIdsIn, const std::map<int, int> & mapIdsIn,
const std::map<int, std::string> & labels, const std::map<int, std::string> & labels,
const std::map<int, Transform> & groundTruths, // ground truth should contain only valid transforms const std::map<int, Transform> & groundTruths, // ground truth should contain only valid transforms
bool verboseProgress) bool verboseProgress,
std::map<std::string, float> * stats)
{ {
UTimer timer;
UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d", UDEBUG("posesIn=%d constraints=%d mapIdsIn=%d labelsIn=%d",
(int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size()); (int)posesIn.size(), (int)constraints.size(), (int)mapIdsIn.size(), (int)labels.size());
if(posesIn.size()) if(posesIn.size())
{ {
_currentPosesMap = posesIn; _currentPosesMap = posesIn;
_currentPosesMap.erase(-1); // don't keep -1 if it is there
_currentLinksMap = constraints; _currentLinksMap = constraints;
_currentMapIds = mapIdsIn; _currentMapIds = mapIdsIn;
_currentLabels = labels; _currentLabels = labels;
_currentGTPosesMap = groundTruths; _currentGTPosesMap = groundTruths;
_currentGTPosesMap.erase(-1);
if(_state != kMonitoring && _state != kDetecting) if(_state != kMonitoring && _state != kDetecting)
{ {
_ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1); _ui->actionPost_processing->setEnabled(_cachedSignatures.size() >= 2 && _currentPosesMap.size() >= 2 && _currentLinksMap.size() >= 1);
@@ -1902,12 +1939,12 @@ void MainWindow::updateMapCloud(
} }
_ui->widget_mapVisibility->setMap(posesIn, posesMask); _ui->widget_mapVisibility->setMap(posesIn, posesMask);
if(_currentGTPosesMap.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked()) if(groundTruths.size() && _ui->actionAnchor_clouds_to_ground_truth->isChecked())
{ {
for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter) for(std::map<int, Transform>::iterator iter = poses.begin(); iter!=poses.end(); ++iter)
{ {
std::map<int, Transform>::iterator gtIter = _currentGTPosesMap.find(iter->first); std::map<int, Transform>::const_iterator gtIter = groundTruths.find(iter->first);
if(gtIter!=_currentGTPosesMap.end()) if(gtIter!=groundTruths.end())
{ {
iter->second = gtIter->second; iter->second = gtIter->second;
} }
@@ -1932,6 +1969,12 @@ void MainWindow::updateMapCloud(
{ {
std::string cloudName = uFormat("cloud%d", iter->first); std::string cloudName = uFormat("cloud%d", iter->first);
if(iter->first < 0)
{
viewerClouds.remove(cloudName);
_cloudViewer->removeCloud(cloudName);
}
// 3d point cloud // 3d point cloud
bool update3dCloud = _cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0); bool update3dCloud = _cloudViewer->isVisible() && _preferencesDialog->isCloudsShown(0);
if(update3dCloud) if(update3dCloud)
@@ -1971,6 +2014,11 @@ void MainWindow::updateMapCloud(
// 2d point cloud // 2d point cloud
std::string scanName = uFormat("scan%d", iter->first); std::string scanName = uFormat("scan%d", iter->first);
if(iter->first < 0)
{
viewerClouds.remove(scanName);
_cloudViewer->removeCloud(scanName);
}
if(_cloudViewer->isVisible() && _preferencesDialog->isScansShown(0)) if(_cloudViewer->isVisible() && _preferencesDialog->isScansShown(0))
{ {
if(viewerClouds.contains(scanName)) if(viewerClouds.contains(scanName))
@@ -2004,6 +2052,12 @@ void MainWindow::updateMapCloud(
} }
// occupancy grids // occupancy grids
if(iter->first < 0)
{
_gridLocalMaps.erase(iter->first);
_gridViewPoints.erase(iter->first);
}
bool updateGridMap = bool updateGridMap =
((_ui->graphicsView_graphView->isVisible() && _ui->graphicsView_graphView->isGridMapVisible()) || ((_ui->graphicsView_graphView->isVisible() && _ui->graphicsView_graphView->isGridMapVisible()) ||
(_cloudViewer->isVisible() && _preferencesDialog->getGridMapShown())) && (_cloudViewer->isVisible() && _preferencesDialog->getGridMapShown())) &&
@@ -2061,6 +2115,11 @@ void MainWindow::updateMapCloud(
// 3d features // 3d features
std::string featuresName = uFormat("features%d", iter->first); std::string featuresName = uFormat("features%d", iter->first);
if(iter->first < 0)
{
viewerClouds.remove(featuresName);
_cloudViewer->removeCloud(featuresName);
}
if(_cloudViewer->isVisible() && _preferencesDialog->isFeaturesShown(0)) if(_cloudViewer->isVisible() && _preferencesDialog->isFeaturesShown(0))
{ {
if(viewerClouds.contains(featuresName)) if(viewerClouds.contains(featuresName))
@@ -2129,6 +2188,10 @@ void MainWindow::updateMapCloud(
} }
UDEBUG(""); UDEBUG("");
if(stats)
{
stats->insert(std::make_pair("GUI/RGB-D cloud/ms", (float)timer.restart()*1000.0f));
}
// update 3D graphes (show all poses) // update 3D graphes (show all poses)
_cloudViewer->removeAllGraphs(); _cloudViewer->removeAllGraphs();
@@ -2268,6 +2331,10 @@ void MainWindow::updateMapCloud(
} }
UDEBUG(""); UDEBUG("");
if(stats)
{
stats->insert(std::make_pair("GUI/Graph Update/ms", (float)timer.restart()*1000.0f));
}
#ifdef RTABMAP_OCTOMAP #ifdef RTABMAP_OCTOMAP
_cloudViewer->removeOctomap(); _cloudViewer->removeOctomap();
@@ -2279,6 +2346,10 @@ void MainWindow::updateMapCloud(
_octomap->update(poses); _octomap->update(poses);
UINFO("Octomap update time = %fs", time.ticks()); UINFO("Octomap update time = %fs", time.ticks());
} }
if(stats)
{
stats->insert(std::make_pair("GUI/Octomap Update/ms", (float)timer.restart()*1000.0f));
}
if(_preferencesDialog->isOctomapShown()) if(_preferencesDialog->isOctomapShown())
{ {
UDEBUG(""); UDEBUG("");
@@ -2294,11 +2365,16 @@ void MainWindow::updateMapCloud(
if(obstacles->size()) if(obstacles->size())
{ {
_cloudViewer->addCloud("octomap_cloud", cloud); _cloudViewer->addCloud("octomap_cloud", cloud);
_cloudViewer->setCloudPointSize("octomap_cloud", _preferencesDialog->getOctomapPointSize());
} }
} }
UINFO("Octomap show 3d map time = %fs", time.ticks()); UINFO("Octomap show 3d map time = %fs", time.ticks());
} }
UDEBUG(""); UDEBUG("");
if(stats)
{
stats->insert(std::make_pair("GUI/Octomap Rendering/ms", (float)timer.restart()*1000.0f));
}
#endif #endif
// Update occupancy grid map in 3D map view and graph view // Update occupancy grid map in 3D map view and graph view
@@ -2326,6 +2402,10 @@ void MainWindow::updateMapCloud(
if(_preferencesDialog->isGridMapIncremental()) if(_preferencesDialog->isGridMapIncremental())
{ {
_occupancyGrid->update(poses, 0, _preferencesDialog->getGridMapFootprintRadius()); _occupancyGrid->update(poses, 0, _preferencesDialog->getGridMapFootprintRadius());
if(stats)
{
stats->insert(std::make_pair("GUI/Grid Update/ms", (float)timer.restart()*1000.0f));
}
map8S = _occupancyGrid->getMap(xMin, yMin); map8S = _occupancyGrid->getMap(xMin, yMin);
} }
else else
@@ -2359,6 +2439,10 @@ void MainWindow::updateMapCloud(
_ui->graphicsView_graphView->update(); _ui->graphicsView_graphView->update();
UDEBUG(""); UDEBUG("");
if(stats)
{
stats->insert(std::make_pair("GUI/Grid Rendering/ms", (float)timer.restart()*1000.0f));
}
if(!_preferencesDialog->getGridMapShown()) if(!_preferencesDialog->getGridMapShown())
{ {
+9
View File
@@ -412,6 +412,8 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->checkBox_octomap_2dgrid, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->checkBox_octomap_2dgrid, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_octomap_show3dMap, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->checkBox_octomap_show3dMap, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->checkBox_octomap_cubeRendering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->checkBox_octomap_cubeRendering, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->spinBox_octomap_pointSize, SIGNAL(valueChanged(int)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_octomap_occupancyThr, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->groupBox_organized, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->groupBox_organized, SIGNAL(toggled(bool)), this, SLOT(makeObsoleteCloudRenderingPanel()));
connect(_ui->doubleSpinBox_mesh_angleTolerance, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel())); connect(_ui->doubleSpinBox_mesh_angleTolerance, SIGNAL(valueChanged(double)), this, SLOT(makeObsoleteCloudRenderingPanel()));
@@ -1313,6 +1315,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->checkBox_octomap_2dgrid->setChecked(true); _ui->checkBox_octomap_2dgrid->setChecked(true);
_ui->checkBox_octomap_show3dMap->setChecked(true); _ui->checkBox_octomap_show3dMap->setChecked(true);
_ui->checkBox_octomap_cubeRendering->setChecked(true); _ui->checkBox_octomap_cubeRendering->setChecked(true);
_ui->spinBox_octomap_pointSize->setValue(5);
_ui->doubleSpinBox_octomap_occupancyThr->setValue(0.5); _ui->doubleSpinBox_octomap_occupancyThr->setValue(0.5);
} }
else if(groupBox->objectName() == _ui->groupBox_logging1->objectName()) else if(groupBox->objectName() == _ui->groupBox_logging1->objectName())
@@ -1692,6 +1695,7 @@ void PreferencesDialog::readGuiSettings(const QString & filePath)
_ui->checkBox_octomap_show3dMap->setChecked(settings.value("octomap_3dmap", _ui->checkBox_octomap_show3dMap->isChecked()).toBool()); _ui->checkBox_octomap_show3dMap->setChecked(settings.value("octomap_3dmap", _ui->checkBox_octomap_show3dMap->isChecked()).toBool());
_ui->checkBox_octomap_cubeRendering->setChecked(settings.value("octomap_cube", _ui->checkBox_octomap_cubeRendering->isChecked()).toBool()); _ui->checkBox_octomap_cubeRendering->setChecked(settings.value("octomap_cube", _ui->checkBox_octomap_cubeRendering->isChecked()).toBool());
_ui->doubleSpinBox_octomap_occupancyThr->setValue(settings.value("octomap_occupancy_thr", _ui->doubleSpinBox_octomap_occupancyThr->value()).toDouble()); _ui->doubleSpinBox_octomap_occupancyThr->setValue(settings.value("octomap_occupancy_thr", _ui->doubleSpinBox_octomap_occupancyThr->value()).toDouble());
_ui->spinBox_octomap_pointSize->setValue(settings.value("octomap_point_size", _ui->spinBox_octomap_pointSize->value()).toInt());
_ui->groupBox_organized->setChecked(settings.value("meshing", _ui->groupBox_organized->isChecked()).toBool()); _ui->groupBox_organized->setChecked(settings.value("meshing", _ui->groupBox_organized->isChecked()).toBool());
_ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("meshing_angle", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble()); _ui->doubleSpinBox_mesh_angleTolerance->setValue(settings.value("meshing_angle", _ui->doubleSpinBox_mesh_angleTolerance->value()).toDouble());
@@ -2077,6 +2081,7 @@ void PreferencesDialog::writeGuiSettings(const QString & filePath) const
settings.setValue("octomap_3dmap", _ui->checkBox_octomap_show3dMap->isChecked()); settings.setValue("octomap_3dmap", _ui->checkBox_octomap_show3dMap->isChecked());
settings.setValue("octomap_cube", _ui->checkBox_octomap_cubeRendering->isChecked()); settings.setValue("octomap_cube", _ui->checkBox_octomap_cubeRendering->isChecked());
settings.setValue("octomap_occupancy_thr", _ui->doubleSpinBox_octomap_occupancyThr->value()); settings.setValue("octomap_occupancy_thr", _ui->doubleSpinBox_octomap_occupancyThr->value());
settings.setValue("octomap_point_size", _ui->spinBox_octomap_pointSize->value());
settings.setValue("meshing", _ui->groupBox_organized->isChecked()); settings.setValue("meshing", _ui->groupBox_organized->isChecked());
@@ -4067,6 +4072,10 @@ double PreferencesDialog::getOctomapOccupancyThr() const
{ {
return _ui->doubleSpinBox_octomap_occupancyThr->value(); return _ui->doubleSpinBox_octomap_occupancyThr->value();
} }
int PreferencesDialog::getOctomapPointSize() const
{
return _ui->spinBox_octomap_pointSize->value();
}
double PreferencesDialog::getVoxel() const double PreferencesDialog::getVoxel() const
{ {
+61 -32
View File
@@ -86,7 +86,7 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>15</number> <number>3</number>
</property> </property>
<widget class="QWidget" name="page_22"> <widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1"> <layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -1958,7 +1958,33 @@ Show a yellow background when the number of odometry inliers goes under this thr
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QGridLayout" name="gridLayout_72" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_72" columnstretch="0,1">
<item row="2" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_octomap_treeDepth_4">
<property name="text">
<string>Occupancy threshold.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_octomap_treeDepth_5">
<property name="text">
<string>Cube rendering. Disable to show as a point cloud (a lot less GPU power required).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_octomap_treeDepth"> <widget class="QLabel" name="label_octomap_treeDepth">
<property name="text"> <property name="text">
<string>Octomap maximum tree depth (max 16). The highest depth means the smallest resolution of the map (cell size). At smallest resolution the octomap shows RGB colors. Other resolutions produce z-axis gradient colored octomap.</string> <string>Octomap maximum tree depth (max 16). The highest depth means the smallest resolution of the map (cell size). At smallest resolution the octomap shows RGB colors. Other resolutions produce z-axis gradient colored octomap.</string>
@@ -1971,7 +1997,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QSpinBox" name="spinBox_octomap_treeDepth"> <widget class="QSpinBox" name="spinBox_octomap_treeDepth">
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@@ -1984,7 +2010,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="checkBox_octomap_2dgrid"> <widget class="QCheckBox" name="checkBox_octomap_2dgrid">
<property name="text"> <property name="text">
<string/> <string/>
@@ -1994,7 +2020,7 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="1">
<widget class="QLabel" name="label_octomap_treeDepth_2"> <widget class="QLabel" name="label_octomap_treeDepth_2">
<property name="text"> <property name="text">
<string>Show 2D occupancy grid map from OctoMap projection.</string> <string>Show 2D occupancy grid map from OctoMap projection.</string>
@@ -2030,42 +2056,19 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="5" column="0">
<widget class="QLabel" name="label_octomap_treeDepth_4">
<property name="text">
<string>Occupancy threshold.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_octomap_occupancyThr"> <widget class="QDoubleSpinBox" name="doubleSpinBox_octomap_occupancyThr">
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value"> <property name="value">
<double>0.500000000000000</double> <double>0.500000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLabel" name="label_octomap_treeDepth_5">
<property name="text">
<string>Cube rendering. Disable to show as a point cloud (a lot less GPU power required).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="checkBox_octomap_cubeRendering"> <widget class="QCheckBox" name="checkBox_octomap_cubeRendering">
<property name="text"> <property name="text">
@@ -2076,6 +2079,32 @@ Show a yellow background when the number of odometry inliers goes under this thr
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QLabel" name="label_octomap_treeDepth_6">
<property name="text">
<string>Point size. When cube rendering is disabled.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="spinBox_octomap_pointSize">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>