@@ -47,7 +47,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::initializeVoxelGrid ()
47
47
{
48
48
// initialization set to true
49
49
initialized_ = true ;
50
-
50
+
51
51
// create the voxel grid and store the output cloud
52
52
this ->filter (filtered_cloud_);
53
53
@@ -162,13 +162,13 @@ pcl::VoxelGridOcclusionEstimation<PointT>::occlusionEstimationAll (std::vector<E
162
162
Eigen::Vector4f p = getCentroidCoordinate (ijk);
163
163
Eigen::Vector4f direction = p - sensor_origin_;
164
164
direction.normalize ();
165
-
165
+
166
166
// estimate entry point into the voxel grid
167
167
float tmin = rayBoxIntersection (sensor_origin_, direction);
168
168
169
169
// ray traversal
170
170
int state = rayTraversal (ijk, sensor_origin_, direction, tmin);
171
-
171
+
172
172
// if voxel is occluded
173
173
if (state == 1 )
174
174
occluded_voxels.push_back (ijk);
@@ -179,7 +179,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::occlusionEstimationAll (std::vector<E
179
179
180
180
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181
181
template <typename PointT> float
182
- pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vector4f& origin,
182
+ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vector4f& origin,
183
183
const Eigen::Vector4f& direction)
184
184
{
185
185
float tmin, tmax, tymin, tymax, tzmin, tzmax;
@@ -198,7 +198,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
198
198
if (direction[1 ] >= 0 )
199
199
{
200
200
tymin = (b_min_[1 ] - origin[1 ]) / direction[1 ];
201
- tymax = (b_max_[1 ] - origin[1 ]) / direction[1 ];
201
+ tymax = (b_max_[1 ] - origin[1 ]) / direction[1 ];
202
202
}
203
203
else
204
204
{
@@ -233,7 +233,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
233
233
{
234
234
PCL_ERROR (" no intersection with the bounding box \n " );
235
235
tmin = -1 .0f ;
236
- return tmin;
236
+ return tmin;
237
237
}
238
238
239
239
if (tzmin > tmin)
@@ -246,15 +246,16 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
246
246
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
247
247
template <typename PointT> int
248
248
pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i& target_voxel,
249
- const Eigen::Vector4f& origin,
249
+ const Eigen::Vector4f& origin,
250
250
const Eigen::Vector4f& direction,
251
251
const float t_min)
252
252
{
253
- // coordinate of the boundary of the voxel grid
254
- Eigen::Vector4f start = origin + t_min * direction;
253
+ // coordinate of the boundary of the voxel grid. To avoid numerical imprecision
254
+ // causing the start voxel index to be off by one, we add the machine epsilon
255
+ Eigen::Vector4f start = origin + (t_min > 0 .0f ? (t_min + std::numeric_limits<float >::epsilon ()) : t_min) * direction;
255
256
256
257
// i,j,k coordinate of the voxel were the ray enters the voxel grid
257
- Eigen::Vector3i ijk = getGridCoordinatesRound (start[0 ], start[1 ], start[2 ]);
258
+ Eigen::Vector3i ijk = this -> getGridCoordinates (start[0 ], start[1 ], start[2 ]);
258
259
259
260
// steps in which direction we have to travel in the voxel grid
260
261
int step_x, step_y, step_z;
@@ -296,13 +297,13 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i&
296
297
float t_max_x = t_min + (voxel_max[0 ] - start[0 ]) / direction[0 ];
297
298
float t_max_y = t_min + (voxel_max[1 ] - start[1 ]) / direction[1 ];
298
299
float t_max_z = t_min + (voxel_max[2 ] - start[2 ]) / direction[2 ];
299
-
300
+
300
301
float t_delta_x = leaf_size_[0 ] / static_cast <float > (std::abs (direction[0 ]));
301
302
float t_delta_y = leaf_size_[1 ] / static_cast <float > (std::abs (direction[1 ]));
302
303
float t_delta_z = leaf_size_[2 ] / static_cast <float > (std::abs (direction[2 ]));
303
304
304
- while ( (ijk[0 ] < max_b_[0 ]+1 ) && (ijk[0 ] >= min_b_[0 ]) &&
305
- (ijk[1 ] < max_b_[1 ]+1 ) && (ijk[1 ] >= min_b_[1 ]) &&
305
+ while ( (ijk[0 ] < max_b_[0 ]+1 ) && (ijk[0 ] >= min_b_[0 ]) &&
306
+ (ijk[1 ] < max_b_[1 ]+1 ) && (ijk[1 ] >= min_b_[1 ]) &&
306
307
(ijk[2 ] < max_b_[2 ]+1 ) && (ijk[2 ] >= min_b_[2 ]) )
307
308
{
308
309
// check if we reached target voxel
@@ -339,20 +340,20 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i&
339
340
template <typename PointT> int
340
341
pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i> >& out_ray,
341
342
const Eigen::Vector3i& target_voxel,
342
- const Eigen::Vector4f& origin,
343
+ const Eigen::Vector4f& origin,
343
344
const Eigen::Vector4f& direction,
344
345
const float t_min)
345
346
{
346
347
// reserve space for the ray vector
347
348
int reserve_size = div_b_.maxCoeff () * div_b_.maxCoeff ();
348
349
out_ray.reserve (reserve_size);
349
350
350
- // coordinate of the boundary of the voxel grid
351
- Eigen::Vector4f start = origin + t_min * direction;
351
+ // coordinate of the boundary of the voxel grid. To avoid numerical imprecision
352
+ // causing the start voxel index to be off by one, we add the machine epsilon
353
+ Eigen::Vector4f start = origin + (t_min > 0 .0f ? (t_min + std::numeric_limits<float >::epsilon ()) : t_min) * direction;
352
354
353
355
// i,j,k coordinate of the voxel were the ray enters the voxel grid
354
- Eigen::Vector3i ijk = getGridCoordinatesRound (start[0 ], start[1 ], start[2 ]);
355
- // Eigen::Vector3i ijk = this->getGridCoordinates (start_x, start_y, start_z);
356
+ Eigen::Vector3i ijk = this ->getGridCoordinates (start[0 ], start[1 ], start[2 ]);
356
357
357
358
// steps in which direction we have to travel in the voxel grid
358
359
int step_x, step_y, step_z;
@@ -394,16 +395,16 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (std::vector<Eigen::Vect
394
395
float t_max_x = t_min + (voxel_max[0 ] - start[0 ]) / direction[0 ];
395
396
float t_max_y = t_min + (voxel_max[1 ] - start[1 ]) / direction[1 ];
396
397
float t_max_z = t_min + (voxel_max[2 ] - start[2 ]) / direction[2 ];
397
-
398
+
398
399
float t_delta_x = leaf_size_[0 ] / static_cast <float > (std::abs (direction[0 ]));
399
400
float t_delta_y = leaf_size_[1 ] / static_cast <float > (std::abs (direction[1 ]));
400
401
float t_delta_z = leaf_size_[2 ] / static_cast <float > (std::abs (direction[2 ]));
401
402
402
403
// the index of the cloud (-1 if empty)
403
404
int result = 0 ;
404
405
405
- while ( (ijk[0 ] < max_b_[0 ]+1 ) && (ijk[0 ] >= min_b_[0 ]) &&
406
- (ijk[1 ] < max_b_[1 ]+1 ) && (ijk[1 ] >= min_b_[1 ]) &&
406
+ while ( (ijk[0 ] < max_b_[0 ]+1 ) && (ijk[0 ] >= min_b_[0 ]) &&
407
+ (ijk[1 ] < max_b_[1 ]+1 ) && (ijk[1 ] >= min_b_[1 ]) &&
407
408
(ijk[2 ] < max_b_[2 ]+1 ) && (ijk[2 ] >= min_b_[2 ]) )
408
409
{
409
410
// add voxel to ray
0 commit comments