MRPT  1.9.9
PbMapLocaliser.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 /* Plane-based Map (PbMap) library
11  * Construction of plane-based maps and localization in it from RGBD Images.
12  * Writen by Eduardo Fernandez-Moral. See docs for <a
13  * href="group__mrpt__pbmap__grp.html" >mrpt-pbmap</a>
14  */
15 #include "pbmap-precomp.h" // Precompiled headers
16 
17 #if MRPT_HAS_PCL
18 
23 #include <pcl/common/time.h>
24 #include <pcl/io/pcd_io.h>
25 #include <fstream>
26 #include <iostream>
27 
28 using namespace std;
29 using namespace mrpt::pbmap;
30 
31 double time1, time2;
32 
33 PbMapLocaliser::PbMapLocaliser(PbMap& mPbM, const string& config_file)
34  : mPbMap(mPbM),
35  m_pbMapLocaliser_must_stop(false),
36  m_pbMapLocaliser_finished(false)
37 {
38  matcher.configLocaliser.load_params(config_file);
39  std::cout << "PbMapLocaliser::PbMapLocaliser min_planes_recognition "
41  << " color thresholds " << matcher.configLocaliser.color_threshold
44 
45  LoadPreviousPbMaps("/home/edu/newPbMaps/PbMaps.txt");
46 
47  pbMapLocaliser_hd = std::thread(&PbMapLocaliser::run, this);
48 }
49 
50 // Load Previous PbMaps
52 {
53  cout << "PbMapLocaliser::LoadPreviousPbMaps(...)\n";
54  std::ifstream configFile;
55  configFile.open(fileMaps.c_str());
56 
57  string mapFile, filepath = "/home/edu/newPbMaps/";
58  totalPrevPlanes = 0;
59  while (!configFile.eof())
60  {
61  // floorPlane = -1;
62  getline(configFile, mapFile);
63  if (mapFile == "") break;
64 
65  if (mapFile.at(0) == '%') continue;
66  cout << "Load map: " << filepath << mapFile << endl;
67 
68  PbMap previousPbMap;
69  previousPbMap.loadPbMap(filepath + mapFile);
70 
71  previousPbMapNames.push_back(mapFile);
72  previousPbMaps.push_back(previousPbMap);
73 
74  // prevPbMap.vPlaness.push_back(vPlanesTemp);
75  // previousPbMapNames.push_back(mapFile);
76  // vFloors.push_back(floorPlane);
77  totalPrevPlanes += previousPbMap.vPlanes.size();
78  // cout << "PbMap loaded has " << previousPbMap.vPlanes.size() << "
79  // planes" << endl;
80  }
81  // cout << "Size: " << totalPrevPlanes << " " << vFloors.size() << endl;
82  // cout << "Floors: ";
83  // for(unsigned i=0; i< vFloors.size(); i++)
84  // cout << vFloors[i] << " ";
85  // cout << endl;
86 
87  configFile.close();
88  cout << "PbMapLocaliser:: previous PbMaps loaded\n";
89 }
90 
91 // Check 2nd order neighbors of the reference plane
93 {
94  cout << "PbMapLocaliser::compareSubgraphNeighbors\n";
95  PbMap& matchedPbMap = previousPbMaps[bestMap];
96 
97  for (auto it = bestMatch.begin(); it != bestMatch.end(); it++)
98  {
99  // TODO: use the graph to grow
100  if (matcher.configLocaliser.graph_mode == 0) // Nearby neighbors -
101  // Check the 2nd order
102  // neighbors of the
103  // matched planes
104  for (auto it1 = mPbMap.vPlanes[it->first].nearbyPlanes.begin();
105  it1 != mPbMap.vPlanes[it->first].nearbyPlanes.end(); it1++)
106  {
107  if (matcher.subgraphSrc->subgraphPlanesIdx.count(*it1))
108  continue;
109 
110  for (auto it2 =
111  matchedPbMap.vPlanes[it->second].nearbyPlanes.begin();
112  it2 != matchedPbMap.vPlanes[it->second].nearbyPlanes.end();
113  it2++)
114  {
115  if (matcher.subgraphTrg->subgraphPlanesIdx.count(*it2))
116  continue;
117 
119  mPbMap.vPlanes[*it1], matchedPbMap.vPlanes[*it2],
120  matchedPbMap, false)) //(FloorPlane != -1 &&
121  // FloorPlaneMap != -1) ? true
122  //: false ) )
123  continue;
124  for (auto it_matched = bestMatch.begin();
125  it_matched != bestMatch.end(); it_matched++)
127  mPbMap.vPlanes[*it1],
128  mPbMap.vPlanes[it_matched->first],
129  matchedPbMap.vPlanes[*it2],
130  matchedPbMap.vPlanes[it_matched->second]))
131  continue;
132 
133  // Asign new neighbor
134  bestMatch[*it1] = *it2;
135  }
136  }
137  else // if(matcher.configLocaliser.graph_mode == 1)// Co-visible
138  // neighbors - Check the 2nd order neighbors of the matched planes
139  for (auto it1 = mPbMap.vPlanes[it->first].neighborPlanes.begin();
140  it1 != mPbMap.vPlanes[it->first].neighborPlanes.end(); it1++)
141  {
142  if (matcher.subgraphSrc->subgraphPlanesIdx.count(it1->first))
143  continue;
144 
145  for (auto it2 = matchedPbMap.vPlanes[it->second]
146  .neighborPlanes.begin();
147  it2 !=
148  matchedPbMap.vPlanes[it->second].neighborPlanes.end();
149  it2++)
150  {
152  it2->first))
153  continue;
154 
156  mPbMap.vPlanes[it1->first],
157  matchedPbMap.vPlanes[it2->first], matchedPbMap,
158  false)) //(FloorPlane != -1 && FloorPlaneMap != -1)
159  //? true : false ) )
160  continue;
161  for (auto it_matched = bestMatch.begin();
162  it_matched != bestMatch.end(); it_matched++)
164  mPbMap.vPlanes[it1->first],
165  mPbMap.vPlanes[it_matched->first],
166  matchedPbMap.vPlanes[it2->first],
167  matchedPbMap.vPlanes[it_matched->second]))
168  continue;
169 
170  // Asign new neighbor
171  bestMatch[it1->first] = it2->first;
172  }
173  }
174  }
175 }
176 
178 {
179  double area = 0.0;
180  for (auto it = bestMatch.begin(); it != bestMatch.end(); it++)
181  area += mPbMap.vPlanes[it->first].areaVoxels;
182 
183 #ifdef _VERBOSE
184  cout << "getAreaMatch " << area << endl;
185 #endif
186 
187  return area;
188 }
189 
190 /**!
191  * Searches the input plane in the rest of planes of the map taking into account
192  * the neighboring relations
193  */
195 {
196 #ifdef _VERBOSE
197  cout << "\nSearching plane P" << searchPlane.id << " numNeigs "
198  << searchPlane.neighborPlanes.size() << " in map composed of "
199  << totalPrevPlanes << " planes\n";
200 #endif
201 
202  // REVISAR: Esto cambia el codigo anterior (antes la vecindad actual
203  // contenia todos los vecinos de los planos observados
204  Subgraph currentSubgraph(&mPbMap, searchPlane.id);
205  // matcher.setSourceSubgraph(currentSubgraph);
206 
207  for (size_t mapId = 0; mapId < previousPbMaps.size(); mapId++)
208  {
209  PbMap& prevPbMap = previousPbMaps[mapId];
210 
211  for (size_t i = 0; i < prevPbMap.vPlanes.size(); i++)
212  {
213  Plane& targetPlane = prevPbMap.vPlanes[i];
214 
215  // Do not consider evaluating planes which do not have more than
216  // min_planes_recognition neighbor planes (too much uncertainty)
218  {
219  if (targetPlane.nearbyPlanes.size() <
221  {
222  continue;
223  }
224  }
225  else // matcher.configLocaliser.graph_mode = 1
226  {
227  if (targetPlane.neighborPlanes.size() <
229  {
230  continue;
231  }
232  }
233 
234  Subgraph targetSubgraph(&prevPbMap, targetPlane.id);
235  // matcher.setTargetSubgraph(targetSubgraph);
236 
237  // cout << "\nsource size " <<
238  // currentSubgraph.subgraphPlanesIdx.size() << endl;
239  // cout << "target size " <<
240  // targetSubgraph.subgraphPlanesIdx.size() << endl;
241  std::map<unsigned, unsigned> resultingMatch =
242  matcher.compareSubgraphs(currentSubgraph, targetSubgraph);
243 
244  // cout << "ResultingMatch size " << resultingMatch.size() <<
245  // endl;
246  if (resultingMatch.size() > bestMatch.size())
247  {
248  bestMap = mapId;
249  bestMatch = resultingMatch;
250  }
251 
252  // Evaluate Score of the matched places
253  // if( score > maxScore)
254  // {
255  // max2ndScore = maxScore;
256  // maxScore = score;
257  // winnerPlane = targetPlane.label;
258  // }
259  // score_results[i] = comparePlanes(searchPlane, targetPlane);
260  }
261  }
262 
263 #ifdef _VERBOSE
264  cout << "bestMatch size " << bestMatch.size() << " min "
266 #endif
267 
268  if (bestMatch.size() >=
270  .min_planes_recognition) // Assign label of previous map plane
271  {
272 #ifdef _VERBOSE
273  cout << "Context matched\n";
274 #endif
275 
276  // compareSubgraphNeighbors(matcher);
277 
278  PbMap& winnerPbMap = previousPbMaps[bestMap];
279 
280  // We require that the sum of the areas of the matched planes is above a
281  // minimum
282  if (getAreaMatch() < 3.0) return false;
283 
284  pcl::PointXYZ placePos(0, 0, 0);
285  for (auto it = bestMatch.begin(); it != bestMatch.end(); it++)
286  {
287  if (mPbMap.vPlanes[it->first].label !=
288  winnerPbMap.vPlanes[it->second].label)
289  {
290  placePos.x += mPbMap.vPlanes[it->first].v3center[0];
291  placePos.y += mPbMap.vPlanes[it->first].v3center[1];
292  placePos.z += mPbMap.vPlanes[it->first].v3center[2];
293  if (planeRecognitionLUT.count(
294  winnerPbMap.vPlanes[it->second].label))
295  {
296  cout << "Re-assign plane label\n";
297  if (bestMatch.size() >=
298  planeRecognitionLUT[winnerPbMap.vPlanes[it->second]
299  .label]
300  .second)
301  {
302  mPbMap
304  [winnerPbMap.vPlanes[it->second].label]
305  .first]
306  .label = ""; // Delete previous label asignment
307  mPbMap.vPlanes[it->first].label =
308  winnerPbMap.vPlanes[it->second].label;
309  planeRecognitionLUT[winnerPbMap.vPlanes[it->second]
310  .label] =
311  pair<int, double>(
312  mPbMap.vPlanes[it->first].id, bestMatch.size());
313  }
314  else
315  mPbMap.vPlanes[it->first].label = "";
316  }
317  else
318  {
319 #ifdef _VERBOSE
320  cout << "Assign plane label\n";
321 #endif
322 
323  planeRecognitionLUT[winnerPbMap.vPlanes[it->second].label] =
324  pair<int, double>(
325  mPbMap.vPlanes[it->first].id, bestMatch.size());
326  mPbMap.vPlanes[it->first].label =
327  winnerPbMap.vPlanes[it->second].label;
328  }
329  }
330  }
331 
332  placePos.x /= bestMatch.size();
333  placePos.y /= bestMatch.size();
334  placePos.z /= bestMatch.size();
336 
337  // Check previous assignments. TODO. change the external label based
338  // system
339  // if(searchPlane.label != winnerPlane)
340  // {
341  // if(planeRecognitionLUT.count(winnerPlane) )
342  // {
343  // if( bestMatch.size() >=
344  // planeRecognitionLUT[winnerPlane].second )
345  // {
346  // mPbMap.vPlanes[planeRecognitionLUT[winnerPlane].first].label
347  // = ""; // Delete previous label asignment
348  // searchPlane.label = winnerPlane;
349  // planeRecognitionLUT[winnerPlane] =
350  // pair<int,double>(searchPlane.id, bestMatch.size());
351  // }
352  // else
353  // searchPlane.label = "";
354  // }
355  // else
356  // {
357  // planeRecognitionLUT[winnerPlane] =
358  // pair<int,double>(searchPlane.id, bestMatch.size());
359  // searchPlane.label = winnerPlane;
360  // }
361  // }
362 
363  // Superimpose model
364  Eigen::Matrix4f rigidTransf; // Pose of map as from current model
365  Eigen::Matrix4f rigidTransfInv; // Pose of model as from current map
366  ConsistencyTest fitModel(mPbMap, winnerPbMap);
367  rigidTransf = fitModel.getRTwithModel(bestMatch);
368  rigidTransfInv = inverse(rigidTransf);
369 
370  // Read in the cloud data
371  pcl::PCDReader reader;
372  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model(
373  new pcl::PointCloud<pcl::PointXYZRGBA>);
374  string filename = "/home/edu/Projects/PbMaps/" +
375  previousPbMapNames[bestMap] + "/MapPlanes.pcd";
376  reader.read(filename, *model);
377  alignedModelPtr.reset(new pcl::PointCloud<pcl::PointXYZRGBA>);
378  pcl::transformPointCloud(*model, *alignedModelPtr, rigidTransfInv);
379 
380  return true;
381  }
382 
383  // TODO Has this place been matched before? Check it and if so, decide which
384  // is the best match
385  return false;
386 }
387 
389 {
390  // cout << "run PbMapLocaliser\n";
391  bool placeFound = false;
392 
393  std::map<unsigned, vector<double>> timeLocalizer;
394  std::map<unsigned, vector<int>> nCheckLocalizer;
395  time1 = 0.0;
396  time2 = 0.0;
397 
398  while (!m_pbMapLocaliser_must_stop && !placeFound)
399  {
400  // cout << "while...\n";
401  if (vQueueObservedPlanes.empty()) // if(sQueueObservedPlanes.empty())
402  std::this_thread::sleep_for(50ms);
403 
404  else
405  {
406  while (!vQueueObservedPlanes.empty())
407  {
408  // Do not consider searching planes which do not have more than
409  // 2 neighbor planes (too much uncertainty)
411  0) // Nearby neighbors
412  {
413  // cout << "vecinos1 " <<
414  // mPbMap.vPlanes[vQueueObservedPlanes[0]].nearbyPlanes.size()
415  // << endl;
417  .nearbyPlanes.size() <
419  {
420  vQueueObservedPlanes.erase(
421  vQueueObservedPlanes.begin());
422  continue;
423  }
424  }
425  else // matcher.configLocaliser.graph_mode = 1
426  {
427  // cout << "vecinos2 " <<
428  // mPbMap.vPlanes[vQueueObservedPlanes[0]].neighborPlanes.size()
429  // << endl;
431  .neighborPlanes.size() <
433  {
434  vQueueObservedPlanes.erase(
435  vQueueObservedPlanes.begin());
436  continue;
437  }
438  }
439 
440  // cout << "Search context\n";
442  // #ifdef _VERBOSE
443  double search_plane_start = pcl::getTime();
444  // #endif
445 
447  {
448  placeFound = true;
449  // #ifdef _VERBOSE
450  double search_plane_end = pcl::getTime();
451  std::cout << "PLACE FOUND. Search took "
452  << double(search_plane_end - search_plane_start)
453  << " s\n";
454  // #endif
455  break;
456  }
457 
459 
460  // cout << "nChecks " << matcher.nCheckConditions << endl;
461  double search_plane_end = pcl::getTime();
462  if (timeLocalizer.count(mPbMap.vPlanes[vQueueObservedPlanes[0]]
463  .neighborPlanes.size()) == 0)
464  {
465  timeLocalizer[mPbMap.vPlanes[vQueueObservedPlanes[0]]
466  .neighborPlanes.size()]
467  .push_back(
468  double(search_plane_end - search_plane_start));
469  nCheckLocalizer[mPbMap.vPlanes[vQueueObservedPlanes[0]]
470  .neighborPlanes.size()]
471  .push_back(matcher.nCheckConditions);
472  }
473  else
474  {
475  vector<double> firstElement(
476  1, double(search_plane_end - search_plane_start));
477  vector<int> firstElement_(1, matcher.nCheckConditions);
478  timeLocalizer[mPbMap.vPlanes[vQueueObservedPlanes[0]]
479  .neighborPlanes.size()] = firstElement;
480  nCheckLocalizer[mPbMap.vPlanes[vQueueObservedPlanes[0]]
481  .neighborPlanes.size()] = firstElement_;
482  }
483 
484 #ifdef _VERBOSE
485  double search_plane_end = pcl::getTime();
486  std::cout
487  << "Search a plane took "
488  << double(search_plane_end - search_plane_start)
489  << std::endl; //<< " or " << clock.Tac() << std::endl;
490 #endif
491  }
492  }
493  }
495 
496  cout << "Print TIME PbLocalizer\n";
497  cout << "Tiempo1 " << time1 << " tiempo2 " << time2 << endl;
498  ;
499  auto itChecks = nCheckLocalizer.begin();
500  for (auto it = timeLocalizer.begin(); it != timeLocalizer.end(); it++)
501  {
502  double sum_times = 0;
503  double sum_nChecks = 0;
504  for (unsigned j = 0; j < it->second.size(); j++)
505  {
506  sum_times += it->second[j];
507  sum_nChecks += itChecks->second[j];
508  }
509  itChecks++;
510 
511  cout << "Size " << it->first << " time "
512  << sum_times / it->second.size() << endl;
513  cout << "... nChecks " << sum_nChecks / it->second.size() << endl;
514  }
515 }
516 
518 {
520  while (!m_pbMapLocaliser_finished) std::this_thread::sleep_for(1ms);
521  cout << "Waiting for PbMapLocaliser thread to die.." << endl;
522 
523  pbMapLocaliser_hd.join();
524 
525  return true;
526 }
527 
529 #endif
void loadPbMap(std::string PbMapFile)
Definition: PbMap.cpp:96
double time1
void load_params(const std::string &config_file_name)
std::vector< std::string > previousPbMapNames
std::map< std::string, pcl::PointXYZ > foundPlaces
A class used to store a planar feature (Plane for short).
Definition: Plane.h:43
std::map< unsigned, unsigned > neighborPlanes
Definition: Plane.h:128
STL namespace.
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr alignedModelPtr
_u8 model
Definition: rplidar_cmd.h:19
Eigen::Matrix< dataType, 4, 4 > inverse(Eigen::Matrix< dataType, 4, 4 > &pose)
Definition: Miscellaneous.h:81
std::set< unsigned > nearbyPlanes
Definition: Plane.h:127
GLsizei const GLchar ** string
Definition: glext.h:4116
std::vector< unsigned > vQueueObservedPlanes
std::map< unsigned, unsigned > bestMatch
double time2
bool searchPlaneContext(Plane &searchPlane)
! Searches the input plane in the rest of planes of the map taking into account the neighboring relat...
void compareSubgraphNeighbors(SubgraphMatcher &matcher)
config_heuristics configLocaliser
std::map< unsigned, unsigned > compareSubgraphs(Subgraph &subgraphSource, Subgraph &subgraphTarget, const int option=0)
unsigned id
! Parameters to allow the plane-based representation of the map by a graph
Definition: Plane.h:124
bool evalUnaryConstraints(Plane &plane1, Plane &plane2, PbMap &trgPbMap, bool useStructure=false)
! Check if the two input planes could be the same
bool evalBinaryConstraints(Plane &plane1, Plane &plane2, Plane &planeA, Plane &planeB)
! Compares the relation between Ref-neigRef with the relation between Check-neigCheck.
void LoadPreviousPbMaps(std::string fileMaps)
std::set< unsigned > subgraphPlanesIdx
Definition: Subgraph.h:63
std::vector< Plane > vPlanes
Definition: pbmap/PbMap.h:54
std::vector< PbMap > previousPbMaps
A class used to store a Plane-based Map (PbMap).
Definition: pbmap/PbMap.h:44
std::map< std::string, std::pair< int, double > > planeRecognitionLUT
*PbMapLocaliser y montarlo en un define *size_t totalPrevPlanes
Eigen::Matrix4f getRTwithModel(std::map< unsigned, unsigned > &matched_planes)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019