Skip to content

Commit 28e6312

Browse files
authored
Merge pull request #5181 from kunaltyagi/fix.centroid-zero
Ensure centroid/cov_mat are modified only when needed
2 parents 5871c90 + 3fdae3a commit 28e6312

1 file changed

Lines changed: 65 additions & 42 deletions

File tree

common/include/pcl/common/impl/centroid.hpp

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,9 @@ template <typename PointT, typename Scalar> inline unsigned int
5656
compute3DCentroid (ConstCloudIterator<PointT> &cloud_iterator,
5757
Eigen::Matrix<Scalar, 4, 1> &centroid)
5858
{
59-
// Initialize to 0
60-
centroid.setZero ();
59+
Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
6160

62-
unsigned cp = 0;
61+
unsigned int cp = 0;
6362

6463
// For each point in the cloud
6564
// If the data is dense, we don't need to check for NaN
@@ -68,15 +67,19 @@ compute3DCentroid (ConstCloudIterator<PointT> &cloud_iterator,
6867
// Check if the point is invalid
6968
if (pcl::isFinite (*cloud_iterator))
7069
{
71-
centroid[0] += cloud_iterator->x;
72-
centroid[1] += cloud_iterator->y;
73-
centroid[2] += cloud_iterator->z;
70+
accumulator[0] += cloud_iterator->x;
71+
accumulator[1] += cloud_iterator->y;
72+
accumulator[2] += cloud_iterator->z;
7473
++cp;
7574
}
7675
++cloud_iterator;
7776
}
78-
centroid /= static_cast<Scalar> (cp);
79-
centroid[3] = 1;
77+
78+
if (cp > 0) {
79+
centroid = accumulator;
80+
centroid /= static_cast<Scalar> (cp);
81+
centroid[3] = 1;
82+
}
8083
return (cp);
8184
}
8285

@@ -88,12 +91,12 @@ compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
8891
if (cloud.empty ())
8992
return (0);
9093

91-
// Initialize to 0
92-
centroid.setZero ();
9394
// For each point in the cloud
9495
// If the data is dense, we don't need to check for NaN
9596
if (cloud.is_dense)
9697
{
98+
// Initialize to 0
99+
centroid.setZero ();
97100
for (const auto& point: cloud)
98101
{
99102
centroid[0] += point.x;
@@ -106,20 +109,24 @@ compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
106109
return (static_cast<unsigned int> (cloud.size ()));
107110
}
108111
// NaN or Inf values could exist => check for them
109-
unsigned cp = 0;
112+
unsigned int cp = 0;
113+
Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
110114
for (const auto& point: cloud)
111115
{
112116
// Check if the point is invalid
113117
if (!isFinite (point))
114118
continue;
115119

116-
centroid[0] += point.x;
117-
centroid[1] += point.y;
118-
centroid[2] += point.z;
120+
accumulator[0] += point.x;
121+
accumulator[1] += point.y;
122+
accumulator[2] += point.z;
119123
++cp;
120124
}
121-
centroid /= static_cast<Scalar> (cp);
122-
centroid[3] = 1;
125+
if (cp > 0) {
126+
centroid = accumulator;
127+
centroid /= static_cast<Scalar> (cp);
128+
centroid[3] = 1;
129+
}
123130

124131
return (cp);
125132
}
@@ -133,11 +140,11 @@ compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
133140
if (indices.empty ())
134141
return (0);
135142

136-
// Initialize to 0
137-
centroid.setZero ();
138143
// If the data is dense, we don't need to check for NaN
139144
if (cloud.is_dense)
140145
{
146+
// Initialize to 0
147+
centroid.setZero ();
141148
for (const auto& index : indices)
142149
{
143150
centroid[0] += cloud[index].x;
@@ -149,20 +156,24 @@ compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
149156
return (static_cast<unsigned int> (indices.size ()));
150157
}
151158
// NaN or Inf values could exist => check for them
152-
unsigned cp = 0;
159+
Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
160+
unsigned int cp = 0;
153161
for (const auto& index : indices)
154162
{
155163
// Check if the point is invalid
156164
if (!isFinite (cloud [index]))
157165
continue;
158166

159-
centroid[0] += cloud[index].x;
160-
centroid[1] += cloud[index].y;
161-
centroid[2] += cloud[index].z;
167+
accumulator[0] += cloud[index].x;
168+
accumulator[1] += cloud[index].y;
169+
accumulator[2] += cloud[index].z;
162170
++cp;
163171
}
164-
centroid /= static_cast<Scalar> (cp);
165-
centroid[3] = 1;
172+
if (cp > 0) {
173+
centroid = accumulator;
174+
centroid /= static_cast<Scalar> (cp);
175+
centroid[3] = 1;
176+
}
166177
return (cp);
167178
}
168179

@@ -184,13 +195,11 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
184195
if (cloud.empty ())
185196
return (0);
186197

187-
// Initialize to 0
188-
covariance_matrix.setZero ();
189-
190198
unsigned point_count;
191199
// If the data is dense, we don't need to check for NaN
192200
if (cloud.is_dense)
193201
{
202+
covariance_matrix.setZero ();
194203
point_count = static_cast<unsigned> (cloud.size ());
195204
// For each point in the cloud
196205
for (const auto& point: cloud)
@@ -214,6 +223,8 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
214223
// NaN or Inf values could exist => check for them
215224
else
216225
{
226+
Eigen::Matrix<Scalar, 3, 3> temp_covariance_matrix;
227+
temp_covariance_matrix.setZero();
217228
point_count = 0;
218229
// For each point in the cloud
219230
for (const auto& point: cloud)
@@ -227,17 +238,23 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
227238
pt[1] = point.y - centroid[1];
228239
pt[2] = point.z - centroid[2];
229240

230-
covariance_matrix (1, 1) += pt.y () * pt.y ();
231-
covariance_matrix (1, 2) += pt.y () * pt.z ();
241+
temp_covariance_matrix (1, 1) += pt.y () * pt.y ();
242+
temp_covariance_matrix (1, 2) += pt.y () * pt.z ();
232243

233-
covariance_matrix (2, 2) += pt.z () * pt.z ();
244+
temp_covariance_matrix (2, 2) += pt.z () * pt.z ();
234245

235246
pt *= pt.x ();
236-
covariance_matrix (0, 0) += pt.x ();
237-
covariance_matrix (0, 1) += pt.y ();
238-
covariance_matrix (0, 2) += pt.z ();
247+
temp_covariance_matrix (0, 0) += pt.x ();
248+
temp_covariance_matrix (0, 1) += pt.y ();
249+
temp_covariance_matrix (0, 2) += pt.z ();
239250
++point_count;
240251
}
252+
if (point_count > 0) {
253+
covariance_matrix = temp_covariance_matrix;
254+
}
255+
}
256+
if (point_count == 0) {
257+
return 0;
241258
}
242259
covariance_matrix (1, 0) = covariance_matrix (0, 1);
243260
covariance_matrix (2, 0) = covariance_matrix (0, 2);
@@ -268,13 +285,11 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
268285
if (indices.empty ())
269286
return (0);
270287

271-
// Initialize to 0
272-
covariance_matrix.setZero ();
273-
274288
std::size_t point_count;
275289
// If the data is dense, we don't need to check for NaN
276290
if (cloud.is_dense)
277291
{
292+
covariance_matrix.setZero ();
278293
point_count = indices.size ();
279294
// For each point in the cloud
280295
for (const auto& idx: indices)
@@ -298,6 +313,8 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
298313
// NaN or Inf values could exist => check for them
299314
else
300315
{
316+
Eigen::Matrix<Scalar, 3, 3> temp_covariance_matrix;
317+
temp_covariance_matrix.setZero ();
301318
point_count = 0;
302319
// For each point in the cloud
303320
for (const auto &index : indices)
@@ -311,17 +328,23 @@ computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
311328
pt[1] = cloud[index].y - centroid[1];
312329
pt[2] = cloud[index].z - centroid[2];
313330

314-
covariance_matrix (1, 1) += pt.y () * pt.y ();
315-
covariance_matrix (1, 2) += pt.y () * pt.z ();
331+
temp_covariance_matrix (1, 1) += pt.y () * pt.y ();
332+
temp_covariance_matrix (1, 2) += pt.y () * pt.z ();
316333

317-
covariance_matrix (2, 2) += pt.z () * pt.z ();
334+
temp_covariance_matrix (2, 2) += pt.z () * pt.z ();
318335

319336
pt *= pt.x ();
320-
covariance_matrix (0, 0) += pt.x ();
321-
covariance_matrix (0, 1) += pt.y ();
322-
covariance_matrix (0, 2) += pt.z ();
337+
temp_covariance_matrix (0, 0) += pt.x ();
338+
temp_covariance_matrix (0, 1) += pt.y ();
339+
temp_covariance_matrix (0, 2) += pt.z ();
323340
++point_count;
324341
}
342+
if (point_count > 0) {
343+
covariance_matrix = temp_covariance_matrix;
344+
}
345+
}
346+
if (point_count == 0) {
347+
return 0;
325348
}
326349
covariance_matrix (1, 0) = covariance_matrix (0, 1);
327350
covariance_matrix (2, 0) = covariance_matrix (0, 2);

0 commit comments

Comments
 (0)