38 #include <visualization_msgs/Marker.h> 40 #include <boost/iostreams/filtering_stream.hpp> 41 #include <boost/iostreams/copy.hpp> 42 #include <boost/iostreams/filter/zlib.hpp> 47 double origin_x,
double origin_y,
double origin_z,
48 double max_distance,
bool propagate_negative)
49 :
DistanceField(size_x, size_y, size_z, resolution, origin_x, origin_y, origin_z)
50 , propagate_negative_(propagate_negative)
51 , max_distance_(max_distance)
58 bool propagate_negative_distances)
59 :
DistanceField(bbx_max.
x() - bbx_min.
x(), bbx_max.
y() - bbx_min.
y(), bbx_max.
z() - bbx_min.
z(),
70 bool propagate_negative_distances)
98 VoxelSet::const_iterator it;
99 for (it =
set.begin(); it !=
set.end(); ++it)
101 Eigen::Vector3i loc1 = *it;
102 ROS_DEBUG_NAMED(
"distance_field",
"%d, %d, %d ", loc1.x(), loc1.y(), loc1.z());
104 ROS_DEBUG_NAMED(
"distance_field",
"] size=%u\n", (
unsigned int)
set.size());
110 EigenSTL::vector_Vector3d::const_iterator it;
111 for (it = points.begin(); it != points.end(); ++it)
114 ROS_DEBUG_NAMED(
"distance_field",
"%g, %g, %g ", loc1.x(), loc1.y(), loc1.z());
116 ROS_DEBUG_NAMED(
"distance_field",
"] size=%u\n", (
unsigned int)points.size());
123 for (
unsigned int i = 0; i < old_points.size(); i++)
125 Eigen::Vector3i voxel_loc;
126 bool valid =
worldToGrid(old_points[i].
x(), old_points[i].
y(), old_points[i].
z(), voxel_loc.x(), voxel_loc.y(),
130 old_point_set.insert(voxel_loc);
135 for (
unsigned int i = 0; i < new_points.size(); i++)
137 Eigen::Vector3i voxel_loc;
138 bool valid =
worldToGrid(new_points[i].
x(), new_points[i].
y(), new_points[i].
z(), voxel_loc.x(), voxel_loc.y(),
142 new_point_set.insert(voxel_loc);
148 std::set_difference(old_point_set.begin(), old_point_set.end(), new_point_set.begin(), new_point_set.end(),
149 std::inserter(old_not_new, old_not_new.end()), comp);
152 std::set_difference(new_point_set.begin(), new_point_set.end(), old_point_set.begin(), old_point_set.end(),
153 std::inserter(new_not_old, new_not_old.end()), comp);
156 for (
unsigned int i = 0; i < new_not_old.size(); i++)
158 if (
voxel_grid_->getCell(new_not_old[i].x(), new_not_old[i].y(), new_not_old[i].z()).distance_square_ != 0)
160 new_not_in_current.push_back(new_not_old[i]);
181 for (
unsigned int i = 0; i < points.size(); i++)
184 Eigen::Vector3i voxel_loc;
185 bool valid =
worldToGrid(points[i].
x(), points[i].
y(), points[i].
z(), voxel_loc.x(), voxel_loc.y(), voxel_loc.z());
189 if (
voxel_grid_->getCell(voxel_loc.x(), voxel_loc.y(), voxel_loc.z()).distance_square_ > 0)
191 voxel_points.push_back(voxel_loc);
203 for (
unsigned int i = 0; i < points.size(); i++)
206 Eigen::Vector3i voxel_loc;
207 bool valid =
worldToGrid(points[i].
x(), points[i].
y(), points[i].
z(), voxel_loc.x(), voxel_loc.y(), voxel_loc.z());
211 voxel_points.push_back(voxel_loc);
232 for (
unsigned int i = 0; i < voxel_points.size(); i++)
235 const Eigen::Vector3i& loc = voxel_points[i];
246 negative_stack.push_back(loc);
253 while (!negative_stack.empty())
255 Eigen::Vector3i loc = negative_stack.back();
256 negative_stack.pop_back();
258 for (
int neighbor = 0; neighbor < 27; neighbor++)
261 Eigen::Vector3i nloc(loc.x() + diff.x(), loc.y() + diff.y(), loc.z() + diff.z());
267 if (!
isCellValid(close_point.x(), close_point.y(), close_point.z()))
272 voxel_grid_->getCell(close_point.x(), close_point.y(), close_point.z());
287 negative_stack.push_back(nloc);
326 for (
unsigned int i = 0; i < voxel_points.size(); i++)
332 stack.push_back(voxel_points[i]);
343 while (!stack.empty())
345 Eigen::Vector3i loc = stack.back();
348 for (
int neighbor = 0; neighbor < 27; neighbor++)
351 Eigen::Vector3i nloc(loc.x() + diff.x(), loc.y() + diff.y(), loc.z() + diff.z());
357 if (!
isCellValid(close_point.x(), close_point.y(), close_point.z()))
362 voxel_grid_->getCell(close_point.x(), close_point.y(), close_point.z());
371 stack.push_back(nloc);
395 EigenSTL::vector_Vector3i::iterator list_it =
bucket_queue_[i].begin();
396 EigenSTL::vector_Vector3i::iterator list_end =
bucket_queue_[i].end();
397 for (; list_it != list_end; ++list_it)
399 const Eigen::Vector3i& loc = *list_it;
411 ROS_ERROR_NAMED(
"distance_field",
"PROGRAMMING ERROR: Invalid update direction detected: %d",
418 for (
unsigned int n = 0; n < neighborhood->size(); n++)
420 Eigen::Vector3i
diff = (*neighborhood)[n];
421 Eigen::Vector3i nloc(loc.x() + diff.x(), loc.y() + diff.y(), loc.z() + diff.z());
428 int new_distance_sq = (vptr->
closest_point_ - nloc).squaredNorm();
432 if (new_distance_sq < neighbor->distance_square_)
455 for (; list_it != list_end; ++list_it)
457 const Eigen::Vector3i& loc = *list_it;
470 ROS_ERROR_NAMED(
"distance_field",
"PROGRAMMING ERROR: Invalid update direction detected: %d",
477 for (
unsigned int n = 0; n < neighborhood->size(); n++)
479 Eigen::Vector3i
diff = (*neighborhood)[n];
480 Eigen::Vector3i nloc(loc.x() + diff.x(), loc.y() + diff.y(), loc.z() + diff.z());
492 if (new_distance_sq < neighbor->negative_distance_square_)
534 for (
int dx = -1; dx <= 1; ++dx)
536 for (
int dy = -1; dy <= 1; ++dy)
538 for (
int dz = -1; dz <= 1; ++dz)
541 Eigen::Vector3i n_point(dx, dy, dz);
548 for (
int n = 0; n < 2; n++)
552 for (
int dx = -1; dx <= 1; ++dx)
554 for (
int dy = -1; dy <= 1; ++dy)
556 for (
int dz = -1; dz <= 1; ++dz)
560 for (
int tdx = -1; tdx <= 1; ++tdx)
562 for (
int tdy = -1; tdy <= 1; ++tdy)
564 for (
int tdz = -1; tdz <= 1; ++tdz)
566 if (tdx == 0 && tdy == 0 && tdz == 0)
570 if ((
abs(tdx) +
abs(tdy) +
abs(tdz)) != 1)
572 if (dx * tdx < 0 || dy * tdy < 0 || dz * tdz < 0)
575 Eigen::Vector3i n_point(tdx, tdy, tdz);
590 return (dx + 1) * 9 + (dy + 1) * 3 + dz + 1;
630 voxel_grid_->gridToWorld(x, y, z, world_x, world_y, world_z);
636 return voxel_grid_->worldToGrid(world_x, world_y, world_z, x, y, z);
642 os <<
"size_x: " <<
size_x_ << std::endl;
643 os <<
"size_y: " <<
size_y_ << std::endl;
644 os <<
"size_z: " <<
size_z_ << std::endl;
645 os <<
"origin_x: " <<
origin_x_ << std::endl;
646 os <<
"origin_y: " <<
origin_y_ << std::endl;
647 os <<
"origin_z: " <<
origin_z_ << std::endl;
651 boost::iostreams::filtering_ostream out;
652 out.push(boost::iostreams::zlib_compressor());
655 for (
unsigned int x = 0; x < static_cast<unsigned int>(
getXNumCells());
x++)
657 for (
unsigned int y = 0; y < static_cast<unsigned int>(
getYNumCells());
y++)
659 for (
unsigned int z = 0; z < static_cast<unsigned int>(
getZNumCells());
z += 8)
661 std::bitset<8> bs(0);
662 unsigned int zv = std::min((
unsigned int)8,
getZNumCells() - z);
663 for (
unsigned int zi = 0; zi < zv; zi++)
665 if (
getCell(
x,
y, z + zi).distance_square_ == 0)
671 out.write((
char*)&bs,
sizeof(
char));
687 if (temp !=
"resolution:")
692 if (temp !=
"size_x:")
697 if (temp !=
"size_y:")
702 if (temp !=
"size_z:")
707 if (temp !=
"origin_x:")
712 if (temp !=
"origin_y:")
717 if (temp !=
"origin_z:")
730 boost::iostreams::filtering_istream in;
731 in.push(boost::iostreams::zlib_decompressor());
737 for (
unsigned int x = 0; x < static_cast<unsigned int>(
getXNumCells());
x++)
739 for (
unsigned int y = 0; y < static_cast<unsigned int>(
getYNumCells());
y++)
741 for (
unsigned int z = 0; z < static_cast<unsigned int>(
getZNumCells());
z += 8)
749 std::bitset<8> inbit((
unsigned long long)inchar);
750 unsigned int zv = std::min((
unsigned int)8,
getZNumCells() - z);
751 for (
unsigned int zi = 0; zi < zv; zi++)
756 obs_points.push_back(Eigen::Vector3i(
x,
y, z + zi));
bool propagate_negative_
Whether or not to propagate negative distances.
Eigen::Vector3i getLocationDifference(int directionNumber) const
Helper function that gets change values given single number representing update direction.
int getZNumCells() const override
Gets the number of cells along the Z axis.
Vec3fX< details::Vec3Data< double > > Vector3d
bool writeToStream(std::ostream &stream) const override
Writes the contents of the distance field to the supplied stream.
std::vector< Eigen::Vector3d, Eigen::aligned_allocator< Eigen::Vector3d > > vector_Vector3d
const PropDistanceFieldVoxel & getCell(int x, int y, int z) const
Gets full cell data given an index.
int distance_square_
Distance in cells to the closest obstacle, squared.
std::vector< EigenSTL::vector_Vector3i > bucket_queue_
Structure used to hold propagation frontier.
std::vector< std::vector< EigenSTL::vector_Vector3i > > neighborhoods_
Holds information on neighbor direction, with 27 different directions. Shows where to propagate given...
int update_direction_
Direction from which this voxel was updated for occupied distance propagation.
Structure that holds voxel information for the DistanceField. Will be used in VoxelGrid.
double size_x_
X size of the distance field.
bool gridToWorld(int x, int y, int z, double &world_x, double &world_y, double &world_z) const override
Converts from an set of integer indices to a world location given the origin and resolution parameter...
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
VoxelGrid holds a dense 3D, axis-aligned set of data at a given resolution, where the data is supplie...
Struct for sorting type Eigen::Vector3i for use in sorted std containers. Sorts in z order...
PropagationDistanceField(double size_x, double size_y, double size_z, double resolution, double origin_x, double origin_y, double origin_z, double max_distance, bool propagate_negative_distances=false)
Constructor that initializes entire distance field to empty - all cells will be assigned maximum dist...
void addPointsToField(const EigenSTL::vector_Vector3d &points) override
Add a set of obstacle points to the distance field, updating distance values accordingly. The distance field may already contain obstacle cells.
Eigen::Vector3i closest_point_
Closest occupied cell.
Eigen::Vector3i closest_negative_point_
Closest unoccupied cell.
bool isCellValid(int x, int y, int z) const override
Determines whether or not the cell associated with the supplied indices is valid for this distance fi...
static const int UNINITIALIZED
Value that represents an unitialized voxel.
void print(const VoxelSet &set)
Debug function that prints all voxels in a set to ROS_DEBUG_NAMED.
int getXNumCells() const override
Gets the number of cells along the X axis.
double origin_y_
Y origin of the distance field.
bool readFromStream(std::istream &stream) override
Reads, parameterizes, and populates the distance field based on the supplied stream.
#define ROS_DEBUG_NAMED(name,...)
std::vector< EigenSTL::vector_Vector3i > negative_bucket_queue_
Data member that holds points from which to propagate in the negative, where each vector holds points...
DistanceField is an abstract base class for computing distances from sets of 3D obstacle points...
void propagateNegative()
Propagates inward to a maximum distance given the contents of the negative_bucket_queue_, and clears the negative_bucket_queue_.
double size_z_
Z size of the distance field.
void reset() override
Resets the entire distance field to max_distance for positive values and zero for negative values...
VoxelGrid< PropDistanceFieldVoxel >::Ptr voxel_grid_
Actual container for distance data.
bool worldToGrid(double world_x, double world_y, double world_z, int &x, int &y, int &z) const override
Converts from a world location to a set of integer indices. Should return false if the world location...
double origin_z_
Z origin of the distance field.
std::vector< Eigen::Vector3i, Eigen::aligned_allocator< Eigen::Vector3i > > vector_Vector3i
int getYNumCells() const override
Gets the number of cells along the Y axis.
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
void propagatePositive()
Propagates outward to the maximum distance given the contents of the bucket_queue_, and clears the bucket_queue_.
double getResolution() const
Gets the resolution of the distance field in meters.
Namespace for holding classes that generate distance fields.
double origin_x_
X origin of the distance field.
double max_distance_
Holds maximum distance.
void updatePointsInField(const EigenSTL::vector_Vector3d &old_points, const EigenSTL::vector_Vector3d &new_points) override
This function will remove any obstacle points that are in the old point set but not the new point set...
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
EigenSTL::vector_Vector3i direction_number_to_direction_
Holds conversion from direction number to integer changes.
double getDistance(double x, double y, double z) const override
Get the distance value associated with the cell indicated by the world coordinate. If the cell is invalid, max_distance will be returned. If running without negative distances, all obstacle cells will have zero distance. If running with negative distances, the distance will be between -max_distance and max_distance, with no values having a 0 distance.
void initialize()
Initializes the field, resetting the voxel grid and building a sqrt lookup table for efficiency based...
void removePointsFromField(const EigenSTL::vector_Vector3d &points) override
Remove a set of obstacle points from the distance field, updating distance values accordingly...
int negative_distance_square_
Distance in cells to the nearest unoccupied cell, squared.
int getDirectionNumber(int dx, int dy, int dz) const
Helper function to get a single number in a 27 connected 3D voxel grid given dx, dy, and dz values.
#define ROS_ERROR_NAMED(name,...)
std::vector< double > sqrt_table_
Precomputed square root table for faster distance lookups.
std::set< Eigen::Vector3i, compareEigen_Vector3i, Eigen::aligned_allocator< Eigen::Vector3i > > VoxelSet
void removeObstacleVoxels(const EigenSTL::vector_Vector3i &voxel_points)
Removes a valid set of integer points from the voxel grid.
void addOcTreeToField(const octomap::OcTree *octree)
Adds an octree to the distance field. Cells that are occupied in the octree that lie within the voxel...
int negative_update_direction_
Direction from which this voxel was updated for negative distance propagation.
double resolution_
Resolution of the distance field.
double size_y_
Y size of the distance field.
int max_distance_sq_
Holds maximum distance squared in cells.
void addNewObstacleVoxels(const EigenSTL::vector_Vector3i &voxel_points)
Adds a valid set of integer points to the voxel grid.
void initNeighborhoods()
Helper function for computing location and neighborhood information in 27 connected voxel grid...