@@ -47,7 +47,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::initializeVoxelGrid ()
4747{
4848 // initialization set to true
4949 initialized_ = true ;
50-
50+
5151 // create the voxel grid and store the output cloud
5252 this ->filter (filtered_cloud_);
5353
@@ -162,13 +162,13 @@ pcl::VoxelGridOcclusionEstimation<PointT>::occlusionEstimationAll (std::vector<E
162162 Eigen::Vector4f p = getCentroidCoordinate (ijk);
163163 Eigen::Vector4f direction = p - sensor_origin_;
164164 direction.normalize ();
165-
165+
166166 // estimate entry point into the voxel grid
167167 float tmin = rayBoxIntersection (sensor_origin_, direction);
168168
169169 // ray traversal
170170 int state = rayTraversal (ijk, sensor_origin_, direction, tmin);
171-
171+
172172 // if voxel is occluded
173173 if (state == 1 )
174174 occluded_voxels.push_back (ijk);
@@ -179,7 +179,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::occlusionEstimationAll (std::vector<E
179179
180180// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181181template <typename PointT> float
182- pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vector4f& origin,
182+ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vector4f& origin,
183183 const Eigen::Vector4f& direction)
184184{
185185 float tmin, tmax, tymin, tymax, tzmin, tzmax;
@@ -198,7 +198,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
198198 if (direction[1 ] >= 0 )
199199 {
200200 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 ];
202202 }
203203 else
204204 {
@@ -233,7 +233,7 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
233233 {
234234 PCL_ERROR (" no intersection with the bounding box \n " );
235235 tmin = -1 .0f ;
236- return tmin;
236+ return tmin;
237237 }
238238
239239 if (tzmin > tmin)
@@ -246,15 +246,16 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayBoxIntersection (const Eigen::Vect
246246// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
247247template <typename PointT> int
248248pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i& target_voxel,
249- const Eigen::Vector4f& origin,
249+ const Eigen::Vector4f& origin,
250250 const Eigen::Vector4f& direction,
251251 const float t_min)
252252{
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;
255256
256257 // 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 ]);
258259
259260 // steps in which direction we have to travel in the voxel grid
260261 int step_x, step_y, step_z;
@@ -296,13 +297,13 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i&
296297 float t_max_x = t_min + (voxel_max[0 ] - start[0 ]) / direction[0 ];
297298 float t_max_y = t_min + (voxel_max[1 ] - start[1 ]) / direction[1 ];
298299 float t_max_z = t_min + (voxel_max[2 ] - start[2 ]) / direction[2 ];
299-
300+
300301 float t_delta_x = leaf_size_[0 ] / static_cast <float > (std::abs (direction[0 ]));
301302 float t_delta_y = leaf_size_[1 ] / static_cast <float > (std::abs (direction[1 ]));
302303 float t_delta_z = leaf_size_[2 ] / static_cast <float > (std::abs (direction[2 ]));
303304
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 ]) &&
306307 (ijk[2 ] < max_b_[2 ]+1 ) && (ijk[2 ] >= min_b_[2 ]) )
307308 {
308309 // check if we reached target voxel
@@ -339,20 +340,20 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (const Eigen::Vector3i&
339340template <typename PointT> int
340341pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (std::vector<Eigen::Vector3i, Eigen::aligned_allocator<Eigen::Vector3i> >& out_ray,
341342 const Eigen::Vector3i& target_voxel,
342- const Eigen::Vector4f& origin,
343+ const Eigen::Vector4f& origin,
343344 const Eigen::Vector4f& direction,
344345 const float t_min)
345346{
346347 // reserve space for the ray vector
347348 int reserve_size = div_b_.maxCoeff () * div_b_.maxCoeff ();
348349 out_ray.reserve (reserve_size);
349350
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;
352354
353355 // 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 ]);
356357
357358 // steps in which direction we have to travel in the voxel grid
358359 int step_x, step_y, step_z;
@@ -394,16 +395,16 @@ pcl::VoxelGridOcclusionEstimation<PointT>::rayTraversal (std::vector<Eigen::Vect
394395 float t_max_x = t_min + (voxel_max[0 ] - start[0 ]) / direction[0 ];
395396 float t_max_y = t_min + (voxel_max[1 ] - start[1 ]) / direction[1 ];
396397 float t_max_z = t_min + (voxel_max[2 ] - start[2 ]) / direction[2 ];
397-
398+
398399 float t_delta_x = leaf_size_[0 ] / static_cast <float > (std::abs (direction[0 ]));
399400 float t_delta_y = leaf_size_[1 ] / static_cast <float > (std::abs (direction[1 ]));
400401 float t_delta_z = leaf_size_[2 ] / static_cast <float > (std::abs (direction[2 ]));
401402
402403 // the index of the cloud (-1 if empty)
403404 int result = 0 ;
404405
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 ]) &&
407408 (ijk[2 ] < max_b_[2 ]+1 ) && (ijk[2 ] >= min_b_[2 ]) )
408409 {
409410 // add voxel to ray
0 commit comments