mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 17:40:23 +08:00
OccupancyGrid: added Grid/Footprint*** parameters, templated segmentCloud() function, added Grid/ClusterRadius parameter. Parameters: fixed getDefaultParameters(group) function to correctly compare groups.
This commit is contained in:
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
|
#include "rtabmap/core/RtabmapExp.h" // DLL export/import defines
|
||||||
|
|
||||||
|
#include <pcl/point_cloud.h>
|
||||||
|
#include <pcl/pcl_base.h>
|
||||||
#include <rtabmap/core/Parameters.h>
|
#include <rtabmap/core/Parameters.h>
|
||||||
#include <rtabmap/core/Signature.h>
|
#include <rtabmap/core/Signature.h>
|
||||||
|
|
||||||
@@ -42,7 +44,22 @@ public:
|
|||||||
void parseParameters(const ParametersMap & parameters);
|
void parseParameters(const ParametersMap & parameters);
|
||||||
void setCellSize(float cellSize);
|
void setCellSize(float cellSize);
|
||||||
float getCellSize() const {return cellSize_;}
|
float getCellSize() const {return cellSize_;}
|
||||||
void createLocalMap(const Signature & node, cv::Mat & ground, cv::Mat & obstacles, cv::Point3f & viewPoint) const;
|
|
||||||
|
template<typename PointT>
|
||||||
|
typename pcl::PointCloud<PointT>::Ptr segmentCloud(
|
||||||
|
const typename pcl::PointCloud<PointT>::Ptr & cloud,
|
||||||
|
const pcl::IndicesPtr & indices,
|
||||||
|
const Transform & pose,
|
||||||
|
const cv::Point3f & viewPoint,
|
||||||
|
pcl::IndicesPtr & groundIndices, // output cloud indices
|
||||||
|
pcl::IndicesPtr & obstaclesIndices, // output cloud indices
|
||||||
|
pcl::IndicesPtr * flatObstacles = 0) const; // output cloud indices
|
||||||
|
|
||||||
|
void createLocalMap(
|
||||||
|
const Signature & node,
|
||||||
|
cv::Mat & ground,
|
||||||
|
cv::Mat & obstacles,
|
||||||
|
cv::Point3f & viewPoint) const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void addToCache(
|
void addToCache(
|
||||||
@@ -63,6 +80,9 @@ private:
|
|||||||
float cloudMaxDepth_;
|
float cloudMaxDepth_;
|
||||||
float cloudMinDepth_;
|
float cloudMinDepth_;
|
||||||
std::vector<float> roiRatios_;
|
std::vector<float> roiRatios_;
|
||||||
|
float footprintLength_;
|
||||||
|
float footprintWidth_;
|
||||||
|
float footprintHeight_;
|
||||||
int scanDecimation_;
|
int scanDecimation_;
|
||||||
float cellSize_;
|
float cellSize_;
|
||||||
bool occupancyFromCloud_;
|
bool occupancyFromCloud_;
|
||||||
@@ -70,6 +90,7 @@ private:
|
|||||||
float maxObstacleHeight_;
|
float maxObstacleHeight_;
|
||||||
int normalKSearch_;
|
int normalKSearch_;
|
||||||
float maxGroundAngle_;
|
float maxGroundAngle_;
|
||||||
|
float clusterRadius_;
|
||||||
int minClusterSize_;
|
int minClusterSize_;
|
||||||
bool flatObstaclesDetected_;
|
bool flatObstaclesDetected_;
|
||||||
float minGroundHeight_;
|
float minGroundHeight_;
|
||||||
@@ -93,4 +114,6 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <rtabmap/core/impl/OccupancyGrid.hpp>
|
||||||
|
|
||||||
#endif /* CORELIB_SRC_OCCUPANCYGRID_H_ */
|
#endif /* CORELIB_SRC_OCCUPANCYGRID_H_ */
|
||||||
|
|||||||
@@ -467,6 +467,9 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(Grid, DepthMin, float, 0.0, uFormat("[%s=true] Minimum cloud's depth from sensor.", kGridDepthDecimation().c_str()));
|
RTABMAP_PARAM(Grid, DepthMin, float, 0.0, uFormat("[%s=true] Minimum cloud's depth from sensor.", kGridDepthDecimation().c_str()));
|
||||||
RTABMAP_PARAM(Grid, DepthMax, float, 4.0, uFormat("[%s=true] Maximum cloud's depth from sensor. 0=inf.", kGridDepthDecimation().c_str()));
|
RTABMAP_PARAM(Grid, DepthMax, float, 4.0, uFormat("[%s=true] Maximum cloud's depth from sensor. 0=inf.", kGridDepthDecimation().c_str()));
|
||||||
RTABMAP_PARAM_STR(Grid, DepthRoiRatios, "0.0 0.0 0.0 0.0", uFormat("[%s=true] Region of interest ratios [left, right, top, bottom].", kGridDepthDecimation().c_str()));
|
RTABMAP_PARAM_STR(Grid, DepthRoiRatios, "0.0 0.0 0.0 0.0", uFormat("[%s=true] Region of interest ratios [left, right, top, bottom].", kGridDepthDecimation().c_str()));
|
||||||
|
RTABMAP_PARAM(Grid, FootprintLength, float, 0.0, "Footprint length used to filter points over the footprint of the robot.");
|
||||||
|
RTABMAP_PARAM(Grid, FootprintWidth, float, 0.0, "Footprint width used to filter points over the footprint of the robot. Footprint length should be set.");
|
||||||
|
RTABMAP_PARAM(Grid, FootprintHeight, float, 0.0, "Footprint height used to filter points over the footprint of the robot. Footprint length and width should be set.");
|
||||||
RTABMAP_PARAM(Grid, ScanDecimation, int, 1, uFormat("[%s=false] Decimation of the laser scan before creating cloud.", kGridDepthDecimation().c_str()));
|
RTABMAP_PARAM(Grid, ScanDecimation, int, 1, uFormat("[%s=false] Decimation of the laser scan before creating cloud.", kGridDepthDecimation().c_str()));
|
||||||
RTABMAP_PARAM(Grid, CellSize, float, 0.05, "Resolution of the occupancy grid.");
|
RTABMAP_PARAM(Grid, CellSize, float, 0.05, "Resolution of the occupancy grid.");
|
||||||
RTABMAP_PARAM(Grid, MapFrameProjection, bool, false, "Projection in map frame. On a 3D terrain and a fixed local camera transform (the cloud is created relative to ground), you may want to disable this to do the projection in robot frame instead.");
|
RTABMAP_PARAM(Grid, MapFrameProjection, bool, false, "Projection in map frame. On a 3D terrain and a fixed local camera transform (the cloud is created relative to ground), you may want to disable this to do the projection in robot frame instead.");
|
||||||
@@ -475,8 +478,9 @@ 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, 10, uFormat("[%s=true] K neighbors to compute normals.", kGridNormalsSegmentation().c_str()));
|
||||||
RTABMAP_PARAM(Grid, MinClusterSize, int, 10, uFormat("[%s=true] Minimum cluster size to project the points. The distance between clusters is defined by 2*\"%s\".", kGridNormalsSegmentation().c_str(), kGridCellSize().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, 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()));
|
||||||
#ifdef RTABMAP_OCTOMAP
|
#ifdef RTABMAP_OCTOMAP
|
||||||
RTABMAP_PARAM(Grid, 3D, bool, true, uFormat("A 3D occupancy grid is required if you want an Octomap. Set to false if you want only a 2D map, the cloud will be projected on xy plane. A 2D map can be still generated if checked, but it requires more memory and time to generate it. Ignored if laser scan is 2D and \"%s\" is false.", kGridFromDepth().c_str()));
|
RTABMAP_PARAM(Grid, 3D, bool, true, uFormat("A 3D occupancy grid is required if you want an Octomap. Set to false if you want only a 2D map, the cloud will be projected on xy plane. A 2D map can be still generated if checked, but it requires more memory and time to generate it. Ignored if laser scan is 2D and \"%s\" is false.", kGridFromDepth().c_str()));
|
||||||
|
|||||||
162
corelib/include/rtabmap/core/impl/OccupancyGrid.hpp
Normal file
162
corelib/include/rtabmap/core/impl/OccupancyGrid.hpp
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Universite de Sherbrooke nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CORELIB_INCLUDE_RTABMAP_CORE_IMPL_OCCUPANCYGRID_HPP_
|
||||||
|
#define CORELIB_INCLUDE_RTABMAP_CORE_IMPL_OCCUPANCYGRID_HPP_
|
||||||
|
|
||||||
|
#include <rtabmap/core/util3d_mapping.h>
|
||||||
|
#include <rtabmap/core/util3d_transforms.h>
|
||||||
|
#include <rtabmap/utilite/ULogger.h>
|
||||||
|
|
||||||
|
namespace rtabmap {
|
||||||
|
|
||||||
|
template<typename PointT>
|
||||||
|
typename pcl::PointCloud<PointT>::Ptr OccupancyGrid::segmentCloud(
|
||||||
|
const typename pcl::PointCloud<PointT>::Ptr & cloudIn,
|
||||||
|
const pcl::IndicesPtr & indicesIn,
|
||||||
|
const Transform & pose,
|
||||||
|
const cv::Point3f & viewPoint,
|
||||||
|
pcl::IndicesPtr & groundIndices,
|
||||||
|
pcl::IndicesPtr & obstaclesIndices,
|
||||||
|
pcl::IndicesPtr * flatObstacles) const
|
||||||
|
{
|
||||||
|
typename pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
|
||||||
|
|
||||||
|
// voxelize to grid cell size
|
||||||
|
cloud = util3d::voxelize(cloudIn, indicesIn, cellSize_);
|
||||||
|
pcl::IndicesPtr indices(new std::vector<int>);
|
||||||
|
indices->resize(cloud->size());
|
||||||
|
for(unsigned int i=0; i<indices->size(); ++i)
|
||||||
|
{
|
||||||
|
indices->at(i) = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add pose rotation without yaw
|
||||||
|
float roll, pitch, yaw;
|
||||||
|
pose.getEulerAngles(roll, pitch, yaw);
|
||||||
|
UDEBUG("node.getPose()=%s projMapFrame_=%d", pose.prettyPrint().c_str(), projMapFrame_?1:0);
|
||||||
|
cloud = util3d::transformPointCloud(cloud, Transform(0,0, projMapFrame_?pose.z():0, roll, pitch, 0));
|
||||||
|
|
||||||
|
// filter footprint
|
||||||
|
if(footprintLength_ > 0.0f || footprintWidth_ > 0.0f || footprintHeight_ > 0.0f)
|
||||||
|
{
|
||||||
|
indices = util3d::cropBox(
|
||||||
|
cloud,
|
||||||
|
indices,
|
||||||
|
Eigen::Vector4f(
|
||||||
|
footprintLength_>0.0f?-footprintLength_/2.0f:std::numeric_limits<int>::min(),
|
||||||
|
footprintWidth_>0.0f&&footprintLength_>0.0f?-footprintWidth_/2.0f:std::numeric_limits<int>::min(),
|
||||||
|
0,
|
||||||
|
1),
|
||||||
|
Eigen::Vector4f(
|
||||||
|
footprintLength_>0.0f?footprintLength_/2.0f:std::numeric_limits<int>::max(),
|
||||||
|
footprintWidth_>0.0f&&footprintLength_>0.0f?footprintWidth_/2.0f:std::numeric_limits<int>::max(),
|
||||||
|
footprintHeight_>0.0f&&footprintLength_>0.0f&&footprintWidth_>0.0f?footprintHeight_:std::numeric_limits<int>::max(),
|
||||||
|
1),
|
||||||
|
Transform::getIdentity(),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter ground/obstacles zone
|
||||||
|
if(minGroundHeight_ != 0.0f || maxObstacleHeight_ > 0.0f)
|
||||||
|
{
|
||||||
|
indices = util3d::passThrough(cloud, indices, "z",
|
||||||
|
minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(),
|
||||||
|
maxObstacleHeight_>0.0f?maxObstacleHeight_:std::numeric_limits<int>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(indices->size())
|
||||||
|
{
|
||||||
|
if(normalsSegmentation_)
|
||||||
|
{
|
||||||
|
UDEBUG("normalKSearch=%d", normalKSearch_);
|
||||||
|
UDEBUG("maxGroundAngle=%f", maxGroundAngle_);
|
||||||
|
UDEBUG("Cluster radius=%f", clusterRadius_);
|
||||||
|
UDEBUG("flatObstaclesDetected=%d", flatObstaclesDetected_?1:0);
|
||||||
|
UDEBUG("maxGroundHeight=%f", maxGroundHeight_?1:0);
|
||||||
|
util3d::segmentObstaclesFromGround<PointT>(
|
||||||
|
cloud,
|
||||||
|
indices,
|
||||||
|
groundIndices,
|
||||||
|
obstaclesIndices,
|
||||||
|
normalKSearch_,
|
||||||
|
maxGroundAngle_,
|
||||||
|
clusterRadius_,
|
||||||
|
minClusterSize_,
|
||||||
|
flatObstaclesDetected_,
|
||||||
|
maxGroundHeight_,
|
||||||
|
flatObstacles,
|
||||||
|
Eigen::Vector4f(viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?pose.z():0), 1));
|
||||||
|
UDEBUG("viewPoint=%f,%f,%f", viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?pose.z():0));
|
||||||
|
//UWARN("Saving ground.pcd and obstacles.pcd");
|
||||||
|
//pcl::io::savePCDFile("ground.pcd", *cloud, *groundIndices);
|
||||||
|
//pcl::io::savePCDFile("obstacles.pcd", *cloud, *obstaclesIndices);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UDEBUG("");
|
||||||
|
// passthrough filter
|
||||||
|
groundIndices = rtabmap::util3d::passThrough(cloud, indices, "z", minGroundHeight_<0.0f?minGroundHeight_:std::numeric_limits<int>::min(), maxGroundHeight_);
|
||||||
|
obstaclesIndices = rtabmap::util3d::extractIndices(cloud, groundIndices, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
UDEBUG("groundIndices=%d obstaclesIndices=%d", (int)groundIndices->size(), (int)obstaclesIndices->size());
|
||||||
|
|
||||||
|
// Do radius filtering after voxel filtering ( a lot faster)
|
||||||
|
if(noiseFilteringRadius_ > 0.0 && noiseFilteringMinNeighbors_ > 0)
|
||||||
|
{
|
||||||
|
UDEBUG("");
|
||||||
|
if(groundIndices->size())
|
||||||
|
{
|
||||||
|
groundIndices = rtabmap::util3d::radiusFiltering(cloud, groundIndices, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
|
||||||
|
}
|
||||||
|
if(obstaclesIndices->size())
|
||||||
|
{
|
||||||
|
obstaclesIndices = rtabmap::util3d::radiusFiltering(cloud, obstaclesIndices, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
|
||||||
|
}
|
||||||
|
if(flatObstacles && (*flatObstacles)->size())
|
||||||
|
{
|
||||||
|
*flatObstacles = rtabmap::util3d::radiusFiltering(cloud, *flatObstacles, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(groundIndices->empty() && obstaclesIndices->empty())
|
||||||
|
{
|
||||||
|
UWARN("Cloud (with %d points) is empty after noise "
|
||||||
|
"filtering. Occupancy grid cannot be "
|
||||||
|
"created.",
|
||||||
|
(int)cloud->size());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CORELIB_INCLUDE_RTABMAP_CORE_IMPL_OCCUPANCYGRID_HPP_ */
|
||||||
@@ -136,6 +136,33 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP passThrough(
|
|||||||
float max,
|
float max,
|
||||||
bool negative = false);
|
bool negative = false);
|
||||||
|
|
||||||
|
pcl::IndicesPtr RTABMAP_EXP cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
|
const pcl::IndicesPtr & indices,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform = Transform::getIdentity(),
|
||||||
|
bool negative = false);
|
||||||
|
pcl::IndicesPtr RTABMAP_EXP cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
|
const pcl::IndicesPtr & indices,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform = Transform::getIdentity(),
|
||||||
|
bool negative = false);
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr RTABMAP_EXP cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform = Transform::getIdentity(),
|
||||||
|
bool negative = false);
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr RTABMAP_EXP cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform = Transform::getIdentity(),
|
||||||
|
bool negative = false);
|
||||||
|
|
||||||
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
|
//Note: This assumes a coordinate system where X is forward, * Y is up, and Z is right.
|
||||||
pcl::IndicesPtr RTABMAP_EXP frustumFiltering(
|
pcl::IndicesPtr RTABMAP_EXP frustumFiltering(
|
||||||
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <rtabmap/core/OccupancyGrid.h>
|
#include <rtabmap/core/OccupancyGrid.h>
|
||||||
#include <rtabmap/core/util3d.h>
|
#include <rtabmap/core/util3d.h>
|
||||||
#include <rtabmap/core/util3d_mapping.h>
|
|
||||||
#include <rtabmap/core/util3d_transforms.h>
|
|
||||||
#include <rtabmap/utilite/ULogger.h>
|
#include <rtabmap/utilite/ULogger.h>
|
||||||
#include <rtabmap/utilite/UConversion.h>
|
#include <rtabmap/utilite/UConversion.h>
|
||||||
#include <rtabmap/utilite/UStl.h>
|
#include <rtabmap/utilite/UStl.h>
|
||||||
@@ -44,6 +42,9 @@ OccupancyGrid::OccupancyGrid(const ParametersMap & parameters) :
|
|||||||
cloudMaxDepth_(Parameters::defaultGridDepthMax()),
|
cloudMaxDepth_(Parameters::defaultGridDepthMax()),
|
||||||
cloudMinDepth_(Parameters::defaultGridDepthMin()),
|
cloudMinDepth_(Parameters::defaultGridDepthMin()),
|
||||||
//roiRatios_(Parameters::defaultGridDepthRoiRatios()), // initialized in parseParameters()
|
//roiRatios_(Parameters::defaultGridDepthRoiRatios()), // initialized in parseParameters()
|
||||||
|
footprintLength_(Parameters::defaultGridFootprintLength()),
|
||||||
|
footprintWidth_(Parameters::defaultGridFootprintWidth()),
|
||||||
|
footprintHeight_(Parameters::defaultGridFootprintHeight()),
|
||||||
scanDecimation_(Parameters::defaultGridScanDecimation()),
|
scanDecimation_(Parameters::defaultGridScanDecimation()),
|
||||||
cellSize_(Parameters::defaultGridCellSize()),
|
cellSize_(Parameters::defaultGridCellSize()),
|
||||||
occupancyFromCloud_(Parameters::defaultGridFromDepth()),
|
occupancyFromCloud_(Parameters::defaultGridFromDepth()),
|
||||||
@@ -51,6 +52,7 @@ OccupancyGrid::OccupancyGrid(const ParametersMap & parameters) :
|
|||||||
maxObstacleHeight_(Parameters::defaultGridMaxObstacleHeight()),
|
maxObstacleHeight_(Parameters::defaultGridMaxObstacleHeight()),
|
||||||
normalKSearch_(Parameters::defaultGridNormalK()),
|
normalKSearch_(Parameters::defaultGridNormalK()),
|
||||||
maxGroundAngle_(Parameters::defaultGridMaxGroundAngle()*M_PI/180.0f),
|
maxGroundAngle_(Parameters::defaultGridMaxGroundAngle()*M_PI/180.0f),
|
||||||
|
clusterRadius_(Parameters::defaultGridClusterRadius()),
|
||||||
minClusterSize_(Parameters::defaultGridMinClusterSize()),
|
minClusterSize_(Parameters::defaultGridMinClusterSize()),
|
||||||
flatObstaclesDetected_(Parameters::defaultGridFlatObstacleDetected()),
|
flatObstaclesDetected_(Parameters::defaultGridFlatObstacleDetected()),
|
||||||
minGroundHeight_(Parameters::defaultGridMinGroundHeight()),
|
minGroundHeight_(Parameters::defaultGridMinGroundHeight()),
|
||||||
@@ -74,6 +76,9 @@ void OccupancyGrid::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kGridDepthDecimation(), cloudDecimation_);
|
Parameters::parse(parameters, Parameters::kGridDepthDecimation(), cloudDecimation_);
|
||||||
Parameters::parse(parameters, Parameters::kGridDepthMin(), cloudMinDepth_);
|
Parameters::parse(parameters, Parameters::kGridDepthMin(), cloudMinDepth_);
|
||||||
Parameters::parse(parameters, Parameters::kGridDepthMax(), cloudMaxDepth_);
|
Parameters::parse(parameters, Parameters::kGridDepthMax(), cloudMaxDepth_);
|
||||||
|
Parameters::parse(parameters, Parameters::kGridFootprintLength(), footprintLength_);
|
||||||
|
Parameters::parse(parameters, Parameters::kGridFootprintWidth(), footprintWidth_);
|
||||||
|
Parameters::parse(parameters, Parameters::kGridFootprintHeight(), footprintHeight_);
|
||||||
Parameters::parse(parameters, Parameters::kGridScanDecimation(), scanDecimation_);
|
Parameters::parse(parameters, Parameters::kGridScanDecimation(), scanDecimation_);
|
||||||
float cellSize = cellSize_;
|
float cellSize = cellSize_;
|
||||||
if(Parameters::parse(parameters, Parameters::kGridCellSize(), cellSize))
|
if(Parameters::parse(parameters, Parameters::kGridCellSize(), cellSize))
|
||||||
@@ -109,6 +114,8 @@ void OccupancyGrid::parseParameters(const ParametersMap & parameters)
|
|||||||
{
|
{
|
||||||
maxGroundAngle_ *= M_PI/180.0f;
|
maxGroundAngle_ *= M_PI/180.0f;
|
||||||
}
|
}
|
||||||
|
Parameters::parse(parameters, Parameters::kGridClusterRadius(), clusterRadius_);
|
||||||
|
UASSERT_MSG(clusterRadius_ > 0.0f, uFormat("Param name is \"%s\"", Parameters::kGridClusterRadius().c_str()).c_str());
|
||||||
Parameters::parse(parameters, Parameters::kGridMinClusterSize(), minClusterSize_);
|
Parameters::parse(parameters, Parameters::kGridMinClusterSize(), minClusterSize_);
|
||||||
Parameters::parse(parameters, Parameters::kGridFlatObstacleDetected(), flatObstaclesDetected_);
|
Parameters::parse(parameters, Parameters::kGridFlatObstacleDetected(), flatObstaclesDetected_);
|
||||||
Parameters::parse(parameters, Parameters::kGridNormalsSegmentation(), normalsSegmentation_);
|
Parameters::parse(parameters, Parameters::kGridNormalsSegmentation(), normalsSegmentation_);
|
||||||
@@ -175,7 +182,11 @@ void OccupancyGrid::setCellSize(float cellSize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OccupancyGrid::createLocalMap(const Signature & node, cv::Mat & ground, cv::Mat & obstacles, cv::Point3f & viewPoint) const
|
void OccupancyGrid::createLocalMap(
|
||||||
|
const Signature & node,
|
||||||
|
cv::Mat & ground,
|
||||||
|
cv::Mat & obstacles,
|
||||||
|
cv::Point3f & viewPoint) const
|
||||||
{
|
{
|
||||||
UDEBUG("scan channels=%d, occupancyFromCloud_=%d normalsSegmentation_=%d grid3D_=%d",
|
UDEBUG("scan channels=%d, occupancyFromCloud_=%d normalsSegmentation_=%d grid3D_=%d",
|
||||||
node.sensorData().laserScanRaw().empty()?0:node.sensorData().laserScanRaw().channels(), occupancyFromCloud_?1:0, normalsSegmentation_?1:0, grid3D_?1:0);
|
node.sensorData().laserScanRaw().empty()?0:node.sensorData().laserScanRaw().channels(), occupancyFromCloud_?1:0, normalsSegmentation_?1:0, grid3D_?1:0);
|
||||||
@@ -211,7 +222,10 @@ void OccupancyGrid::createLocalMap(const Signature & node, cv::Mat & ground, cv:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UDEBUG("Depth image");
|
UDEBUG("Depth image : decimation=%d max=%f min=%f",
|
||||||
|
cloudDecimation_,
|
||||||
|
cloudMaxDepth_,
|
||||||
|
cloudMinDepth_);
|
||||||
cloud = util3d::cloudRGBFromSensorData(
|
cloud = util3d::cloudRGBFromSensorData(
|
||||||
node.sensorData(),
|
node.sensorData(),
|
||||||
cloudDecimation_,
|
cloudDecimation_,
|
||||||
@@ -253,89 +267,18 @@ void OccupancyGrid::createLocalMap(const Signature & node, cv::Mat & ground, cv:
|
|||||||
|
|
||||||
if(cloud->size())
|
if(cloud->size())
|
||||||
{
|
{
|
||||||
// voxelize to grid cell size
|
pcl::IndicesPtr groundIndices(new std::vector<int>);
|
||||||
cloud = util3d::voxelize(cloud, indices, cellSize_);
|
pcl::IndicesPtr obstaclesIndices(new std::vector<int>);
|
||||||
indices->resize(cloud->size());
|
cloud = this->segmentCloud<pcl::PointXYZRGB>(
|
||||||
for(unsigned int i=0; i<indices->size(); ++i)
|
cloud,
|
||||||
|
indices,
|
||||||
|
node.getPose(),
|
||||||
|
viewPoint,
|
||||||
|
groundIndices,
|
||||||
|
obstaclesIndices);
|
||||||
|
|
||||||
|
if(!groundIndices->empty() || !obstaclesIndices->empty())
|
||||||
{
|
{
|
||||||
indices->at(i) = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add pose rotation without yaw
|
|
||||||
float roll, pitch, yaw;
|
|
||||||
node.getPose().getEulerAngles(roll, pitch, yaw);
|
|
||||||
UDEBUG("node.getPose()=%s projMapFrame_=%d", node.getPose().prettyPrint().c_str(), projMapFrame_?1:0);
|
|
||||||
cloud = util3d::transformPointCloud(cloud, Transform(0,0, projMapFrame_?node.getPose().z():0, roll, pitch, 0));
|
|
||||||
|
|
||||||
if(minGroundHeight_ != 0.0f || maxObstacleHeight_ > 0.0f)
|
|
||||||
{
|
|
||||||
indices = util3d::passThrough(cloud, indices, "z",
|
|
||||||
minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(),
|
|
||||||
maxObstacleHeight_>0.0f?maxObstacleHeight_:std::numeric_limits<int>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
pcl::IndicesPtr groundIndices, obstaclesIndices;
|
|
||||||
|
|
||||||
if(indices->size())
|
|
||||||
{
|
|
||||||
if(normalsSegmentation_)
|
|
||||||
{
|
|
||||||
UDEBUG("normalKSearch=%d", normalKSearch_);
|
|
||||||
UDEBUG("maxGroundAngle=%f", maxGroundAngle_);
|
|
||||||
UDEBUG("Cluster radius=%f", cellSize_*2.0f);
|
|
||||||
UDEBUG("flatObstaclesDetected=%d", flatObstaclesDetected_?1:0);
|
|
||||||
UDEBUG("maxGroundHeight=%f", maxGroundHeight_?1:0);
|
|
||||||
util3d::segmentObstaclesFromGround<pcl::PointXYZRGB>(
|
|
||||||
cloud,
|
|
||||||
indices,
|
|
||||||
groundIndices,
|
|
||||||
obstaclesIndices,
|
|
||||||
normalKSearch_,
|
|
||||||
maxGroundAngle_,
|
|
||||||
cellSize_*2.0f,
|
|
||||||
minClusterSize_,
|
|
||||||
flatObstaclesDetected_,
|
|
||||||
maxGroundHeight_,
|
|
||||||
0,
|
|
||||||
Eigen::Vector4f(viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?node.getPose().z():0), 1));
|
|
||||||
UDEBUG("viewPoint=%f,%f,%f", viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?node.getPose().z():0));
|
|
||||||
//UWARN("Saving ground.pcd and obstacles.pcd");
|
|
||||||
//pcl::io::savePCDFile("ground.pcd", *cloud, *groundIndices);
|
|
||||||
//pcl::io::savePCDFile("obstacles.pcd", *cloud, *obstaclesIndices);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UDEBUG("");
|
|
||||||
// passthrough filter
|
|
||||||
groundIndices = rtabmap::util3d::passThrough(cloud, indices, "z", minGroundHeight_<0.0f?minGroundHeight_:std::numeric_limits<int>::min(), maxGroundHeight_);
|
|
||||||
obstaclesIndices = rtabmap::util3d::extractIndices(cloud, groundIndices, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
UDEBUG("groundIndices=%d obstaclesIndices=%d", (int)groundIndices->size(), (int)obstaclesIndices->size());
|
|
||||||
|
|
||||||
// Do radius filtering after voxel filtering ( a lot faster)
|
|
||||||
if(noiseFilteringRadius_ > 0.0 && noiseFilteringMinNeighbors_ > 0)
|
|
||||||
{
|
|
||||||
UDEBUG("");
|
|
||||||
if(groundIndices->size())
|
|
||||||
{
|
|
||||||
groundIndices = rtabmap::util3d::radiusFiltering(cloud, groundIndices, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
|
|
||||||
}
|
|
||||||
if(obstaclesIndices->size())
|
|
||||||
{
|
|
||||||
obstaclesIndices = rtabmap::util3d::radiusFiltering(cloud, obstaclesIndices, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(groundIndices->empty() && obstaclesIndices->empty())
|
|
||||||
{
|
|
||||||
UWARN("Cloud (with %d points) is empty after noise "
|
|
||||||
"filtering. Occupancy grid of node %d cannot be "
|
|
||||||
"created.",
|
|
||||||
(int)cloud->size(), node.id());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr groundCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||||
pcl::PointCloud<pcl::PointXYZRGB>::Ptr obstaclesCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr obstaclesCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||||
|
|
||||||
@@ -359,6 +302,8 @@ void OccupancyGrid::createLocalMap(const Signature & node, cv::Mat & ground, cv:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transform back in base frame
|
// transform back in base frame
|
||||||
|
float roll, pitch, yaw;
|
||||||
|
node.getPose().getEulerAngles(roll, pitch, yaw);
|
||||||
Transform tinv = Transform(0,0, projMapFrame_?node.getPose().z():0, roll, pitch, 0).inverse();
|
Transform tinv = Transform(0,0, projMapFrame_?node.getPose().z():0, roll, pitch, 0).inverse();
|
||||||
ground = util3d::laserScanFromPointCloud(*groundCloud, tinv);
|
ground = util3d::laserScanFromPointCloud(*groundCloud, tinv);
|
||||||
obstacles = util3d::laserScanFromPointCloud(*obstaclesCloud, tinv);
|
obstacles = util3d::laserScanFromPointCloud(*obstaclesCloud, tinv);
|
||||||
|
|||||||
@@ -186,27 +186,31 @@ rtabmap::ParametersMap Parameters::getDefaultOdometryParameters(bool stereo, boo
|
|||||||
return odomParameters;
|
return odomParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParametersMap Parameters::getDefaultParameters(const std::string & group)
|
ParametersMap Parameters::getDefaultParameters(const std::string & groupIn)
|
||||||
{
|
{
|
||||||
rtabmap::ParametersMap parameters;
|
rtabmap::ParametersMap parameters;
|
||||||
const rtabmap::ParametersMap & defaultParameters = rtabmap::Parameters::getDefaultParameters();
|
const rtabmap::ParametersMap & defaultParameters = rtabmap::Parameters::getDefaultParameters();
|
||||||
for(rtabmap::ParametersMap::const_iterator iter=defaultParameters.begin(); iter!=defaultParameters.end(); ++iter)
|
for(rtabmap::ParametersMap::const_iterator iter=defaultParameters.begin(); iter!=defaultParameters.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(iter->first.compare(group) == 0)
|
UASSERT(uSplit(iter->first, '/').size() == 2);
|
||||||
|
std::string group = uSplit(iter->first, '/').front();
|
||||||
|
if(group.compare(groupIn) == 0)
|
||||||
{
|
{
|
||||||
parameters.insert(*iter);
|
parameters.insert(*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UASSERT_MSG(parameters.size(), uFormat("No parameters found for group %s!", group.c_str()).c_str());
|
UASSERT_MSG(parameters.size(), uFormat("No parameters found for group %s!", groupIn.c_str()).c_str());
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParametersMap Parameters::filterParameters(const ParametersMap & parameters, const std::string & group)
|
ParametersMap Parameters::filterParameters(const ParametersMap & parameters, const std::string & groupIn)
|
||||||
{
|
{
|
||||||
ParametersMap output;
|
ParametersMap output;
|
||||||
for(rtabmap::ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
for(rtabmap::ParametersMap::const_iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
|
||||||
{
|
{
|
||||||
if(iter->first.compare(group) == 0)
|
UASSERT(uSplit(iter->first, '/').size() == 2);
|
||||||
|
std::string group = uSplit(iter->first, '/').front();
|
||||||
|
if(group.compare(groupIn) == 0)
|
||||||
{
|
{
|
||||||
output.insert(*iter);
|
output.insert(*iter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <pcl/filters/frustum_culling.h>
|
#include <pcl/filters/frustum_culling.h>
|
||||||
#include <pcl/filters/random_sample.h>
|
#include <pcl/filters/random_sample.h>
|
||||||
#include <pcl/filters/passthrough.h>
|
#include <pcl/filters/passthrough.h>
|
||||||
|
#include <pcl/filters/crop_box.h>
|
||||||
|
|
||||||
#include <pcl/features/normal_3d_omp.h>
|
#include <pcl/features/normal_3d_omp.h>
|
||||||
|
|
||||||
@@ -340,6 +341,101 @@ pcl::PointCloud<pcl::PointXYZRGB>::Ptr passThrough(
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pcl::IndicesPtr cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
|
const pcl::IndicesPtr & indices,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
UASSERT(min[0] < max[0] && min[1] < max[1] && min[2] < max[2]);
|
||||||
|
|
||||||
|
pcl::IndicesPtr output(new std::vector<int>);
|
||||||
|
pcl::CropBox<pcl::PointXYZ> filter;
|
||||||
|
filter.setNegative(negative);
|
||||||
|
filter.setMin(min);
|
||||||
|
filter.setMax(max);
|
||||||
|
if(!transform.isNull() && !transform.isIdentity())
|
||||||
|
{
|
||||||
|
filter.setTransform(transform.toEigen3f());
|
||||||
|
}
|
||||||
|
filter.setInputCloud(cloud);
|
||||||
|
filter.setIndices(indices);
|
||||||
|
filter.filter(*output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
pcl::IndicesPtr cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
|
const pcl::IndicesPtr & indices,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
UASSERT(min[0] < max[0] && min[1] < max[1] && min[2] < max[2]);
|
||||||
|
|
||||||
|
pcl::IndicesPtr output(new std::vector<int>);
|
||||||
|
pcl::CropBox<pcl::PointXYZRGB> filter;
|
||||||
|
filter.setNegative(negative);
|
||||||
|
filter.setMin(min);
|
||||||
|
filter.setMax(max);
|
||||||
|
if(!transform.isNull() && !transform.isIdentity())
|
||||||
|
{
|
||||||
|
filter.setTransform(transform.toEigen3f());
|
||||||
|
}
|
||||||
|
filter.setInputCloud(cloud);
|
||||||
|
filter.setIndices(indices);
|
||||||
|
filter.filter(*output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
UASSERT(min[0] < max[0] && min[1] < max[1] && min[2] < max[2]);
|
||||||
|
|
||||||
|
pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>);
|
||||||
|
pcl::CropBox<pcl::PointXYZ> filter;
|
||||||
|
filter.setNegative(negative);
|
||||||
|
filter.setMin(min);
|
||||||
|
filter.setMax(max);
|
||||||
|
if(!transform.isNull() && !transform.isIdentity())
|
||||||
|
{
|
||||||
|
filter.setTransform(transform.toEigen3f());
|
||||||
|
}
|
||||||
|
filter.setInputCloud(cloud);
|
||||||
|
filter.filter(*output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cropBox(
|
||||||
|
const pcl::PointCloud<pcl::PointXYZRGB>::Ptr & cloud,
|
||||||
|
const Eigen::Vector4f & min,
|
||||||
|
const Eigen::Vector4f & max,
|
||||||
|
const Transform & transform,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
UASSERT(min[0] < max[0] && min[1] < max[1] && min[2] < max[2]);
|
||||||
|
|
||||||
|
pcl::PointCloud<pcl::PointXYZRGB>::Ptr output(new pcl::PointCloud<pcl::PointXYZRGB>);
|
||||||
|
pcl::CropBox<pcl::PointXYZRGB> filter;
|
||||||
|
filter.setNegative(negative);
|
||||||
|
filter.setMin(min);
|
||||||
|
filter.setMax(max);
|
||||||
|
if(!transform.isNull() && !transform.isIdentity())
|
||||||
|
{
|
||||||
|
filter.setTransform(transform.toEigen3f());
|
||||||
|
}
|
||||||
|
filter.setInputCloud(cloud);
|
||||||
|
filter.filter(*output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
pcl::IndicesPtr frustumFiltering(
|
pcl::IndicesPtr frustumFiltering(
|
||||||
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud,
|
||||||
const pcl::IndicesPtr & indices,
|
const pcl::IndicesPtr & indices,
|
||||||
|
|||||||
@@ -2338,8 +2338,6 @@ void DatabaseViewer::update(int value,
|
|||||||
if(signatures.size() && signatures.front()!=0 && signatures.front()->getWords().size())
|
if(signatures.size() && signatures.front()!=0 && signatures.front()->getWords().size())
|
||||||
{
|
{
|
||||||
view->setFeatures(signatures.front()->getWords(), data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow);
|
view->setFeatures(signatures.front()->getWords(), data.depthOrRightRaw().type() == CV_8UC1?cv::Mat():data.depthOrRightRaw(), Qt::yellow);
|
||||||
delete signatures.front();
|
|
||||||
signatures.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform odomPose, g;
|
Transform odomPose, g;
|
||||||
@@ -2421,6 +2419,14 @@ void DatabaseViewer::update(int value,
|
|||||||
(!data.depthOrRightRaw().empty() ||
|
(!data.depthOrRightRaw().empty() ||
|
||||||
!data.laserScanRaw().empty()))
|
!data.laserScanRaw().empty()))
|
||||||
{
|
{
|
||||||
|
Transform pose = Transform::getIdentity();
|
||||||
|
if(signatures.size())
|
||||||
|
{
|
||||||
|
float x, y, z, roll, pitch, yaw;
|
||||||
|
(*signatures.begin())->getPose().getTranslationAndEulerAngles(x, y, z, roll, pitch, yaw);
|
||||||
|
pose = Transform(0,0,z,roll,pitch,0);
|
||||||
|
}
|
||||||
|
|
||||||
view3D->removeAllFrustums();
|
view3D->removeAllFrustums();
|
||||||
view3D->removeCloud("0");
|
view3D->removeCloud("0");
|
||||||
view3D->removeCloud("1");
|
view3D->removeCloud("1");
|
||||||
@@ -2474,14 +2480,14 @@ void DatabaseViewer::update(int value,
|
|||||||
ui_->checkBox_mesh_quad->isChecked(),
|
ui_->checkBox_mesh_quad->isChecked(),
|
||||||
ui_->spinBox_mesh_triangleSize->value(),
|
ui_->spinBox_mesh_triangleSize->value(),
|
||||||
viewpoint);
|
viewpoint);
|
||||||
view3D->addCloudMesh("0", cloud, polygons);
|
view3D->addCloudMesh("0", cloud, polygons, pose);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
view3D->addCloud("0", cloud);
|
view3D->addCloud("0", cloud, pose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view3D->updateCameraFrustums(Transform::getIdentity(), data.cameraModels());
|
view3D->updateCameraFrustums(pose, data.cameraModels());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2489,8 +2495,8 @@ void DatabaseViewer::update(int value,
|
|||||||
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
|
cloud = util3d::cloudFromSensorData(data, 1, 0, 0, 0, ui_->parameters_toolbox->getParameters());
|
||||||
if(cloud->size())
|
if(cloud->size())
|
||||||
{
|
{
|
||||||
view3D->addCloud("0", cloud);
|
view3D->addCloud("0", cloud, pose);
|
||||||
view3D->updateCameraFrustum(Transform::getIdentity(), data.stereoCameraModel());
|
view3D->updateCameraFrustum(pose, data.stereoCameraModel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2499,7 +2505,7 @@ void DatabaseViewer::update(int value,
|
|||||||
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw(), data.laserScanInfo().localTransform());
|
pcl::PointCloud<pcl::PointXYZ>::Ptr scan = util3d::laserScanToPointCloud(data.laserScanRaw(), data.laserScanInfo().localTransform());
|
||||||
if(scan->size())
|
if(scan->size())
|
||||||
{
|
{
|
||||||
view3D->addCloud("1", scan);
|
view3D->addCloud("1", scan, pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add occupancy grid
|
//add occupancy grid
|
||||||
@@ -2533,6 +2539,12 @@ void DatabaseViewer::update(int value,
|
|||||||
|
|
||||||
view3D->update();
|
view3D->update();
|
||||||
}
|
}
|
||||||
|
if(signatures.size())
|
||||||
|
{
|
||||||
|
UASSERT(signatures.front() != 0 && signatures.size() == 1);
|
||||||
|
delete signatures.front();
|
||||||
|
signatures.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!img.isNull())
|
if(!img.isNull())
|
||||||
|
|||||||
@@ -775,6 +775,9 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
|||||||
_ui->doubleSpinBox_grid_maxDepth->setObjectName(Parameters::kGridDepthMax().c_str());
|
_ui->doubleSpinBox_grid_maxDepth->setObjectName(Parameters::kGridDepthMax().c_str());
|
||||||
_ui->doubleSpinBox_grid_minDepth->setObjectName(Parameters::kGridDepthMin().c_str());
|
_ui->doubleSpinBox_grid_minDepth->setObjectName(Parameters::kGridDepthMin().c_str());
|
||||||
_ui->lineEdit_grid_roi->setObjectName(Parameters::kGridDepthRoiRatios().c_str());
|
_ui->lineEdit_grid_roi->setObjectName(Parameters::kGridDepthRoiRatios().c_str());
|
||||||
|
_ui->doubleSpinBox_grid_footprintLength->setObjectName(Parameters::kGridFootprintLength().c_str());
|
||||||
|
_ui->doubleSpinBox_grid_footprintWidth->setObjectName(Parameters::kGridFootprintWidth().c_str());
|
||||||
|
_ui->doubleSpinBox_grid_footprintHeight->setObjectName(Parameters::kGridFootprintHeight().c_str());
|
||||||
_ui->checkBox_grid_flatObstaclesDetected->setObjectName(Parameters::kGridFlatObstacleDetected().c_str());
|
_ui->checkBox_grid_flatObstaclesDetected->setObjectName(Parameters::kGridFlatObstacleDetected().c_str());
|
||||||
_ui->groupBox_grid_fromDepthImage->setObjectName(Parameters::kGridFromDepth().c_str());
|
_ui->groupBox_grid_fromDepthImage->setObjectName(Parameters::kGridFromDepth().c_str());
|
||||||
_ui->checkBox_grid_projMapFrame->setObjectName(Parameters::kGridMapFrameProjection().c_str());
|
_ui->checkBox_grid_projMapFrame->setObjectName(Parameters::kGridMapFrameProjection().c_str());
|
||||||
@@ -782,6 +785,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
|||||||
_ui->spinBox_grid_normalK->setObjectName(Parameters::kGridNormalK().c_str());
|
_ui->spinBox_grid_normalK->setObjectName(Parameters::kGridNormalK().c_str());
|
||||||
_ui->doubleSpinBox_grid_maxGroundHeight->setObjectName(Parameters::kGridMaxGroundHeight().c_str());
|
_ui->doubleSpinBox_grid_maxGroundHeight->setObjectName(Parameters::kGridMaxGroundHeight().c_str());
|
||||||
_ui->doubleSpinBox_grid_maxObstacleHeight->setObjectName(Parameters::kGridMaxObstacleHeight().c_str());
|
_ui->doubleSpinBox_grid_maxObstacleHeight->setObjectName(Parameters::kGridMaxObstacleHeight().c_str());
|
||||||
|
_ui->doubleSpinBox_grid_clusterRadius->setObjectName(Parameters::kGridClusterRadius().c_str());
|
||||||
_ui->spinBox_grid_minClusterSize->setObjectName(Parameters::kGridMinClusterSize().c_str());
|
_ui->spinBox_grid_minClusterSize->setObjectName(Parameters::kGridMinClusterSize().c_str());
|
||||||
_ui->doubleSpinBox_grid_minGroundHeight->setObjectName(Parameters::kGridMinGroundHeight().c_str());
|
_ui->doubleSpinBox_grid_minGroundHeight->setObjectName(Parameters::kGridMinGroundHeight().c_str());
|
||||||
_ui->spinBox_grid_noiseMinNeighbors->setObjectName(Parameters::kGridNoiseFilteringMinNeighbors().c_str());
|
_ui->spinBox_grid_noiseMinNeighbors->setObjectName(Parameters::kGridNoiseFilteringMinNeighbors().c_str());
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>984</width>
|
<width>976</width>
|
||||||
<height>727</height>
|
<height>731</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>-500</y>
|
||||||
<width>686</width>
|
<width>678</width>
|
||||||
<height>2278</height>
|
<height>2417</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>3</number>
|
<number>15</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">
|
||||||
@@ -8105,7 +8105,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QLabel" name="label_331">
|
<widget class="QLabel" name="label_331">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Laser scan decimation.</string>
|
<string>Laser scan decimation.</string>
|
||||||
@@ -8118,7 +8118,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="10" column="0">
|
||||||
<widget class="QSpinBox" name="spinBox_grid_scanDecimation">
|
<widget class="QSpinBox" name="spinBox_grid_scanDecimation">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -8131,6 +8131,102 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QLabel" name="label_333">
|
||||||
|
<property name="text">
|
||||||
|
<string>Footprint filtering length (0=disabled).</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLabel" name="label_334">
|
||||||
|
<property name="text">
|
||||||
|
<string>Footprint filtering width (0=disabled). Footprint length should be set.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_grid_footprintLength">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_grid_footprintWidth">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QLabel" name="label_335">
|
||||||
|
<property name="text">
|
||||||
|
<string>Footprint filtering height (0=disabled). Footprint length and width should be set.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_grid_footprintHeight">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -8315,7 +8411,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QSpinBox" name="spinBox_grid_minClusterSize">
|
<widget class="QSpinBox" name="spinBox_grid_minClusterSize">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
@@ -8341,7 +8437,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="label_308">
|
<widget class="QLabel" name="label_308">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Minimum cluster size to project the points. The distance between clusters is defined by 2*Resolution.</string>
|
<string>Minimum cluster size to project the points. The distance between clusters is defined by 2*Resolution.</string>
|
||||||
@@ -8354,7 +8450,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="label_272">
|
<widget class="QLabel" name="label_272">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Flat obstacles detected.</string>
|
<string>Flat obstacles detected.</string>
|
||||||
@@ -8367,7 +8463,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="checkBox_grid_flatObstaclesDetected">
|
<widget class="QCheckBox" name="checkBox_grid_flatObstaclesDetected">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
@@ -8403,6 +8499,41 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_336">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cluster radius.</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="QDoubleSpinBox" name="doubleSpinBox_grid_clusterRadius">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> m</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.001000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.100000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
Reference in New Issue
Block a user