00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "mrpt_graphslam_2d/CMapMerger.h"
00011
00012 using namespace mrpt::graphslam;
00013 using namespace mrpt::graphslam::detail;
00014 using namespace mrpt_msgs;
00015 using namespace mrpt::maps;
00016 using namespace mrpt::slam;
00017 using namespace mrpt::math;
00018 using namespace mrpt::system;
00019 using namespace mrpt::poses;
00020 using namespace mrpt::opengl;
00021 using namespace mrpt::utils;
00022 using namespace ros;
00023 using namespace nav_msgs;
00024 using namespace std;
00025 using namespace mrpt_bridge;
00026
00027
00028
00030
00032 bool removeObjectFrom3DScene(
00033 mrpt::gui::CDisplayWindow3D* win,
00034 std::string obj_name="") {
00035 using namespace mrpt::opengl;
00036 ASSERT_(win);
00037 bool res = true;
00038 COpenGLScene::Ptr& scene = win->get3DSceneAndLock();
00039
00040 if (obj_name.empty()) {
00041 cout << "Clearing entire scene." << endl;
00042 scene.reset();
00043 }
00044 else {
00045 CRenderizable::Ptr obj = scene->getByName(obj_name);
00046 if (obj) {
00047 scene->removeObject(obj);
00048 }
00049 else {
00050 res = false;
00051 }
00052 }
00053
00054 win->unlockAccess3DScene();
00055 win->forceRepaint();
00056 return res;
00057 }
00058
00060 bool removeObjectFrom3DScene(
00061 mrpt::graphslam::CWindowManager* win_manager,
00062 std::string obj_name="") {
00063 ASSERT_(win_manager);
00064 return removeObjectFrom3DScene(win_manager->win, obj_name);
00065 }
00066
00067 template<class RENDERIZABLE_OBJECT>
00068 void addToWindow(mrpt::gui::CDisplayWindow3D* win,
00069 const RENDERIZABLE_OBJECT& o,
00070 const std::string& obj_name="",
00071 const mrpt::poses::CPose3D& obj_pose=EMPTY_POSE) {
00072 using namespace mrpt::opengl;
00073
00074 COpenGLScene::Ptr &scene = win->get3DSceneAndLock();
00075 CSetOfObjects::Ptr obj = CSetOfObjects::Create();
00076
00077 o.getAs3DObject(obj);
00078 obj->setPose(obj_pose);
00079
00080 if (!obj_name.empty()) {
00081 obj->setName(obj_name);
00082 }
00083
00084 scene->insert(obj);
00085
00086 win->unlockAccess3DScene();
00087 win->forceRepaint();
00088 }
00089
00090 void addAxis(mrpt::gui::CDisplayWindow3D* win) {
00091 using namespace mrpt;
00092 using namespace mrpt::opengl;
00093 ASSERT_(win);
00094
00095 COpenGLScene::Ptr &scene = win->get3DSceneAndLock();
00096 opengl::CAxis::Ptr obj = opengl::CAxis::Create(-6, -6, -6, 6, 6, 6, 2, 2, true);
00097 obj->setLocation(0, 0, 0);
00098 scene->insert(obj);
00099 win->unlockAccess3DScene();
00100 win->forceRepaint();
00101 }
00102
00103 void addGrid(mrpt::gui::CDisplayWindow3D* win) {
00104 using namespace mrpt;
00105 using namespace mrpt::opengl;
00106 ASSERT_(win);
00107
00108 COpenGLScene::Ptr &scene = win->get3DSceneAndLock();
00109 opengl::CGridPlaneXY::Ptr obj = opengl::CGridPlaneXY::Create(-20, 20, -20, 20, 0, 1);
00110 obj->setColor(0.7, 0.7, 0.7);
00111 obj->setLocation(0, 0, 0);
00112 scene->insert(obj);
00113
00114 win->unlockAccess3DScene();
00115 win->forceRepaint();
00116 }
00117
00118 void addSupWidgets(mrpt::gui::CDisplayWindow3D* win) {
00119 ASSERT_(win);
00120
00121 addAxis(win);
00122 addGrid(win);
00123 }
00124
00126
00127
00128 CMapMerger::CMapMerger(
00129 mrpt::utils::COutputLogger* logger_in,
00130 ros::NodeHandle* nh_in):
00131 m_logger(logger_in),
00132 m_nh(nh_in),
00133 m_conn_manager(logger_in, nh_in),
00134 m_queue_size(1),
00135 quit_keypress1("q"),
00136 quit_keypress2("Ctrl+c"),
00137 map_merge_keypress("n"),
00138 save_map_merging_results(true)
00139 {
00140 ASSERT_(m_nh);
00141
00142 m_global_ns = "/map_merger";
00143
00144
00145 m_alignment_options.methodSelection = CGridMapAligner::amModifiedRANSAC;
00147 m_alignment_options.min_ICP_goodness = 0.60;
00148 m_alignment_options.maxKLd_for_merge = 0.90;
00149 m_alignment_options.ransac_minSetSizeRatio = 0.40;
00150
00151
00152
00153 m_alignment_options.dumpToConsole();
00154
00155
00156 m_fused_map_win_manager = this->initWindowVisuals();
00157 m_fused_map_win_manager->win->setWindowTitle("Fused map");
00158 this->monitorKeystrokes(m_fused_map_win_manager->observer);
00159
00160 }
00161
00162 void CMapMerger::monitorKeystrokes(mrpt::graphslam::CWindowObserver* win_observer) {
00163 ASSERT_(win_observer);
00164
00165 win_observer->registerKeystroke(quit_keypress1,
00166 "Finish execution");
00167 win_observer->registerKeystroke(map_merge_keypress,
00168 "Compute next available grid-merging");
00169
00170
00171 }
00172
00173 CMapMerger::~CMapMerger() {
00174
00175
00176 for (neighbors_t::iterator n_it = m_neighbors.begin();
00177 n_it != m_neighbors.end();
00178 ++n_it) {
00179
00180 delete m_neighbors_to_windows.at(*n_it)->observer;
00181 delete m_neighbors_to_windows.at(*n_it)->win;
00182 delete m_neighbors_to_windows.at(*n_it);
00183 delete *n_it;
00184 }
00185
00186
00187 delete m_fused_map_win_manager->win;
00188 delete m_fused_map_win_manager->observer;
00189 delete m_fused_map_win_manager;
00190
00191 m_logger->logFmt(LVL_WARN, "Exiting...");
00192 }
00193
00194 bool CMapMerger::updateState() {
00195 MRPT_START;
00196
00197
00198 const GraphSlamAgents& nearby_slam_agents =
00199 m_conn_manager.getNearbySlamAgents();
00200
00201
00202
00203 for (GraphSlamAgents::_list_type::const_iterator
00204 it = nearby_slam_agents.list.begin();
00205 it != nearby_slam_agents.list.end();
00206 ++it) {
00207 const GraphSlamAgent& gsa = *it;
00208
00209
00210 auto search = [gsa](const TNeighborAgentMapProps* neighbor) {
00211 return (neighbor->agent == gsa);
00212 };
00213 typename neighbors_t::iterator n_it = find_if(
00214 m_neighbors.begin(),
00215 m_neighbors.end(), search);
00216
00217 if (n_it == m_neighbors.end()) {
00218
00219 m_neighbors.push_back(new TNeighborAgentMapProps(m_logger, gsa, m_nh));
00220 TNeighborAgentMapProps* latest_neighbor = m_neighbors.back();
00221 latest_neighbor->setupComm();
00222 m_logger->logFmt(LVL_WARN,
00223 "Initialized NeighborAgentMapProps instance for agent %s...",
00224 latest_neighbor->agent.topic_namespace.data.c_str());
00225
00226
00227 mrpt::graphslam::CWindowManager* win_manager = initWindowVisuals();
00228 win_manager->win->setWindowTitle(
00229 latest_neighbor->agent.topic_namespace.data);
00230 m_neighbors_to_windows.insert(make_pair(latest_neighbor, win_manager));
00231 this->monitorKeystrokes(win_manager->observer);
00232
00233 }
00234 }
00235
00236
00237 bool continue_exec = true;
00238 for (map<TNeighborAgentMapProps*, CWindowManager*>::const_iterator
00239 it = m_neighbors_to_windows.begin();
00240 it != m_neighbors_to_windows.end();
00241 ++it) {
00242
00243 CWindowManager* win_manager = it->second;
00244
00245 std::map<std::string, bool> events_map;
00246 win_manager->observer->returnEventsStruct(&events_map);
00247
00248 if (events_map.at(map_merge_keypress)) {
00249 mergeMaps();
00250 }
00251 win_manager->win->forceRepaint();
00252
00253
00254 if (!win_manager->isOpen() ||
00255 events_map.at(quit_keypress1) ||
00256 events_map.at(quit_keypress2)) {
00257 continue_exec = false;
00258 break;
00259 }
00260 }
00261
00262
00263 if (continue_exec) {
00264 std::map<std::string, bool> events_map;
00265 m_fused_map_win_manager->observer->returnEventsStruct(&events_map);
00266 if (events_map.at(map_merge_keypress)) {
00267 mergeMaps();
00268 }
00269 m_fused_map_win_manager->win->forceRepaint();
00270 continue_exec =
00271 m_fused_map_win_manager->isOpen() &&
00272 !events_map.at(quit_keypress1) &&
00273 !events_map.at(quit_keypress2);
00274 }
00275
00276 return continue_exec;
00277
00278 MRPT_END;
00279 }
00280
00281 void CMapMerger::mergeMaps() {
00282 MRPT_START;
00283 m_logger->logFmt(LVL_WARN, "In mergeMaps.");
00284
00285 CGridMapAligner gridmap_aligner;
00286 gridmap_aligner.options = m_alignment_options;
00287
00288
00289 maps_t mrpt_gridmaps;
00290 trajectories_t mrpt_trajectories;
00291
00292
00293 for (neighbors_t::const_iterator n_it = m_neighbors.begin();
00294 n_it != m_neighbors.end();
00295 ++n_it) {
00296 TNeighborAgentMapProps& neighbor = **n_it;
00297 CWindowManager* neighbor_win_manager = m_neighbors_to_windows.at(*n_it);
00298
00299
00300 removeObjectFrom3DScene(neighbor_win_manager->win);
00301 addSupWidgets(neighbor_win_manager->win);
00302
00303 if (neighbor.nav_map && neighbor.nav_robot_trajectory) {
00304
00305
00306
00307 COccupancyGridMap2D::Ptr map = COccupancyGridMap2D::Create();
00308 m_logger->logFmt(LVL_INFO, "Adding map of agent \"%s\" to the stack",
00309 neighbor.agent.topic_namespace.data.c_str());
00310 convert(*neighbor.nav_map, *map);
00311
00312
00313 addToWindow(neighbor_win_manager->win, *map);
00314 mrpt_gridmaps.insert(make_pair(*n_it, map));
00315
00316
00317
00318
00319 CSetOfLines::Ptr curr_traj = CSetOfLines::Create();
00320 curr_traj->setPose(CPose3D(0,0,0.3,0,0,0));
00321 curr_traj->setLineWidth(1.5);
00322 curr_traj->setColor(TColorf(0,0,1));
00323
00324
00325 curr_traj->appendLine(
00326 0, 0, 0,
00327 0, 0, 0);
00328
00329 for (nav_msgs::Path::_poses_type::const_iterator
00330 pth_it = neighbor.nav_robot_trajectory->poses.begin();
00331 pth_it != neighbor.nav_robot_trajectory->poses.end();
00332 ++pth_it) {
00333 curr_traj->appendLineStrip(pth_it->pose.position.x, pth_it->pose.position.y, 0);
00334 }
00335
00336 {
00337 COpenGLScene::Ptr &scene = neighbor_win_manager->win->get3DSceneAndLock();
00338 scene->insert(curr_traj);
00339
00340 neighbor_win_manager->win->unlockAccess3DScene();
00341 neighbor_win_manager->win->forceRepaint();
00342 }
00343
00344
00345 {
00346
00347
00348 auto tmp = CSetOfLines::Ptr(dynamic_cast<CSetOfLines*>(curr_traj->clone()));
00349 auto curr_traj = mrpt::ptr_cast<CSetOfLines>::from(tmp);
00350 ASSERT_(curr_traj);
00351 mrpt_trajectories.insert(make_pair(&neighbor, curr_traj));
00352 }
00353
00354 }
00355 }
00356
00357
00358 if (mrpt_gridmaps.size() >= 2) {
00359
00360 m_logger->logFmt(LVL_INFO, "Executing map merging for [%lu] gridmaps",
00361 static_cast<unsigned long>(mrpt_gridmaps.size()));
00362 int merge_counter = 0;
00363
00364
00365 std::string output_dir_fname = "map_merger_results";
00366 if (save_map_merging_results) {
00367 m_logger->logFmt(LVL_INFO,
00368 "Saving map-merging results to \"%s\"",
00369 output_dir_fname.c_str());
00370
00371
00372
00373
00374
00375 bool does_exist = directoryExists(output_dir_fname);
00376 if (does_exist) {
00377 deleteFilesInDirectory(output_dir_fname);
00378 }
00379 else {
00380 m_logger->logFmt(LVL_INFO, "Initializing gridmaps output directory.\n");
00381 createDirectory(output_dir_fname);
00382 }
00383 }
00384
00385
00386 COccupancyGridMap2D::Ptr fused_map = COccupancyGridMap2D::Create();
00387 fused_map->copyMapContentFrom(*mrpt_gridmaps.begin()->second);
00388
00389 ASSERT_(fused_map);
00390
00391 {
00392
00393 COpenGLScene::Ptr& fused_scene = m_fused_map_win_manager->win->get3DSceneAndLock();
00394 fused_scene.reset();
00395 m_logger->logFmt(LVL_INFO, "Clearing the fused map visuals");
00396
00397 addSupWidgets(m_fused_map_win_manager->win);
00398
00399
00400 CSetOfObjects::Ptr first_map_obj = CSetOfObjects::Create();
00401 fused_map->getAs3DObject(first_map_obj);
00402
00403
00404 first_map_obj->setName(format("map_%s",
00405 mrpt_gridmaps.begin()->first->agent.topic_namespace.data.c_str()));
00406 fused_scene->insert(first_map_obj);
00407
00408 m_fused_map_win_manager->win->unlockAccess3DScene();
00409 m_fused_map_win_manager->win->forceRepaint();
00410 }
00411
00412
00413 if (save_map_merging_results) {
00414 stringstream ss;
00415 ss << output_dir_fname << "/" << "map" << merge_counter;
00416 (mrpt_gridmaps.begin()->second)->saveMetricMapRepresentationToFile(ss.str());
00417 }
00418
00419
00420 double off_z = 1;
00421 double off_z_step = 1;
00422
00423
00424
00425 neighbor_to_is_used_t neighbor_to_is_used;
00426
00427
00428
00429
00430 neighbor_to_rel_pose_t neighbor_to_rel_pose;
00431 for (neighbors_t::const_iterator
00432 n_it = m_neighbors.begin();
00433 n_it != m_neighbors.end();
00434 ++n_it) {
00435 neighbor_to_is_used[*n_it] = false;
00436 neighbor_to_rel_pose[*n_it] = CPose2D();
00437 }
00438
00439
00440 neighbor_to_is_used[*m_neighbors.begin()] = true;
00441
00442
00443 for (maps_t::iterator
00444 m_it = std::next(mrpt_gridmaps.begin());
00445 m_it != mrpt_gridmaps.end();
00446 ++m_it, ++merge_counter) {
00447
00448 TNeighborAgentMapProps* curr_neighbor = m_it->first;
00449 COccupancyGridMap2D* curr_gridmap = m_it->second.get();
00450
00451
00452 CGridMapAligner::TReturnInfo results;
00453 float run_time = 0;
00454 CPosePDFGaussian init_estim;
00455 m_logger->logFmt(LVL_INFO,
00456 "Trying to align the maps, initial estimation: %s",
00457 init_estim.mean.asString().c_str());
00458 const CPosePDF::Ptr pdf_tmp = gridmap_aligner.AlignPDF(
00459 fused_map.get(), curr_gridmap,
00460 init_estim,
00461 &run_time, &results);
00462 m_logger->logFmt(LVL_INFO, "Elapsed Time: %f", run_time);
00463
00464
00465 CPosePDFSOG::Ptr pdf_out = CPosePDFSOG::Create();
00466 pdf_out->copyFrom(*pdf_tmp);
00467
00468 CPose2D pose_out; CMatrixDouble33 cov_out;
00469 pdf_out->getMostLikelyCovarianceAndMean(cov_out, pose_out);
00470
00471
00472 if (results.goodness > 0.999 || isEssentiallyZero(pose_out)) {
00473 continue;
00474 }
00475
00476 neighbor_to_rel_pose.at(curr_neighbor) = pose_out;
00477 neighbor_to_is_used.at(curr_neighbor) = true;
00478
00479 m_logger->logFmt(LVL_INFO, "%s\n",
00480 getGridMapAlignmentResultsAsString(*pdf_tmp, results).c_str());
00481
00482
00483 if (save_map_merging_results) {
00484 stringstream ss;
00485 ss << output_dir_fname << "/" << "map" << merge_counter;
00486 curr_gridmap->saveMetricMapRepresentationToFile(ss.str());
00487 }
00488
00489
00490 if (save_map_merging_results) {
00491 stringstream ss;
00492 ss << output_dir_fname << "/" << "fusing_proc_with"
00493 << "_" << merge_counter;
00494 COccupancyGridMap2D::saveAsEMFTwoMapsWithCorrespondences(
00495 ss.str(), fused_map.get(), curr_gridmap, results.correspondences);
00496 }
00497
00498
00499 {
00500 COpenGLScene::Ptr fused_scene = m_fused_map_win_manager->win->get3DSceneAndLock();
00501
00502
00503 m_logger->logFmt(LVL_INFO,
00504 "Adding map to the fused map visualiztion using transformation %s",
00505 pose_out.asString().c_str());
00506 CSetOfObjects::Ptr curr_map_obj = CSetOfObjects::Create();
00507 curr_gridmap->getAs3DObject(curr_map_obj);
00508 curr_map_obj->setName(format("map_%s",
00509 curr_neighbor->agent.topic_namespace.data.c_str()));
00510 curr_map_obj->setPose(pose_out + CPose3D(0,0,off_z,0,0,0));
00511 off_z += off_z_step;
00512 fused_scene->insert(curr_map_obj);
00513
00514 m_fused_map_win_manager->win->unlockAccess3DScene();
00515 m_fused_map_win_manager->win->forceRepaint();
00516 }
00517
00518
00519
00520
00521 }
00522
00523 TColorManager traj_color_mngr;
00524
00525 for (trajectories_t::const_iterator
00526 it = mrpt_trajectories.begin();
00527 it != mrpt_trajectories.end();
00528 ++it) {
00529
00530 TNeighborAgentMapProps* curr_neighbor = it->first;
00531
00532 if (!neighbor_to_is_used.at(curr_neighbor)) {
00533 m_logger->logFmt(LVL_WARN, "Skipping visualizing trajectory of agent %s in the fused map",
00534 curr_neighbor->agent.topic_namespace.data.c_str());
00535 continue;
00536 }
00537
00538 CSetOfLines::Ptr curr_traj = it->second;
00539 m_logger->logFmt(LVL_WARN, "Adding #%lu lines...",
00540 static_cast<unsigned long>(curr_traj->getLineCount()));
00541
00542
00543 CPose3D rel_pose(neighbor_to_rel_pose.at(curr_neighbor));
00544
00545 rel_pose += CPose3D(0,0,off_z,0,0,0);
00546
00547 curr_traj->setColor(traj_color_mngr.getNextTColorf());
00548 curr_traj->setPose(rel_pose);
00549 curr_traj->setName(format("traj_%s", curr_neighbor->agent.topic_namespace.data.c_str()));
00550 {
00551 COpenGLScene::Ptr fused_scene = m_fused_map_win_manager->win->get3DSceneAndLock();
00552 fused_scene->insert(curr_traj);
00553
00554 m_fused_map_win_manager->win->unlockAccess3DScene();
00555 m_fused_map_win_manager->win->forceRepaint();
00556 }
00557
00558 }
00559
00560
00561 {
00562
00563 COpenGLScene::Ptr fused_scene = m_fused_map_win_manager->win->get3DSceneAndLock();
00564 std::string fname = output_dir_fname + "/" + "output_scene.3DScene";
00565 fused_scene->saveToFile(fname);
00566
00567 m_fused_map_win_manager->win->unlockAccess3DScene();
00568 m_fused_map_win_manager->win->forceRepaint();
00569 }
00570
00571
00572
00573
00574
00575
00576 }
00577 MRPT_END;
00578 }
00579
00580 CWindowManager* CMapMerger::initWindowVisuals() {
00581 mrpt::graphslam::CWindowManager* win_manager = new CWindowManager();
00582 this->initWindowVisuals(win_manager);
00583 return win_manager;
00584 }
00585
00586 void CMapMerger::initWindowVisuals(
00587 mrpt::graphslam::CWindowManager* win_manager) {
00588 using namespace mrpt::opengl;
00589 using namespace mrpt::gui;
00590 using namespace mrpt::utils;
00591 using namespace mrpt::graphslam;
00592 ASSERT_(win_manager);
00593
00594 CWindowObserver* win_observer = new CWindowObserver();
00595 CDisplayWindow3D* win = new CDisplayWindow3D(
00596 "GraphSlam building procedure", 800, 600);
00597 win->setPos(400, 200);
00598 win_observer->observeBegin(*win);
00599 {
00600 COpenGLScene::Ptr &scene = win->get3DSceneAndLock();
00601 COpenGLViewport::Ptr main_view = scene->getViewport("main");
00602 win_observer->observeBegin(*main_view);
00603 win->unlockAccess3DScene();
00604 }
00605
00606
00607 win_manager->setCDisplayWindow3DPtr(win);
00608 win_manager->setWindowObserverPtr(win_observer);
00609
00610 addSupWidgets(win_manager->win);
00611 m_logger->logFmt(LVL_DEBUG, "Initialized CDisplayWindow3D...");
00612 }