RTAB-Map 0.23.11
Real-Time Appearance-Based Mapping
Loading...
Searching...
No Matches
LocalMapMaker.hpp
1/*
2Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the Universite de Sherbrooke nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifndef CORELIB_INCLUDE_RTABMAP_CORE_IMPL_LOCALMAP_HPP_
29#define CORELIB_INCLUDE_RTABMAP_CORE_IMPL_LOCALMAP_HPP_
30
31#include <rtabmap/core/util3d_mapping.h>
32#include <rtabmap/core/util3d_filtering.h>
33#include <rtabmap/core/util3d_transforms.h>
35
36namespace rtabmap {
37
38template<typename PointT>
39pcl::IndicesPtr LocalGridMaker::noiseFilteringWithMaxRange(
40 const typename pcl::PointCloud<PointT>::Ptr & cloud,
41 const pcl::IndicesPtr & indices,
42 float maxRange,
43 float radiusSearch,
44 int minNeighborsInRadius)
45{
46 // util3d::radiusFiltering() would filter the whole cloud if the indices are empty
47 UASSERT(indices.get() && !indices->empty());
48 pcl::IndicesPtr closeIndices = indices;
49 pcl::IndicesPtr farIndices;
50 if(maxRange != 0.0f)
51 {
52 // Don't filter points farther than maximum range, in case we want to ray trace empty space
53 util3d::rangeSplitFiltering(cloud, indices, maxRange, closeIndices, farIndices);
54 }
55 if(closeIndices->size())
56 {
57 // Note: radiusFiltering() would filter the whole cloud if indices are empty
58 closeIndices = util3d::radiusFiltering(cloud, closeIndices, radiusSearch, minNeighborsInRadius);
59 }
60 if(farIndices.get())
61 {
62 closeIndices = util3d::concatenate(closeIndices, farIndices);
63 }
64 return closeIndices;
65}
66
67template<typename PointT>
68typename pcl::PointCloud<PointT>::Ptr LocalGridMaker::segmentCloud(
69 const typename pcl::PointCloud<PointT>::Ptr & cloudIn,
70 const pcl::IndicesPtr & indicesIn,
71 const Transform & pose,
72 const cv::Point3f & viewPoint,
73 pcl::IndicesPtr & groundIndices,
74 pcl::IndicesPtr & obstaclesIndices,
75 pcl::IndicesPtr * flatObstacles) const
76{
77 groundIndices.reset(new std::vector<int>);
78 obstaclesIndices.reset(new std::vector<int>);
79 if(flatObstacles)
80 {
81 flatObstacles->reset(new std::vector<int>);
82 }
83
84 UASSERT(cloudIn.get());
85 UASSERT(indicesIn.get());
86 if(cloudIn->empty())
87 {
88 return cloudIn;
89 }
90
91 typename pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
92 pcl::IndicesPtr indices(new std::vector<int>);
93
94 if(preVoxelFiltering_)
95 {
96 // voxelize to grid cell size
97 cloud = util3d::voxelize(cloudIn, indicesIn, cellSize_);
98
99 indices->resize(cloud->size());
100 for(unsigned int i=0; i<indices->size(); ++i)
101 {
102 indices->at(i) = i;
103 }
104 }
105 else
106 {
107 cloud = cloudIn;
108 if(indicesIn->empty() && cloud->is_dense)
109 {
110 indices->resize(cloud->size());
111 for(unsigned int i=0; i<indices->size(); ++i)
112 {
113 indices->at(i) = i;
114 }
115 }
116 else
117 {
118 indices = indicesIn;
119 }
120 }
121
122 if(cloud->empty())
123 {
124 return cloud;
125 }
126
127 // add pose rotation without yaw
128 float roll, pitch, yaw;
129 pose.getEulerAngles(roll, pitch, yaw);
130 UDEBUG("node.getPose()=%s projMapFrame_=%d", pose.prettyPrint().c_str(), projMapFrame_?1:0);
131 cloud = util3d::transformPointCloud(cloud, Transform(0,0, projMapFrame_?pose.z():0, roll, pitch, 0));
132
133 // filter footprint
134 if(footprintLength_ > 0.0f || footprintWidth_ > 0.0f || footprintHeight_ > 0.0f)
135 {
136 indices = util3d::cropBox(
137 cloud,
138 indices,
139 Eigen::Vector4f(
140 footprintLength_>0.0f?-footprintLength_/2.0f:std::numeric_limits<int>::min(),
141 footprintWidth_>0.0f&&footprintLength_>0.0f?-footprintWidth_/2.0f:std::numeric_limits<int>::min(),
142 0,
143 1),
144 Eigen::Vector4f(
145 footprintLength_>0.0f?footprintLength_/2.0f:std::numeric_limits<int>::max(),
146 footprintWidth_>0.0f&&footprintLength_>0.0f?footprintWidth_/2.0f:std::numeric_limits<int>::max(),
147 footprintHeight_>0.0f&&footprintLength_>0.0f&&footprintWidth_>0.0f?footprintHeight_:std::numeric_limits<int>::max(),
148 1),
150 true);
151 }
152
153 // filter ground/obstacles zone
154 if(minGroundHeight_ != 0.0f || maxObstacleHeight_ != 0.0f)
155 {
156 indices = util3d::passThrough(cloud, indices, "z",
157 minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(),
158 maxObstacleHeight_>0.0f?maxObstacleHeight_:std::numeric_limits<int>::max());
159 UDEBUG("indices after max obstacles height filtering = %d", (int)indices->size());
160 }
161
162 if(indices->size())
163 {
164 if(normalsSegmentation_ && !groundIsObstacle_)
165 {
166 UDEBUG("normalKSearch=%d", normalKSearch_);
167 UDEBUG("maxGroundAngle=%f", maxGroundAngle_);
168 UDEBUG("Cluster radius=%f", clusterRadius_);
169 UDEBUG("flatObstaclesDetected=%d", flatObstaclesDetected_?1:0);
170 UDEBUG("maxGroundHeight=%f", maxGroundHeight_);
171 UDEBUG("groundNormalsUp=%f", groundNormalsUp_);
172 util3d::segmentObstaclesFromGround<PointT>(
173 cloud,
174 indices,
175 groundIndices,
176 obstaclesIndices,
177 normalKSearch_,
178 maxGroundAngle_,
179 clusterRadius_,
180 minClusterSize_,
181 flatObstaclesDetected_,
182 maxGroundHeight_,
183 flatObstacles,
184 Eigen::Vector4f(viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?pose.z():0), 1),
185 groundNormalsUp_);
186 UDEBUG("viewPoint=%f,%f,%f", viewPoint.x, viewPoint.y, viewPoint.z+(projMapFrame_?pose.z():0));
187 //UWARN("Saving ground.pcd and obstacles.pcd");
188 //pcl::io::savePCDFile("ground.pcd", *cloud, *groundIndices);
189 //pcl::io::savePCDFile("obstacles.pcd", *cloud, *obstaclesIndices);
190 }
191 else
192 {
193 UDEBUG("");
194 // passthrough filter
195 groundIndices = rtabmap::util3d::passThrough(cloud, indices, "z",
196 minGroundHeight_!=0.0f?minGroundHeight_:std::numeric_limits<int>::min(),
197 maxGroundHeight_!=0.0f?maxGroundHeight_:std::numeric_limits<int>::max());
198
199 pcl::IndicesPtr notObstacles = groundIndices;
200 if(indices->size())
201 {
202 notObstacles = util3d::extractIndices(cloud, indices, true);
203 notObstacles = util3d::concatenate(notObstacles, groundIndices);
204 }
205 obstaclesIndices = rtabmap::util3d::extractIndices(cloud, notObstacles, true);
206 }
207
208 UDEBUG("groundIndices=%d obstaclesIndices=%d", (int)groundIndices->size(), (int)obstaclesIndices->size());
209
210 // Do radius filtering after voxel filtering ( a lot faster)
211 if(noiseFilteringRadius_ > 0.0 && noiseFilteringMinNeighbors_ > 0)
212 {
213 UDEBUG("Radius filtering (%ld ground %ld obstacles, radius=%f k=%d)",
214 groundIndices->size(),
215 obstaclesIndices->size()+(flatObstacles?(*flatObstacles)->size():0),
216 noiseFilteringRadius_,
217 noiseFilteringMinNeighbors_);
218 if(groundIndices->size())
219 {
220 groundIndices = noiseFilteringWithMaxRange<PointT>(cloud, groundIndices, rangeMax_, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
221 }
222 if(obstaclesIndices->size())
223 {
224 obstaclesIndices = noiseFilteringWithMaxRange<PointT>(cloud, obstaclesIndices, rangeMax_, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
225 }
226 if(flatObstacles && (*flatObstacles)->size())
227 {
228 *flatObstacles = noiseFilteringWithMaxRange<PointT>(cloud, *flatObstacles, rangeMax_, noiseFilteringRadius_, noiseFilteringMinNeighbors_);
229 }
230 UDEBUG("Radius filtering end (%ld ground %ld obstacles)",
231 groundIndices->size(),
232 obstaclesIndices->size()+(flatObstacles?(*flatObstacles)->size():0));
233
234 if(groundIndices->empty() && obstaclesIndices->empty())
235 {
236 UWARN("Cloud (with %d points) is empty after noise "
237 "filtering. Occupancy grid cannot be "
238 "created.",
239 (int)cloud->size());
240
241 }
242 }
243 }
244 return cloud;
245}
246
247}
248
249
250#endif /* CORELIB_INCLUDE_RTABMAP_CORE_IMPL_LOCALMAP_HPP_ */
ULogger class and convenient macros.
#define UDEBUG(...)
Definition ULogger.h:59
#define UASSERT(condition)
Definition ULogger.h:66
#define UWARN(...)
Definition ULogger.h:61
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, pcl::IndicesPtr &obstaclesIndices, pcl::IndicesPtr *flatObstacles=0) const
Segments a point cloud into ground and obstacle indices.
Represents a 3D rigid body transformation (rotation + translation).
Definition Transform.h:53
std::string prettyPrint() const
Returns a string representation of the transform.
static Transform getIdentity()
Returns identity transform.
void getEulerAngles(float &roll, float &pitch, float &yaw) const
Extracts Euler angles (roll, pitch, yaw).
float & z()
Translation z.
Definition Transform.h:151
pcl::IndicesPtr RTABMAP_CORE_EXPORT cropBox(const pcl::PCLPointCloud2::Ptr &cloud, const pcl::IndicesPtr &indices, const Eigen::Vector4f &min, const Eigen::Vector4f &max, const Transform &transform=Transform::getIdentity(), bool negative=false)
Performs crop box filtering on a point cloud of type pcl::PCLPointCloud2 and returns filtered indices...
pcl::IndicesPtr RTABMAP_CORE_EXPORT extractIndices(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, bool negative)
Extract indices from point cloud of type pcl::PointXYZ.
pcl::IndicesPtr RTABMAP_CORE_EXPORT passThrough(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, const std::string &axis, float min, float max, bool negative=false)
Performs pass-through filtering on a point cloud of type pcl::PointXYZ and returns filtered indices.
void RTABMAP_CORE_EXPORT rangeSplitFiltering(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float range, pcl::IndicesPtr &closeIndices, pcl::IndicesPtr &farIndices)
Splits a point cloud of type pcl::PointXYZ.
pcl::IndicesPtr RTABMAP_CORE_EXPORT radiusFiltering(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, float radiusSearch, int minNeighborsInRadius)
Radius filtering for point cloud of type pcl::PointXYZ.
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_CORE_EXPORT transformPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const Transform &transform)
Transforms pcl::PointXYZ point cloud type.
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_CORE_EXPORT voxelize(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float voxelSize)
Performs voxel grid downsampling on a point cloud of type pcl::PointXYZ on provided indices.
pcl::IndicesPtr RTABMAP_CORE_EXPORT concatenate(const std::vector< pcl::IndicesPtr > &indices)
Concatenates multiple sets of indices into a single index vector.