41 #include <pcl/people/height_map_2d.h>
43 #ifndef PCL_PEOPLE_HEIGHT_MAP_2D_HPP_
44 #define PCL_PEOPLE_HEIGHT_MAP_2D_HPP_
46 template <
typename Po
intT>
51 min_dist_between_maxima_ = 0.3;
55 sqrt_ground_coeffs_ = std::numeric_limits<float>::quiet_NaN();
58 template <
typename Po
intT>
void
62 if (std::isnan(sqrt_ground_coeffs_))
64 PCL_ERROR (
"[pcl::people::HeightMap2D::compute] Floor parameters have not been set or they are not valid!\n");
67 if (cloud_ ==
nullptr)
69 PCL_ERROR (
"[pcl::people::HeightMap2D::compute] Input cloud has not been set!\n");
75 buckets_cloud_indices_.clear();
76 maxima_indices_.clear();
77 maxima_cloud_indices_.clear();
78 maxima_indices_filtered_.clear();
79 maxima_cloud_indices_filtered_.clear();
83 buckets_.resize(
static_cast<std::size_t
>((cluster.
getMax()(0) - cluster.
getMin()(0)) / bin_size_) + 1, 0);
85 buckets_.resize(
static_cast<std::size_t
>((cluster.
getMax()(1) - cluster.
getMin()(1)) / bin_size_) + 1, 0);
86 buckets_cloud_indices_.resize(buckets_.size(), 0);
90 PointT* p = &(*cloud_)[cluster_idx];
93 index =
static_cast<int>((p->x - cluster.
getMin()(0)) / bin_size_);
95 index =
static_cast<int>((p->y - cluster.
getMin()(1)) / bin_size_);
96 if (index > (
static_cast<int> (buckets_.size ()) - 1))
97 std::cout <<
"Error: out of array - " << index <<
" of " << buckets_.size() << std::endl;
100 Eigen::Vector4f new_point(p->x, p->y, p->z, 1.0f);
101 float heightp = std::fabs(new_point.dot(ground_coeffs_));
102 heightp /= sqrt_ground_coeffs_;
103 if ((heightp * 60) > buckets_[index])
105 buckets_[index] = heightp * 60;
106 buckets_cloud_indices_[index] = cluster_idx;
118 template <
typename Po
intT>
void
123 int left = buckets_[0];
125 maxima_indices_.resize(
static_cast<std::size_t
>(buckets_.size()), 0);
126 maxima_cloud_indices_.resize(
static_cast<std::size_t
>(buckets_.size()), 0);
129 if (buckets_[0] > buckets_[1])
131 maxima_indices_[maxima_number_] = 0;
132 maxima_cloud_indices_[maxima_number_] = buckets_cloud_indices_[maxima_indices_[maxima_number_]];
138 while (i < (
static_cast<int> (buckets_.size()) - 1))
140 int right = buckets_[i+1];
141 if ((buckets_[i] > left) && (buckets_[i] > right))
145 while ((t < maxima_number_) && (buckets_[i] < buckets_[maxima_indices_[t]]))
150 for (
int m = maxima_number_; m > t; m--)
152 maxima_indices_[m] = maxima_indices_[m-1];
153 maxima_cloud_indices_[m] = maxima_cloud_indices_[m-1];
156 maxima_indices_[t] = i -
static_cast<int>(offset/2 + 0.5);
157 maxima_cloud_indices_[t] = buckets_cloud_indices_[maxima_indices_[t]];
158 left = buckets_[i+1];
165 if (buckets_[i] == right)
179 if (buckets_[buckets_.size()-1] > left)
183 while ((t < maxima_number_) && (buckets_[buckets_.size()-1] < buckets_[maxima_indices_[t]]))
188 for (
int m = maxima_number_; m > t; m--)
190 maxima_indices_[m] = maxima_indices_[m-1];
191 maxima_cloud_indices_[m] = maxima_cloud_indices_[m-1];
194 maxima_indices_[t] = i -
static_cast<int>(offset/2 + 0.5);
195 maxima_cloud_indices_[t] = buckets_cloud_indices_[maxima_indices_[t]];
201 template <
typename Po
intT>
void
205 maxima_number_after_filtering_ = 0;
206 maxima_indices_filtered_.resize(maxima_number_, 0);
207 maxima_cloud_indices_filtered_.resize(maxima_number_, 0);
208 if (maxima_number_ > 0)
210 for (
int i = 0; i < maxima_number_; i++)
212 bool good_maximum =
true;
214 PointT* p_current = &(*cloud_)[maxima_cloud_indices_[i]];
215 Eigen::Vector3f p_current_eigen(p_current->x, p_current->y, p_current->z);
216 float t = p_current_eigen.dot(ground_coeffs_.head<3>()) / std::pow(sqrt_ground_coeffs_, 2);
217 p_current_eigen -= ground_coeffs_.head<3>() * t;
220 while ((j >= 0) && (good_maximum))
222 PointT* p_previous = &(*cloud_)[maxima_cloud_indices_[j]];
223 Eigen::Vector3f p_previous_eigen(p_previous->x, p_previous->y, p_previous->z);
224 float t = p_previous_eigen.dot(ground_coeffs_.head<3>()) / std::pow(sqrt_ground_coeffs_, 2);
225 p_previous_eigen -= ground_coeffs_.head<3>() * t;
228 float distance = (p_current_eigen-p_previous_eigen).norm();
229 if (
distance < min_dist_between_maxima_)
231 good_maximum =
false;
237 maxima_indices_filtered_[maxima_number_after_filtering_] = maxima_indices_[i];
238 maxima_cloud_indices_filtered_[maxima_number_after_filtering_] = maxima_cloud_indices_[i];
239 maxima_number_after_filtering_++;
245 template <
typename Po
intT>
void
251 template <
typename Po
intT>
254 ground_coeffs_ = ground_coeffs;
255 sqrt_ground_coeffs_ = (ground_coeffs - Eigen::Vector4f(0.0f, 0.0f, 0.0f, ground_coeffs(3))).norm();
258 template <
typename Po
intT>
void
261 bin_size_ = bin_size;
264 template <
typename Po
intT>
void
267 min_dist_between_maxima_ = minimum_distance_between_maxima;
270 template <
typename Po
intT>
void
273 vertical_ = vertical;
276 template <
typename Po
intT> std::vector<int>&
282 template <
typename Po
intT>
float
288 template <
typename Po
intT>
float
291 return (min_dist_between_maxima_);
294 template <
typename Po
intT>
int&
297 return (maxima_number_after_filtering_);
300 template <
typename Po
intT> std::vector<int>&
303 return (maxima_cloud_indices_filtered_);
306 template <
typename Po
intT>
void filterMaxima()
Filter maxima of the height map by imposing a minimum distance between them.
HeightMap2D()
Constructor.
void searchLocalMaxima()
Compute local maxima of the height map.
typename PointCloud::Ptr PointCloudPtr
std::vector< int > & getMaximaCloudIndicesFiltered()
Return the point cloud indices corresponding to the maxima computed after the filterMaxima method.
void setBinSize(float bin_size)
Set bin size for the height map.
float getBinSize()
Get bin size for the height map.
void setInputCloud(PointCloudPtr &cloud)
Set initial cluster indices.
void setSensorPortraitOrientation(bool vertical)
Set sensor orientation to landscape mode (false) or portrait mode (true).
int & getMaximaNumberAfterFiltering()
Return the maxima number after the filterMaxima method.
void setGround(Eigen::VectorXf &ground_coeffs)
Set the ground coefficients.
virtual ~HeightMap2D()
Destructor.
std::vector< int > & getHeightMap()
Get the height map as a vector of int.
void compute(pcl::people::PersonCluster< PointT > &cluster)
Compute the height map with the projection of cluster points onto the ground plane.
float getMinimumDistanceBetweenMaxima()
Get minimum distance between maxima of the height map.
void setMinimumDistanceBetweenMaxima(float minimum_distance_between_maxima)
Set minimum distance between maxima.
PersonCluster represents a class for representing information about a cluster containing a person.
pcl::PointIndices & getIndices()
Returns the indices of the point cloud points corresponding to the cluster.
Eigen::Vector3f & getMin()
Returns the point formed by min x, min y and min z.
Eigen::Vector3f & getMax()
Returns the point formed by max x, max y and max z.
float distance(const PointT &p1, const PointT &p2)
A point structure representing Euclidean xyz coordinates, and the RGB color.