00001
00038 #include <bwi_mapper/topological_mapper.h>
00039 #include <bwi_mapper/connected_components.h>
00040 #include <bwi_mapper/map_utils.h>
00041 #include <bwi_mapper/point_utils.h>
00042
00043 #include <boost/foreach.hpp>
00044
00045 #include <opencv/highgui.h>
00046
00047 namespace bwi_mapper {
00048
00059 void TopologicalMapper::computeTopologicalGraph(double threshold,
00060 double critical_epsilon, double merge_threshold) {
00061
00062 std::cout << "computeTopologicalGraph(): find voronoi points" << std::endl;
00063 findVoronoiPoints(threshold);
00064 std::cout << "computeTopologicalGraph(): compute critical regions" << std::endl;
00065 computeCriticalRegions(critical_epsilon);
00066 std::cout << "computeTopologicalGraph(): compute ze graph" << std::endl;
00067 computeGraph(merge_threshold);
00068 }
00069
00074 void TopologicalMapper::drawCriticalPoints(cv::Mat &image,
00075 uint32_t orig_x, uint32_t orig_y) {
00076
00077 for (size_t i = 0; i < critical_points_.size(); ++i) {
00078 VoronoiPoint &vp = critical_points_[i];
00079 cv::circle(image,
00080 cv::Point(vp.x + orig_x, vp.y + orig_y), 8, cv::Scalar(0,0,255), -1);
00081 }
00082
00083 drawCriticalLines(image, orig_x, orig_y, false, true);
00084 }
00085
00090 void TopologicalMapper::drawConnectedComponents(cv::Mat &image,
00091 uint32_t orig_x, uint32_t orig_y) {
00092
00093
00094 size_t num_colors = num_components_;
00095 component_colors_.resize(num_colors);
00096 for (size_t i = 0; i < num_colors; ++i) {
00097 component_colors_[i] =
00098 cv::Vec3b(160 + rand() % 64, 160 + rand() % 64, 160 + rand() % 64);
00099 }
00100
00101
00102
00103
00104 for (uint32_t j = 1; j < map_resp_.map.info.height; ++j) {
00105 cv::Vec3b* image_row_j = image.ptr<cv::Vec3b>(j + orig_y);
00106 for (uint32_t i = 0; i < map_resp_.map.info.width; ++i) {
00107 size_t map_idx = MAP_IDX(map_resp_.map.info.width, i, j);
00108 if (component_map_[map_idx] == -1)
00109 continue;
00110 cv::Vec3b& pixel = image_row_j[i + orig_x];
00111 pixel[0] = component_colors_[component_map_[map_idx]][0];
00112 pixel[1] = component_colors_[component_map_[map_idx]][1];
00113 pixel[2] = component_colors_[component_map_[map_idx]][2];
00114
00115 }
00116 }
00117 }
00118
00119
00120 void TopologicalMapper::drawRegionGraph(cv::Mat &image,
00121 uint32_t orig_x, uint32_t orig_y) {
00122 drawGraph(image, region_graph_, orig_x, orig_y);
00123 }
00124
00125 void TopologicalMapper::drawPointGraph(cv::Mat &image,
00126 uint32_t orig_x, uint32_t orig_y) {
00127 drawGraph(image, point_graph_, orig_x, orig_y);
00128 }
00129
00130 void TopologicalMapper::writeRegionGraphToFile(std::string &filename) {
00131 writeGraphToFile(filename, region_graph_, map_resp_.map.info);
00132 }
00133
00134 void TopologicalMapper::writePointGraphToFile(std::string &filename) {
00135 writeGraphToFile(filename, point_graph_, map_resp_.map.info);
00136 }
00137
00142 void TopologicalMapper::printCriticalPoints() {
00143 for (size_t i = 0; i < critical_points_.size(); ++i) {
00144 VoronoiPoint &vp = critical_points_[i];
00145 std::cout << " (" << vp.x << "," << vp.y << "): ";
00146 for (size_t j = 0; j < vp.basis_points.size(); ++j) {
00147 std::cout << " (" << vp.basis_points[j].x << ","
00148 << vp.basis_points[j].y << ","
00149 << vp.basis_points[j].distance_from_ref << "), ";
00150 }
00151 std::cout << std::endl;
00152 }
00153 }
00154
00161 void TopologicalMapper::drawOutput(cv::Mat &image) {
00162 VoronoiApproximator::drawOutput(image);
00163 drawMap(image, 2 * map_resp_.map.info.width);
00164 drawConnectedComponents(image, 2 * map_resp_.map.info.width);
00165 drawCriticalPoints(image, 2 * map_resp_.map.info.width);
00166 drawMap(image, 3 * map_resp_.map.info.width);
00167 drawRegionGraph(image, 3 * map_resp_.map.info.width);
00168 drawMap(image, 4 * map_resp_.map.info.width);
00169 drawPointGraph(image, 4 * map_resp_.map.info.width);
00170 }
00171
00172 void TopologicalMapper::saveOutput() {
00173 cv::Mat image;
00174 drawMap(image);
00175 drawVoronoiPoints(image);
00176 cv::imwrite("graphvoronoi.png", image);
00177 drawMap(image);
00178 drawConnectedComponents(image);
00179 drawCriticalPoints(image);
00180 cv::imwrite("graphcritical.png", image);
00181 drawMap(image);
00182 drawGraph(image, region_graph_);
00183 cv::imwrite("graphoriginal.png", image);
00184 drawMap(image);
00185 drawGraph(image, pass_1_graph_);
00186 cv::imwrite("graphpass1.png", image);
00187 drawMap(image);
00188 drawGraph(image, pass_2_graph_);
00189 cv::imwrite("graphpass2.png", image);
00190 drawMap(image);
00191 drawGraph(image, pass_3_graph_);
00192 cv::imwrite("graphpass3.png", image);
00193 drawMap(image);
00194 drawGraph(image, pass_4_graph_);
00195 cv::imwrite("graphpass4.png", image);
00196 drawMap(image);
00197 drawGraph(image, point_graph_);
00198 cv::imwrite("graphfinal.png", image);
00199 }
00200
00206 void TopologicalMapper::computeCriticalRegions (double critical_epsilon) {
00207
00208
00209 size_t pixel_critical_epsilon =
00210 critical_epsilon / map_resp_.map.info.resolution;
00211
00212 for (size_t i = 0; i < voronoi_points_.size(); ++i) {
00213 VoronoiPoint &vpi = voronoi_points_[i];
00214 float average_neighbourhood_clearance = 0;
00215 size_t neighbour_count = 0;
00216 bool is_clearance_minima = true;
00217
00218 for (size_t j = 0; j < voronoi_points_.size(); ++j) {
00219
00220 if (j == i) {
00221 continue;
00222 }
00223
00224
00225
00226 VoronoiPoint &vpj = voronoi_points_[j];
00227 float distance = bwi_mapper::getMagnitude(vpj - vpi);
00228 if (distance > pixel_critical_epsilon) {
00229 continue;
00230 }
00231
00232 average_neighbourhood_clearance += vpj.average_clearance;
00233 ++neighbour_count;
00234
00235
00236 if (vpj.average_clearance < vpi.average_clearance) {
00237 is_clearance_minima = false;
00238 break;
00239 }
00240 }
00241
00242
00243 if (neighbour_count == 0) {
00244 continue;
00245 }
00246
00247
00248
00249 average_neighbourhood_clearance /= neighbour_count;
00250 if (vpi.average_clearance >= 0.999 * average_neighbourhood_clearance) {
00251 continue;
00252 }
00253
00254
00255
00256 vpi.critical_clearance_diff =
00257 average_neighbourhood_clearance - vpi.average_clearance;
00258
00259 std::vector<size_t> mark_for_removal;
00260
00261
00262 for (size_t j = 0; j < critical_points_.size(); ++j) {
00263
00264
00265 VoronoiPoint &vpj = critical_points_[j];
00266 float distance = norm(vpj - vpi);
00267 if (distance > pixel_critical_epsilon) {
00268 continue;
00269 }
00270
00271
00272 if (vpj.critical_clearance_diff >= vpi.critical_clearance_diff) {
00273 is_clearance_minima = false;
00274 break;
00275 } else {
00276 mark_for_removal.push_back(j);
00277 }
00278 }
00279
00280 if (is_clearance_minima) {
00281
00282 for (size_t j = mark_for_removal.size() - 1;
00283 j < mark_for_removal.size(); --j) {
00284 critical_points_.erase(
00285 critical_points_.begin() + mark_for_removal[j]);
00286 }
00287
00288
00289 critical_points_.push_back(vpi);
00290 }
00291 }
00292
00293
00294 std::vector<size_t> mark_for_removal;
00295 for (size_t i = 0; i < critical_points_.size(); ++i) {
00296 VoronoiPoint &cp = critical_points_[i];
00297 float theta0 =
00298 atan2((cp.basis_points[0] - cp).y,
00299 (cp.basis_points[0] - cp).x);
00300 float theta1 =
00301 atan2((cp.basis_points[1] - cp).y,
00302 (cp.basis_points[1] - cp).x);
00303 float thetadiff = fabs(theta1 - theta0);
00304
00305
00306 if (thetadiff > M_PI + M_PI/12 || thetadiff < M_PI - M_PI/12) {
00307 mark_for_removal.push_back(i);
00308 }
00309 }
00310
00311
00312 for (size_t j = mark_for_removal.size() - 1;
00313 j < mark_for_removal.size(); --j) {
00314 critical_points_.erase(
00315 critical_points_.begin() + mark_for_removal[j]);
00316 }
00317
00318
00319
00320
00321 cv::Mat component_map_color;
00322 drawMap(component_map_color, inflated_map_);
00323 cvtColor(component_map_color, component_image_, CV_RGB2GRAY);
00324 drawCriticalLines(component_image_);
00325
00326 component_map_.resize(
00327 component_image_.rows * component_image_.cols);
00328 ConnectedComponents cc(component_image_, component_map_);
00329 num_components_ = cc.getNumberComponents();
00330
00331 }
00332
00333 void TopologicalMapper::computeGraph(double merge_threshold) {
00334
00335
00336 std::vector<std::set<uint32_t> > point_neighbour_sets;
00337 point_neighbour_sets.resize(critical_points_.size());
00338
00339
00340 cv::Mat lines(map_resp_.map.info.height, map_resp_.map.info.width, CV_16UC1,
00341 cv::Scalar((uint16_t)-1));
00342 drawCriticalLines(lines, 0, 0, true);
00343
00344
00345
00346 for (int j = 0; j < lines.rows; ++j) {
00347 uint16_t* image_row_j = lines.ptr<uint16_t>(j);
00348 for (int i = 0; i < lines.cols; ++i) {
00349 uint16_t pixel = image_row_j[i];
00350 if (pixel == (uint16_t)-1) {
00351 continue;
00352 }
00353 int x_offset[] = {0, -1, 1, 0};
00354 int y_offset[] = {-1, 0, 0, 1};
00355 size_t num_neighbours = 4;
00356 for (size_t count = 0; count < num_neighbours; ++count) {
00357 uint32_t x_n = i + x_offset[count];
00358 uint32_t y_n = j + y_offset[count];
00359 if (x_n >= (uint16_t) lines.cols || y_n >= (uint16_t) lines.rows) {
00360 continue;
00361 }
00362 size_t map_idx = MAP_IDX(lines.cols, x_n, y_n);
00363 if (component_map_[map_idx] >= 0 &&
00364 component_map_[map_idx] < (int32_t) num_components_) {
00365 point_neighbour_sets[pixel].insert(component_map_[map_idx]);
00366 }
00367 }
00368 }
00369 }
00370
00371
00372
00373 std::vector<std::vector<uint32_t> > point_neighbours;
00374 point_neighbours.resize(critical_points_.size());
00375 std::vector<int> remove_crit_points;
00376 for (size_t i = 0; i < critical_points_.size(); ++i) {
00377 if (point_neighbour_sets[i].size() == 2) {
00378 point_neighbours[i] =
00379 std::vector<uint32_t>(point_neighbour_sets[i].begin(),
00380 point_neighbour_sets[i].end());
00381 } else {
00382 remove_crit_points.push_back(i);
00383 }
00384 }
00385
00386 for (int i = remove_crit_points.size() - 1; i >=0 ; --i) {
00387 critical_points_.erase(critical_points_.begin() + i);
00388 point_neighbour_sets.erase(point_neighbour_sets.begin() + i);
00389 point_neighbours.erase(point_neighbours.begin() + i);
00390 }
00391
00392
00393 std::vector<bool> checked_region(critical_points_.size(), false);
00394 std::vector<std::set<int> > graph_sets;
00395 for (size_t i = 0; i < num_components_; ++i) {
00396 if (checked_region[i]) {
00397 continue;
00398 }
00399 std::set<int> open_set, closed_set;
00400 open_set.insert(i);
00401 while (open_set.size() != 0) {
00402 int current_region = *(open_set.begin());
00403 open_set.erase(open_set.begin());
00404 closed_set.insert(current_region);
00405 checked_region[current_region] = true;
00406 for (int j = 0; j < critical_points_.size(); ++j) {
00407 for (int k = 0; k < 2; ++k) {
00408 if (point_neighbours[j][k] == current_region &&
00409 std::find(closed_set.begin(), closed_set.end(),
00410 point_neighbours[j][1-k]) ==
00411 closed_set.end()) {
00412 open_set.insert(point_neighbours[j][1-k]);
00413 }
00414 }
00415 }
00416 }
00417 graph_sets.push_back(closed_set);
00418 }
00419
00420 std::set<int> master_region_set;
00421 if (graph_sets.size() != 1) {
00422 std::cout << "WARNING: Master graph is fragmented into " <<
00423 graph_sets.size() << " sub-graphs!!!" << std::endl;
00424 int max_idx = 0;
00425 int max_size = graph_sets[0].size();
00426 for (size_t i = 1; i < graph_sets.size(); ++i) {
00427 if (graph_sets[i].size() > max_size) {
00428 max_idx = i;
00429 max_size = graph_sets[i].size();
00430 }
00431 }
00432 master_region_set = graph_sets[max_idx];
00433 } else {
00434 master_region_set = graph_sets[0];
00435 }
00436
00437
00438 std::map<int, int> region_to_vertex_map;
00439 int vertex_count = 0;
00440 for (size_t r = 0; r < num_components_; ++r) {
00441 if (std::find(master_region_set.begin(), master_region_set.end(), r) ==
00442 master_region_set.end()) {
00443 region_to_vertex_map[r] = -1;
00444 continue;
00445 }
00446
00447 Graph::vertex_descriptor vi = boost::add_vertex(region_graph_);
00448
00449
00450 uint32_t avg_i = 0, avg_j = 0, pixel_count = 0;
00451 for (size_t j = 0; j < map_resp_.map.info.height; ++j) {
00452 for (size_t i = 0; i < map_resp_.map.info.width; ++i) {
00453 size_t map_idx = MAP_IDX(map_resp_.map.info.width, i, j);
00454 if (component_map_[map_idx] == (int)r) {
00455 avg_j += j;
00456 avg_i += i;
00457 pixel_count++;
00458 }
00459 }
00460 }
00461
00462 region_graph_[vi].location.x = ((float) avg_i) / pixel_count;
00463 region_graph_[vi].location.y = ((float) avg_j) / pixel_count;
00464 region_graph_[vi].pixels = floor(sqrt(pixel_count));
00465
00466
00467 region_to_vertex_map[r] = vertex_count;
00468
00469 ++vertex_count;
00470 }
00471
00472
00473
00474 std::map<int, std::map<int, VoronoiPoint> >
00475 region_vertex_crit_points;
00476 for (size_t r = 0; r < num_components_; ++r) {
00477 if (std::find(master_region_set.begin(), master_region_set.end(), r) ==
00478 master_region_set.end()) {
00479 region_to_vertex_map[r] = -1;
00480 continue;
00481 }
00482
00483 for (int j = 0; j < critical_points_.size(); ++j) {
00484 for (int k = 0; k < 2; ++k) {
00485 if (point_neighbours[j][k] == r) {
00486 int region_vertex = region_to_vertex_map[r];
00487 int other_region_vertex = region_to_vertex_map[point_neighbours[j][1-k]];
00488 if (region_vertex == 192 && other_region_vertex == 202) {
00489 std::cout << "192-202: " << r << " " << point_neighbours[j][1-k] << " " << critical_points_[j] << std::endl;
00490 }
00491 if (region_vertex == 202 && other_region_vertex == 192) {
00492 std::cout << "192-202: " << r << " " << point_neighbours[j][1-k] << " " << critical_points_[j] << std::endl;
00493 }
00494 region_vertex_crit_points[region_vertex]
00495 [region_to_vertex_map[point_neighbours[j][1-k]]] =
00496 critical_points_[j];
00497 }
00498 }
00499 }
00500 }
00501
00502
00503 for (size_t i = 0; i < critical_points_.size(); ++i) {
00504 int region1 = region_to_vertex_map[point_neighbours[i][0]];
00505 int region2 = region_to_vertex_map[point_neighbours[i][1]];
00506 if (region1 == -1) {
00507
00508 continue;
00509 }
00510 int count = 0;
00511 Graph::vertex_descriptor vi,vj;
00512 vi = boost::vertex(region1, region_graph_);
00513 vj = boost::vertex(region2, region_graph_);
00514 Graph::edge_descriptor e; bool b;
00515 boost::tie(e,b) = boost::edge(vi, vj, region_graph_);
00516 if (!b) {
00517 boost::tie(e,b) = boost::add_edge(vi, vj, region_graph_);
00518 }
00519
00520
00521
00522 }
00523
00524
00525 int pixel_threshold = merge_threshold / map_resp_.map.info.resolution;
00526
00527 enum {
00528 PRESENT = 0,
00529 REMOVED_REGION_VERTEX = 1,
00530 CONVERT_TO_CRITICAL_POINT = 2,
00531 MERGE_VERTEX = 3
00532 };
00533 Graph::vertex_iterator vi, vend;
00534
00535
00536
00537 std::cout << std::endl << "==============================" << std::endl;
00538 std::cout << "PASS 1" << std::endl;
00539 std::cout << "==============================" << std::endl << std::endl;
00540 Graph pass_0_graph = region_graph_;
00541 Graph pass_1_graph;
00542 int pass_0_count = 0;
00543 int pass_1_count = 0;
00544 std::vector<int> pass_0_vertex_status(
00545 boost::num_vertices(pass_0_graph), PRESENT);
00546 std::map<int, int> pass_0_vertex_to_pass_1_map;
00547 for (boost::tie(vi, vend) = boost::vertices(pass_0_graph); vi != vend;
00548 ++vi, ++pass_0_count) {
00549
00550 std::cout << "Analyzing pass 0 graph vertex: " << pass_0_count << std::endl;
00551
00552 std::vector<size_t> adj_vertices;
00553 getAdjacentNodes(pass_0_count, pass_0_graph, adj_vertices);
00554
00555
00556 if (pass_0_graph[*vi].pixels >= pixel_threshold &&
00557 adj_vertices.size() > 2) {
00558 pass_0_vertex_status[pass_0_count] = CONVERT_TO_CRITICAL_POINT;
00559 std::cout << " - throwing it out (needs to be resolved to CPs)" <<
00560 std::endl;
00561 continue;
00562 }
00563
00564
00565 Graph::vertex_descriptor point_vi = boost::add_vertex(pass_1_graph);
00566 pass_1_graph[point_vi] = pass_0_graph[*vi];
00567 pass_0_vertex_to_pass_1_map[pass_0_count] = pass_1_count;
00568
00569 ++pass_1_count;
00570 }
00571
00572
00573
00574
00575 std::map<int, std::map<int, int> > pass_0_vertex_to_cp_map;
00576 pass_0_count = 0;
00577 for (boost::tie(vi, vend) = boost::vertices(pass_0_graph); vi != vend;
00578 ++vi, ++pass_0_count) {
00579
00580 if (pass_0_vertex_status[pass_0_count] != CONVERT_TO_CRITICAL_POINT) {
00581 continue;
00582 }
00583 std::cout << "Converting pass1 vtx to CPs: " << pass_0_count << std::endl;
00584
00585 std::vector<size_t> adj_vertices;
00586 getAdjacentNodes(pass_0_count, pass_0_graph, adj_vertices);
00587 std::vector<int> connect_edges;
00588 BOOST_FOREACH(size_t vtx, adj_vertices) {
00589 if (pass_0_vertex_status[vtx] == PRESENT) {
00590 Graph::vertex_descriptor point_vi = boost::add_vertex(pass_1_graph);
00591 pass_1_graph[point_vi].location =
00592 region_vertex_crit_points[pass_0_count][vtx];
00593 std::cout << " - added vtx at " << pass_1_graph[point_vi].location
00594 << std::endl;
00595 int pass_1_vertex = pass_0_vertex_to_pass_1_map[vtx];
00596 std::cout << " - connecting vtx to pass_1_vertex: " << pass_1_vertex
00597 << " (pass0 = " << vtx << ")" << std::endl;
00598 Graph::vertex_descriptor vj;
00599 vj = boost::vertex(pass_1_vertex, pass_1_graph);
00600 Graph::edge_descriptor e; bool b;
00601 boost::tie(e,b) = boost::add_edge(point_vi, vj, pass_1_graph);
00602 connect_edges.push_back(pass_1_count);
00603 ++pass_1_count;
00604 } else if (vtx > pass_0_count) {
00605
00606 Graph::vertex_descriptor point_vi = boost::add_vertex(pass_1_graph);
00607 pass_1_graph[point_vi].location =
00608 region_vertex_crit_points[pass_0_count][vtx];
00609 std::cout << " - added shared cp with " << vtx << " at "
00610 << pass_1_graph[point_vi].location << std::endl;
00611 pass_0_vertex_to_cp_map[pass_0_count][vtx] = pass_1_count;
00612 connect_edges.push_back(pass_1_count);
00613 ++pass_1_count;
00614 } else {
00615
00616 int cp_vtx = pass_0_vertex_to_cp_map[vtx][pass_0_count];
00617 connect_edges.push_back(cp_vtx);
00618 }
00619 }
00620
00621
00622 for (int i = 0; i < connect_edges.size(); ++i) {
00623 for (int j = 0; j < i; ++j) {
00624 Graph::vertex_descriptor vi, vj;
00625 vi = boost::vertex(connect_edges[i], pass_1_graph);
00626 vj = boost::vertex(connect_edges[j], pass_1_graph);
00627 Graph::edge_descriptor e; bool b;
00628 boost::tie(e,b) = boost::add_edge(vi, vj, pass_1_graph);
00629 }
00630 }
00631
00632 }
00633
00634
00635 pass_0_count = 0;
00636 for (boost::tie(vi, vend) = boost::vertices(pass_0_graph); vi != vend;
00637 ++vi, ++pass_0_count) {
00638
00639 if (pass_0_vertex_status[pass_0_count] != PRESENT) {
00640 continue;
00641 }
00642 std::cout << "Adding pass 1 edges for: " << pass_0_count << std::endl;
00643
00644 std::vector<size_t> adj_vertices;
00645 getAdjacentNodes(pass_0_count, pass_0_graph, adj_vertices);
00646 BOOST_FOREACH(size_t vtx, adj_vertices) {
00647 if (pass_0_vertex_status[vtx] == PRESENT && vtx < pass_0_count) {
00648 Graph::vertex_descriptor vi, vj;
00649 vi = boost::vertex(
00650 pass_0_vertex_to_pass_1_map[pass_0_count], pass_1_graph);
00651 vj = boost::vertex(
00652 pass_0_vertex_to_pass_1_map[vtx], pass_1_graph);
00653 Graph::edge_descriptor e; bool b;
00654 boost::tie(e,b) = boost::add_edge(vi, vj, pass_1_graph);
00655 }
00656 }
00657 }
00658
00659 pass_1_graph_ = pass_1_graph;
00660
00661
00662
00663 std::cout << std::endl << "==============================" << std::endl;
00664 std::cout << "PASS 2" << std::endl;
00665 std::cout << "==============================" << std::endl << std::endl;
00666
00667 Graph pass_2_graph;
00668
00669 std::vector<int> pass_1_vertex_status(boost::num_vertices(pass_1_graph), PRESENT);
00670 std::map<int, int> pass_1_vertex_to_pass_2_vertex_map;
00671 std::vector<std::pair<int, int> > rr_extra_edges;
00672 std::map<int, std::pair<int, int> > removed_vertex_map;
00673
00674 pass_1_count = 0;
00675 int pass_2_count = 0;
00676 for (boost::tie(vi, vend) = boost::vertices(pass_1_graph); vi != vend;
00677 ++vi, ++pass_1_count) {
00678
00679 std::cout << "Analyzing pass_1 graph vertex: " << pass_1_count << std::endl;
00680
00681 if (pass_1_vertex_status[pass_1_count] != PRESENT) {
00682 std::cout << " - the vertex has been thrown out already " << std::endl;
00683 continue;
00684 }
00685
00686
00687
00688 std::vector<size_t> open_vertices;
00689 int current_vertex = pass_1_count;
00690 getAdjacentNodes(current_vertex, pass_1_graph, open_vertices);
00691 std::vector<int> removed_vertices;
00692 std::pair<int, int> edge;
00693 if (open_vertices.size() == 2 &&
00694 pass_1_vertex_status[open_vertices[0]] == PRESENT &&
00695 pass_1_vertex_status[open_vertices[1]] == PRESENT) {
00696 while(true) {
00697 std::cout << " - has 2 adjacent vertices " << open_vertices[0] << ", "
00698 << open_vertices[1] << std::endl;
00699
00700 Point2f location1 =
00701 getLocationFromGraphId(open_vertices[0], pass_1_graph);
00702 Point2f location2 =
00703 getLocationFromGraphId(open_vertices[1], pass_1_graph);
00704 bool locations_visible =
00705 locationsInDirectLineOfSight(location1, location2, map_resp_.map);
00706 if (locations_visible) {
00707 std::cout << " - the 2 adjacent vertices are visible "
00708 << "- removing vertex." << std::endl;
00709 pass_1_vertex_status[current_vertex] = REMOVED_REGION_VERTEX;
00710 removed_vertices.push_back(current_vertex);
00711 edge = std::make_pair(open_vertices[0], open_vertices[1]);
00712 bool replacement_found = false;
00713 for (int i = 0; i < 2; ++i) {
00714 std::vector<size_t> adj_vertices;
00715 getAdjacentNodes(open_vertices[i], pass_1_graph,
00716 adj_vertices);
00717 if (adj_vertices.size() == 2) {
00718 size_t new_vertex = (adj_vertices[0] == current_vertex) ?
00719 adj_vertices[1] : adj_vertices[0];
00720 if (pass_1_vertex_status[new_vertex] == PRESENT) {
00721 current_vertex = open_vertices[i];
00722 std::cout << " - neighbours may suffer from the same problem"
00723 << ". checking vertex " << current_vertex << std::endl;
00724 open_vertices[i] = new_vertex;
00725 replacement_found = true;
00726 break;
00727 }
00728 }
00729 }
00730 if (!replacement_found) {
00731
00732
00733 break;
00734 }
00735 } else {
00736
00737 break;
00738 }
00739 }
00740 }
00741
00742 BOOST_FOREACH(int removed_vertex, removed_vertices) {
00743 removed_vertex_map[removed_vertex] = edge;
00744 }
00745
00746 if (removed_vertices.size() != 0) {
00747
00748 std::cout << " - adding extra edge between " << edge.first <<
00749 " " << edge.second << std::endl;
00750 rr_extra_edges.push_back(edge);
00751 continue;
00752 }
00753
00754
00755 Graph::vertex_descriptor point_vi = boost::add_vertex(pass_2_graph);
00756 pass_2_graph[point_vi] = pass_1_graph[*vi];
00757 pass_1_vertex_to_pass_2_vertex_map[pass_1_count] =
00758 pass_2_count;
00759
00760 ++pass_2_count;
00761 }
00762
00763
00764
00765
00766 pass_1_count = 0;
00767 for (boost::tie(vi, vend) = boost::vertices(pass_1_graph); vi != vend;
00768 ++vi, ++pass_1_count) {
00769 if (pass_1_vertex_status[pass_1_count] == PRESENT) {
00770 std::vector<size_t> adj_vertices;
00771 getAdjacentNodes(pass_1_count, pass_1_graph, adj_vertices);
00772 BOOST_FOREACH(size_t adj_vertex, adj_vertices) {
00773 if (pass_1_vertex_status[adj_vertex] == PRESENT &&
00774 adj_vertex > pass_1_count) {
00775 Graph::vertex_descriptor vi,vj;
00776 int vertex1 =
00777 pass_1_vertex_to_pass_2_vertex_map[pass_1_count];
00778 int vertex2 = pass_1_vertex_to_pass_2_vertex_map[adj_vertex];
00779 vi = boost::vertex(vertex1, pass_2_graph);
00780 vj = boost::vertex(vertex2, pass_2_graph);
00781 Graph::edge_descriptor e; bool b;
00782 boost::tie(e,b) = boost::add_edge(vi, vj, pass_2_graph);
00783 }
00784 }
00785 }
00786 }
00787
00788
00789 typedef std::pair<int, int> int2pair;
00790 BOOST_FOREACH(const int2pair& edge, rr_extra_edges) {
00791 Graph::vertex_descriptor vi,vj;
00792 int vertex1 =
00793 pass_1_vertex_to_pass_2_vertex_map[edge.first];
00794 int vertex2 = pass_1_vertex_to_pass_2_vertex_map[edge.second];
00795 vi = boost::vertex(vertex1, pass_2_graph);
00796 vj = boost::vertex(vertex2, pass_2_graph);
00797 Graph::edge_descriptor e; bool b;
00798 boost::tie(e,b) = boost::add_edge(vi, vj, pass_2_graph);
00799 }
00800
00801 pass_2_graph_ = pass_2_graph;
00802
00803
00804
00805 int vertex_merge_threshold = 2.0f / map_resp_.map.info.resolution;
00806 std::cout << std::endl << "==============================" << std::endl;
00807 std::cout << "PASS 3" << std::endl;
00808 std::cout << "==============================" << std::endl << std::endl;
00809 Graph pass_3_graph;
00810 pass_2_count = 0;
00811 int pass_3_count = 0;
00812 std::map<int, int> pass_2_vertex_to_pass_3_vertex_map;
00813 std::vector<int> pass_2_vertex_status(
00814 boost::num_vertices(pass_2_graph), PRESENT);
00815 for (boost::tie(vi, vend) = boost::vertices(pass_2_graph); vi != vend;
00816 ++vi, ++pass_2_count) {
00817
00818 std::cout << "Analyzing pass 2 graph vtx: " << pass_2_count << std::endl;
00819 if (pass_2_vertex_status[pass_2_count] != PRESENT) {
00820 std::cout << " - vtx already thrown out " << std::endl;
00821 continue;
00822 }
00823
00824 std::set<int> open_set;
00825 std::set<int> closed_set;
00826 open_set.insert(pass_2_count);
00827 while(open_set.size() != 0) {
00828 int current_vertex = *open_set.begin();
00829 open_set.erase(open_set.begin());
00830 closed_set.insert(current_vertex);
00831 std::vector<size_t> adj_vertices;
00832 getAdjacentNodes(current_vertex, pass_2_graph, adj_vertices);
00833 BOOST_FOREACH(size_t vtx, adj_vertices) {
00834 if (closed_set.count(vtx) || open_set.count(vtx)) {
00835 continue;
00836 }
00837 std::cout << " - checking " << current_vertex << ", " << vtx;
00838 Point2f l1 = getLocationFromGraphId(current_vertex, pass_2_graph);
00839 Point2f l2 = getLocationFromGraphId(vtx, pass_2_graph);
00840 float distance = getMagnitude(l1-l2);
00841 std::cout << " - " << distance;
00842 if (distance < vertex_merge_threshold) {
00843 open_set.insert(vtx);
00844 std::cout << " - WILL MERGE";
00845 }
00846 std::cout << std::endl;
00847 }
00848 }
00849
00850 Point2f vertex_location = pass_2_graph[*vi].location;
00851 if (closed_set.size() != 1) {
00852 Point2f sum(0,0);
00853 BOOST_FOREACH(int vtx, closed_set) {
00854 pass_2_vertex_status[vtx] = MERGE_VERTEX;
00855 pass_2_vertex_to_pass_3_vertex_map[vtx] = pass_3_count;
00856 sum += getLocationFromGraphId(vtx, pass_2_graph);
00857 }
00858 vertex_location = (1.0f / closed_set.size()) * sum;
00859 } else {
00860 pass_2_vertex_to_pass_3_vertex_map[pass_2_count] = pass_3_count;
00861 }
00862
00863 Graph::vertex_descriptor point_vi = boost::add_vertex(pass_3_graph);
00864 pass_3_graph[point_vi].location = vertex_location;
00865 ++pass_3_count;
00866 }
00867
00868
00869 pass_2_count = 0;
00870 for (boost::tie(vi, vend) = boost::vertices(pass_2_graph); vi != vend;
00871 ++vi, ++pass_2_count) {
00872 std::cout << "Gen edges pass 2 graph vtx: " << pass_2_count << std::endl;
00873 std::vector<size_t> adj_vertices;
00874 getAdjacentNodes(pass_2_count, pass_2_graph, adj_vertices);
00875 BOOST_FOREACH(size_t adj_vertex, adj_vertices) {
00876 if (adj_vertex > pass_2_count) {
00877 Graph::vertex_descriptor vi,vj;
00878 int vertex1 = pass_2_vertex_to_pass_3_vertex_map[pass_2_count];
00879 int vertex2 = pass_2_vertex_to_pass_3_vertex_map[adj_vertex];
00880 if (vertex1 != vertex2) {
00881 vi = boost::vertex(vertex1, pass_3_graph);
00882 vj = boost::vertex(vertex2, pass_3_graph);
00883 Graph::edge_descriptor e; bool b;
00884 boost::tie(e,b) = boost::edge(vi, vj, pass_3_graph);
00885 if (!b) {
00886 boost::tie(e,b) = boost::add_edge(vi, vj, pass_3_graph);
00887 pass_3_graph[e].weight = getMagnitude(
00888 getLocationFromGraphId(vertex1, pass_3_graph) -
00889 getLocationFromGraphId(vertex2, pass_3_graph));
00890 std::cout << " - gen edge " << vertex1 << " " << vertex2 << std::endl;
00891 }
00892 }
00893 }
00894 }
00895 }
00896
00897 pass_3_graph_ = pass_3_graph;
00898
00899
00900 pass_3_count = 0;
00901 int neighbourhood = 0.5 / map_resp_.map.info.resolution;
00902 int num_vertices_pass_3 = boost::num_vertices(pass_3_graph);
00903 for (boost::tie(vi, vend) = boost::vertices(pass_3_graph); vi != vend;
00904 ++vi, ++pass_3_count) {
00905 std::cout << "Attempting nudge on vtx: " << pass_3_count << std::endl;
00906 Point2f vtx_loc = getLocationFromGraphId(pass_3_count, pass_3_graph);
00907 int max_visibility = 0, best_i = vtx_loc.x, best_j = vtx_loc.y;
00908 for (int k = 0; k < num_vertices_pass_3; ++k) {
00909 Point2f k_loc = getLocationFromGraphId(k, pass_3_graph);
00910 if (locationsInDirectLineOfSight(vtx_loc, k_loc, map_resp_.map)) {
00911 ++max_visibility;
00912 }
00913 }
00914 for (int j = vtx_loc.y - neighbourhood / 2;
00915 j <= vtx_loc.y + neighbourhood / 2; ++j) {
00916 for (int i = vtx_loc.x - neighbourhood / 2;
00917 i <= vtx_loc.x + neighbourhood / 2; ++i) {
00918 Point2f point_loc(i, j);
00919 int visibility = 0;
00920 for (int k = 0; k < num_vertices_pass_3; ++k) {
00921 Point2f k_loc = getLocationFromGraphId(k, pass_3_graph);
00922 if (locationsInDirectLineOfSight(point_loc, k_loc, map_resp_.map)) {
00923 ++visibility;
00924 }
00925 }
00926 if (visibility > max_visibility) {
00927 max_visibility = visibility;
00928 best_i = i;
00929 best_j = j;
00930 }
00931 }
00932 }
00933 pass_3_graph[*vi].location = Point2f(best_i, best_j);
00934 }
00935
00936
00937 pass_3_count = 0;
00938 for (boost::tie(vi, vend) = boost::vertices(pass_3_graph); vi != vend;
00939 ++vi, ++pass_3_count) {
00940 Point2f vtx1 = getLocationFromGraphId(pass_3_count, pass_3_graph);
00941 std::vector<size_t> adj_vertices;
00942 getAdjacentNodes(pass_3_count, pass_3_graph, adj_vertices);
00943 BOOST_FOREACH(size_t adj_vertex, adj_vertices) {
00944 if (adj_vertex > pass_3_count) {
00945 Point2f vtx2 = getLocationFromGraphId(adj_vertex, pass_3_graph);
00946 Graph::vertex_descriptor vi,vj;
00947 vi = boost::vertex(pass_3_count, pass_3_graph);
00948 vj = boost::vertex(adj_vertex, pass_3_graph);
00949 Graph::edge_descriptor e; bool b;
00950 boost::tie(e,b) = boost::edge(vi, vj, pass_3_graph);
00951 if (b) {
00952 pass_3_graph[e].weight = getMagnitude(vtx1 - vtx2);
00953 }
00954 }
00955 }
00956 }
00957
00958 pass_4_graph_ = pass_3_graph;
00959
00960
00961 pass_3_count = 0;
00962 for (boost::tie(vi, vend) = boost::vertices(pass_3_graph); vi != vend;
00963 ++vi, ++pass_3_count) {
00964 std::cout << "Analyzing edges on vtx " << pass_3_count << std::endl;
00965 std::vector<size_t> adj_vertices;
00966 getAdjacentNodes(pass_3_count, pass_3_graph, adj_vertices);
00967 Point2f vtx1 = getLocationFromGraphId(pass_3_count, pass_3_graph);
00968 BOOST_FOREACH(size_t adj_vertex, adj_vertices) {
00969 if (adj_vertex < pass_3_count)
00970 continue;
00971 std::cout << " - analyzing edge between " << pass_3_count << " and " <<
00972 adj_vertex << std::endl;
00973 Point2f vtx2 = getLocationFromGraphId(adj_vertex, pass_3_graph);
00974 float edge_length = getMagnitude(vtx1 - vtx2);
00975 Graph::vertex_descriptor vi,vj;
00976 vi = boost::vertex(pass_3_count, pass_3_graph);
00977 vj = boost::vertex(adj_vertex, pass_3_graph);
00978 boost::remove_edge(vi, vj, pass_3_graph);
00979 std::vector<size_t> replacement_path;
00980 float path_cost =
00981 getShortestPathWithDistance(pass_3_count, adj_vertex, replacement_path, pass_3_graph);
00982 if (replacement_path.size() >= 2) {
00983 std::cout << " - fount alternate path cost: " << path_cost << std::endl;
00984 }
00985 if (replacement_path.size() < 2 || path_cost > 1.05 * edge_length) {
00986
00987 Graph::edge_descriptor e; bool b;
00988 boost::tie(e,b) = boost::add_edge(vi, vj, pass_3_graph);
00989 pass_3_graph[e].weight = getMagnitude(
00990 getLocationFromGraphId(pass_3_count, pass_3_graph) -
00991 getLocationFromGraphId(adj_vertex, pass_3_graph));
00992 } else {
00993 std::cout << " - removing edge between " << pass_3_count << " and " <<
00994 adj_vertex << std::endl;
00995 }
00996 }
00997 }
00998
00999 point_graph_ = pass_3_graph;
01000
01001 }
01002
01007 void TopologicalMapper::drawCriticalLines(cv::Mat &image,
01008 uint32_t orig_x, uint32_t orig_y, bool draw_idx,
01009 bool visualization_image) {
01010
01011 for (size_t i = 0; i < critical_points_.size(); ++i) {
01012 cv::Scalar color = cv::Scalar(0);
01013 if (draw_idx) {
01014 color = cv::Scalar((uint16_t)i);
01015 }
01016 VoronoiPoint &vp = critical_points_[i];
01017 if (vp.basis_points.size() != 2) {
01018 std::cerr << "ERROR: Found a critical point with more than 2 basis"
01019 << "points. This should not have happened" << std::endl;
01020 } else {
01021 Point2d &p1(vp.basis_points[0]);
01022 Point2d &p2(vp.basis_points[1]);
01023 if (!visualization_image) {
01024 cv::line(image,
01025 cv::Point(orig_x + p1.x, orig_y + p1.y),
01026 cv::Point(orig_x + p2.x, orig_y + p2.y),
01027 color,
01028 1, 4);
01029 } else {
01030 color = cv::Scalar(0, 0, 255);
01031 cv::line(image,
01032 cv::Point(orig_x + p1.x, orig_y + p1.y),
01033 cv::Point(orig_x + p2.x, orig_y + p2.y),
01034 color,
01035 2, CV_AA);
01036 }
01037 }
01038 }
01039 }
01040
01041 }
01042