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
00061 inflateMap(threshold, map_resp_.map, inflated_map_);
00062
00063
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
00081
00082
00083
00084
00085
00086
00087 VoronoiPoint vp(lrint(center_pt.x), lrint(center_pt.y));
00088
00089
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
00096
00097
00098 for (int box = pixel_threshold; box < max_dimension; ++box) {
00099
00100
00101
00102 if (vp.basis_points.size() != 0 &&
00103 box > vp.basis_distance + 1) {
00104 break;
00105 }
00106
00107
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
00115
00116
00117
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
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
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
00157 if (obstacles.size() == 0) {
00158 continue;
00159 }
00160
00161
00162
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
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
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
00238
00239
00240 }
00241 }
00242
00243 }