voronoi_approximator.cpp
Go to the documentation of this file.
00001 
00038 #include <algorithm>
00039 #include <cmath>
00040 #include <cstdlib>
00041 
00042 #include <bwi_mapper/voronoi_approximator.h>
00043 #include <bwi_mapper/map_utils.h>
00044 #include <bwi_mapper/point_utils.h>
00045 
00046 namespace bwi_mapper {
00047 
00057   void VoronoiApproximator::findVoronoiPoints(double threshold, 
00058       bool is_naive, int sub_pixel_sampling) {
00059 
00060     // Get the inflated cost map
00061     inflateMap(threshold, map_resp_.map, inflated_map_);
00062 
00063     // Compute the voronoi points
00064     double pixel_threshold = 
00065       ceil(threshold / map_resp_.map.info.resolution);
00066 
00067     uint32_t max_dimension = 
00068       std::max(inflated_map_.info.height, inflated_map_.info.width);
00069 
00070     for (int j = 0; j < sub_pixel_sampling * (inflated_map_.info.height - 1); ++j) {
00071       if (j % sub_pixel_sampling == 0) {
00072         std::cout << "findVoronoiPoints(): On row : " << j / sub_pixel_sampling << std::endl;
00073       }
00074       for (int i = 0; i < sub_pixel_sampling * (inflated_map_.info.width - 1); 
00075           ++i) {
00076 
00077         Point2f center_pt((i + ((float)sub_pixel_sampling / 2)) / ((float)sub_pixel_sampling) + 0.001,
00078             (j + ((float)sub_pixel_sampling / 2)) / ((float)sub_pixel_sampling) + 0.001);
00079 
00080         // if (center_pt.x < inflated_map_.info.width / 2 ||
00081         //     i >= inflated_map_.info.width / 2 + 1)
00082         //   continue;
00083         // if (j < inflated_map_.info.height / 2 ||
00084         //     j >= inflated_map_.info.height / 2 + 1)
00085         //   continue;
00086 
00087         VoronoiPoint vp(lrint(center_pt.x), lrint(center_pt.y));
00088 
00089         // Check if this location is too close to a given obstacle
00090         uint32_t map_idx = MAP_IDX(inflated_map_.info.width, vp.x, vp.y);
00091         if (inflated_map_.data[map_idx] != 0) {
00092           continue;
00093         }
00094 
00095         /* std::cout << "Checking " << center_pt << ", will mark " << vp << std::endl; */
00096 
00097         // Use the boxes to find obstacles
00098         for (int box = pixel_threshold; box < max_dimension; ++box) {
00099 
00100           // Early termination crit - no more hope of finding more obstacles
00101           // at the same distance as the one found already
00102           if (vp.basis_points.size() != 0 &&
00103               box > vp.basis_distance + 1) {
00104             break;
00105           }
00106 
00107           // Get obstacles at this box size
00108           std::vector<Point2d> obstacles;
00109           int low_j = lrint(center_pt.y - box - 1);
00110           int high_j = lrint(center_pt.y + box);
00111           int low_i = lrint(center_pt.x - box - 1);
00112           int high_i = lrint(center_pt.x + box);
00113 
00114           /* std::cout << " - box " << box << " [" << low_i << "," << low_j << "," << high_i << "," << high_j << "]" << std::endl;  */
00115 
00116           // If we hit the side of the images + 1, we've seen all possible
00117           // sites
00118           if (low_i < 0 || low_j < 0 || 
00119               high_i >= inflated_map_.info.width 
00120               || high_j >= inflated_map_.info.height) {
00121             break;
00122           }
00123 
00124           // Corners of the box + vertical edges
00125           for (int j_box = low_j; j_box <= high_j; ++j_box) {
00126             for (int i_box = low_i; i_box <= high_i; 
00127                 i_box += high_i - low_i) {
00128               uint32_t map_idx_box = 
00129                 MAP_IDX(inflated_map_.info.width, i_box, j_box);
00130               bool occupied = map_resp_.map.data[map_idx_box];
00131               if (occupied) {
00132                 Point2d p(i_box, j_box);
00133                 Point2f f(i_box + 0.5, j_box + 0.5);
00134                 p.distance_from_ref = bwi_mapper::getMagnitude(f - center_pt);
00135                 obstacles.push_back(p);
00136               }
00137             }
00138           }
00139 
00140           // horizontal edges
00141           for (int j_box = low_j; j_box <= high_j;
00142               j_box += high_j - low_j) {
00143             for (int i_box = low_i + 1; i_box < high_i + 1; ++i_box) {
00144               uint32_t map_idx_box = 
00145                 MAP_IDX(inflated_map_.info.width, i_box, j_box);
00146               bool occupied = map_resp_.map.data[map_idx_box];
00147               if (occupied) {
00148                 Point2d p(i_box, j_box);
00149                 Point2f f(i_box + 0.5, j_box + 0.5);
00150                 p.distance_from_ref = bwi_mapper::getMagnitude(f - center_pt);
00151                 obstacles.push_back(p);
00152               }
00153             }
00154           }
00155 
00156           // Check if any obstacles are found
00157           if (obstacles.size() == 0) {
00158             continue;
00159           }
00160 
00161           // Now that obstacles are available, sort and add to the vp as
00162           // necessary
00163           if (!is_naive) {
00164             std::sort(obstacles.begin(), obstacles.end(), 
00165                 Point2dDistanceComp());
00166           }
00167           for (size_t q = 0; q < obstacles.size(); q++) {
00168             vp.addBasisCandidate(obstacles[q], pixel_threshold, 
00169                 inflated_map_, is_naive);
00170           }
00171         }
00172 
00173         if (vp.basis_points.size() >= 2) {
00174           voronoi_points_.push_back(vp);
00175         }
00176         
00177       }
00178     }
00179 
00180     // Compute average basis distance for each voronoi point
00181     for (size_t i = 0; i < voronoi_points_.size(); ++i) {
00182       VoronoiPoint &vp = voronoi_points_[i];
00183       float basis_distance_sum = 0;
00184       for (size_t j = 0; j < vp.basis_points.size(); ++j) {
00185         basis_distance_sum += vp.basis_points[j].distance_from_ref;
00186       }
00187       vp.average_clearance = basis_distance_sum / vp.basis_points.size();
00188       std::cout << "Found VP at " << vp << " with clearance " << vp.average_clearance << std::endl;
00189     }
00190 
00191     // Label the voronoi diagram as being available
00192     initialized_ = true;
00193   }
00194 
00200   void VoronoiApproximator::drawOutput(cv::Mat &image) {
00201     if (!initialized_) {
00202       throw std::runtime_error("drawOutput(): voronoi diagram not "
00203           "initialized, call findVoronoiPoints first");
00204     }
00205     drawMap(image);
00206     drawMap(image, map_resp_.map.info.width);
00207     drawVoronoiPoints(image, map_resp_.map.info.width);
00208   }
00209 
00214   void VoronoiApproximator::printVoronoiPoints() {
00215     for (size_t i = 0; i < voronoi_points_.size(); ++i) {
00216       VoronoiPoint &vp = voronoi_points_[i];
00217       std::cout << " (" << vp.x << "," << vp.y << "): ";
00218       for (size_t j = 0; j < vp.basis_points.size(); ++j) {
00219         std::cout << " (" << vp.basis_points[j].x << "," 
00220           << vp.basis_points[j].y << "," 
00221           << vp.basis_points[j].distance_from_ref << "), ";
00222       }
00223       std::cout << std::endl;
00224     }
00225   }
00226 
00231   void VoronoiApproximator::drawVoronoiPoints(cv::Mat &image, 
00232       uint32_t orig_x, uint32_t orig_y) {
00233     for (size_t i = 0; i < voronoi_points_.size(); ++i) {
00234       VoronoiPoint &vp = voronoi_points_[i];
00235       cv::Point p(vp.x + orig_x, orig_y + vp.y);
00236       cv::circle(image, p, 1, cv::Scalar(255,0,0), -1, CV_AA);
00237       // image.at<cv::Vec3b>
00238       //   (orig_y + vp.y, vp.x + orig_x) = 
00239       //   cv::Vec3b(255,0,0);
00240     }
00241   }
00242 
00243 } /* bwi_mapper */


bwi_mapper
Author(s): Piyush Khandelwal
autogenerated on Fri Aug 28 2015 10:14:35