Main MRPT website > C++ reference for MRPT 1.9.9
CHierarchicalMHMap.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hmtslam-precomp.h" // Precomp header
11 
14 #include <mrpt/poses/CPoint2D.h>
15 
16 using namespace mrpt::poses;
17 using namespace mrpt::slam;
18 using namespace mrpt::utils;
19 using namespace mrpt::hmtslam;
20 
22 
23 /*---------------------------------------------------------------
24  Constructor
25  ---------------------------------------------------------------*/
27 /*---------------------------------------------------------------
28  Destructor
29  ---------------------------------------------------------------*/
30 CHierarchicalMHMap::~CHierarchicalMHMap() { clear(); }
31 /*---------------------------------------------------------------
32  clear
33  ---------------------------------------------------------------*/
35 {
36  // Remaining arcs and nodes will be deleted now
37  // A delicate issue; we must:
38  // 1) .clear() all the smart pointers
39  // 2) then, empty the list of nodes/arcs, which will only
40  // contain empty smart pointers, thus will not raise callbacks again.
41  // ----------------------------------------------------------------
42  TNodeList nodes = m_nodes;
43  TArcList arcs = m_arcs;
44 
45  // 1:
46  std::for_each(
47  nodes.begin(), nodes.end(), metaprogramming::ObjectClearSecond());
48  std::for_each(arcs.begin(), arcs.end(), metaprogramming::ObjectClear2());
49 
50  // 2:
51  m_nodes.clear();
52  m_arcs.clear();
53 }
54 
55 /*---------------------------------------------------------------
56  writeToStream
57  ---------------------------------------------------------------*/
58 void CHierarchicalMHMap::writeToStream(
59  mrpt::utils::CStream& out, int* version) const
60 {
61  if (version)
62  *version = 0;
63  else
64  {
65  uint32_t n;
68 
69  // Nodes:
70  n = static_cast<uint32_t>(nodeCount());
71  out << n;
72  for (it = m_nodes.begin(); it != m_nodes.end(); it++)
73  out << *it->second;
74 
75  // Arcs:
76  n = static_cast<uint32_t>(arcCount());
77  out << n;
78  for (it2 = m_arcs.begin(); it2 != m_arcs.end(); it2++) out << *(*it2);
79  }
80 }
81 
82 /*---------------------------------------------------------------
83  readFromStream
84  ---------------------------------------------------------------*/
85 void CHierarchicalMHMap::readFromStream(mrpt::utils::CStream& in, int version)
86 {
87  switch (version)
88  {
89  case 0:
90  {
91  uint32_t i, n;
92 
93  // Clear previous contents:
94  clear();
95 
96  // Nodes:
97  in >> n;
98  for (i = 0; i < n; i++)
99  {
100  CHMHMapNode::Ptr node = mrpt::make_aligned_shared<CHMHMapNode>(
101  this); // This insert the node in my internal list via the
102  // callback method
103  in >> *node;
104  }
105 
106  // Arcs:
107  in >> n;
108  for (i = 0; i < n; i++)
109  {
110  // This insert the node in my internal list via the callback
111  // method
112  CHMHMapNode::Ptr p1, p2;
113  CHMHMapArc::Ptr arc = mrpt::make_aligned_shared<CHMHMapArc>(
114  p1, p2, THypothesisIDSet(), this);
115  in >> *arc;
116  }
117  }
118  break;
119  default:
121  };
122 }
123 
124 /*---------------------------------------------------------------
125  onNodeDestruction
126  ---------------------------------------------------------------*/
127 void CHierarchicalMHMap::onNodeDestruction(CHMHMapNode* node)
128 {
130 
131  it = m_nodes.find(node->getID());
132 
133  if (it != m_nodes.end())
134  if (node == it->second.get()) m_nodes.erase(it);
135 }
136 
137 /*---------------------------------------------------------------
138  onArcDestruction
139  ---------------------------------------------------------------*/
140 void CHierarchicalMHMap::onArcDestruction(CHMHMapArc* arc)
141 {
142  // Important note: We cannot create a temporary smart pointer here, since
143  // it will lead to an infinity recursion! (BUGFIX, JLBC SEP-2009)
144  TArcList::iterator it = m_arcs.find_ptr_to(arc);
145  if (it != m_arcs.end()) m_arcs.erase(it);
146 }
147 
148 /*---------------------------------------------------------------
149  onNodeAddition
150  ---------------------------------------------------------------*/
151 void CHierarchicalMHMap::onNodeAddition(CHMHMapNode::Ptr& node)
152 {
153  // Check if it is not already in the list:
154  TNodeList::iterator it = m_nodes.find(node->m_ID);
155 
156  if (it != m_nodes.end())
157  {
158  // Already in the list:
159  ASSERT_(node == it->second);
160  return;
161  }
162  else
163  {
164  // It is a new node: add to the list:
165  m_nodes[node->m_ID] = node;
166  }
167 }
168 
169 /*---------------------------------------------------------------
170  onArcAddition
171  ---------------------------------------------------------------*/
172 void CHierarchicalMHMap::onArcAddition(CHMHMapArc::Ptr& arc)
173 {
174  // Check if it is not already in the list:
175  TArcList::iterator it = m_arcs.find(arc);
176 
177  if (it == m_arcs.end()) // Is it new?
178  m_arcs.push_back(arc);
179 }
180 /*---------------------------------------------------------------
181  loadFromXMLfile
182  ---------------------------------------------------------------*/
183 
184 void CHierarchicalMHMap::loadFromXMLfile(std::string fileName)
185 {
186  CSimpleDatabase db;
188  size_t j, numnodes, numarcs;
189 
190  std::map<size_t, CHMHMapNode::Ptr> nodemap;
192  typedef std::pair<size_t, CHMHMapNode::Ptr> IDPair;
193 
194  std::map<size_t, CHMHMapNode::TNodeID> nodeanotmap;
196  typedef std::pair<size_t, CHMHMapNode::TNodeID> IDnodeanotPair;
197 
198  db.loadFromXML(fileName);
199 
200  table = db.getTable("nodes");
201  numnodes = table->getRecordCount();
202 
203  // printf("Loading nodes\n");
204  std::vector<std::string> node_anots;
205 
206  for (j = 0; j < numnodes; j++)
207  {
208  CHMHMapNode::Ptr node;
209  node = mrpt::make_aligned_shared<CHMHMapNode>(this);
210  node->m_label = table->get(j, "nodename");
211  nodemap.insert(IDPair(atoi(table->get(j, "id").c_str()), node));
212  node->m_nodeType.setType(table->get(j, "nodetype"));
213  node->m_hypotheses.insert(COMMON_TOPOLOG_HYP);
214  printf("Loaded node %s\n", node->m_label.c_str());
215 
216  std::deque<std::string> lista;
217  mrpt::system::tokenize(table->get(j, "annotation-list"), " ", lista);
218 
219  for (size_t r = 0; r < lista.size(); r++)
220  nodeanotmap.insert(
221  IDnodeanotPair((size_t)atoi(lista[r].c_str()), node->getID()));
222 
223  // A map with key the id of annotations and value the id of nodes;
224  }
225 
226  table = db.getTable("arcs");
227  numarcs = table->getRecordCount();
228  printf("Loading arcs\n");
229  for (j = 0; j < numarcs; j++)
230  {
231  CHMHMapArc::Ptr arc, arcrev;
232  size_t from, to;
233  from = atoi(table->get(j, "from").c_str());
234  to = atoi(table->get(j, "to").c_str());
235 
236  CHMHMapNode::Ptr nodefrom, nodeto;
237  nodemapit = nodemap.find(from);
238  nodefrom = nodemapit->second;
239  std::cout << "finding nodes" << std::endl;
240 
241  nodemapit = nodemap.find(to);
242  nodeto = nodemapit->second;
243  std::cout << "added arc from " << nodefrom->m_label << " to "
244  << nodeto->m_label << std::endl;
245 
246  arc = mrpt::make_aligned_shared<CHMHMapArc>(nodefrom, nodeto, 0, this);
247  arc->m_arcType.setType(table->get(j, "arctype"));
248  arc->m_hypotheses.insert(COMMON_TOPOLOG_HYP);
249 
250  if (atoi(table->get(j, "bidirectional").c_str()) == 1)
251  {
252  printf("Creating bidirectional arc\n");
253  arcrev = mrpt::make_aligned_shared<CHMHMapArc>(
254  nodeto, nodefrom, 0, this);
255  arcrev->m_arcType.setType(table->get(j, "arctype"));
256  arcrev->m_hypotheses.insert(COMMON_TOPOLOG_HYP);
257  }
258  }
259 
260  std::cout << "Graph with [" << numnodes << "] nodes and [" << numarcs
261  << "] arcs loaded successfully." << std::endl;
262 
263  table = db.getTable("annotations");
264  size_t numannot = table->getRecordCount();
265  printf("Loading annotations\n");
266  for (size_t j = 0; j < numannot; j++)
267  {
268  string type = table->get(j, "annotation-type");
269  string value = table->get(j, "annotation-value");
270  nodeanotmapit = nodeanotmap.find(atoi(table->get(j, "id").c_str()));
271 
272  if (nodeanotmapit != nodeanotmap.end())
273  {
274  if (type == "placePose")
275  {
276  CPoint2D::Ptr o = mrpt::make_aligned_shared<CPoint2D>();
277  o->fromString(value);
278 
279  CHMHMapNode::Ptr node = getNodeByID(nodeanotmapit->second);
280 
281  node->m_annotations.set(
283  }
284  }
285  }
286 }
287 /*---------------------------------------------------------------
288  dumpAsXMLfile
289  ---------------------------------------------------------------*/
290 
291 void CHierarchicalMHMap::dumpAsXMLfile(std::string fileName) const
292 {
293  CSimpleDatabase db;
294  CSimpleDatabaseTable::Ptr tablenodes, tablearcs, tableannots;
295  size_t i;
296 
297  tablenodes = db.createTable("nodes");
298  tablearcs = db.createTable("arcs");
299  tableannots = db.createTable("annotations");
300 
301  tablenodes->addField("id");
302  tablenodes->addField("nodename");
303  tablenodes->addField("nodetype");
304  tablenodes->addField("annotation-list");
305 
306  tablearcs->addField("id");
307  tablearcs->addField("from");
308  tablearcs->addField("to");
309  tablearcs->addField("arctype");
310  tablearcs->addField("bidirectional");
311  tablearcs->addField("annotation-list");
312 
313  tableannots->addField("id");
314  tableannots->addField("annotation-type");
315  tableannots->addField("annotation-value");
316 
317  // for nodes
318  printf("Generating nodes\n");
319  for (TNodeList::const_iterator it = m_nodes.begin(); it != m_nodes.end();
320  ++it)
321  {
322  i = tablenodes->appendRecord();
323  tablenodes->set(i, "nodename", it->second->m_label.c_str());
324  tablenodes->set(
325  i, "id", format("%i", static_cast<int>(it->second->getID())));
326  tablenodes->set(i, "nodetype", it->second->m_nodeType.getType());
327 
328  tablenodes->set(i, "annotation-list", ".");
330  it->second->m_annotations.begin();
331  ann != it->second->m_annotations.end(); ++ann)
332  {
333  size_t j = tableannots->appendRecord();
334  tableannots->set(
335  j, "id", format("%u", static_cast<unsigned int>(j)));
336  tableannots->set(j, "annotation-type", ann->name.c_str());
337  ASSERT_(ann->value)
338  string str;
339  if (IS_CLASS(ann->value, CPoint2D))
340  {
341  CPoint2D::Ptr o =
342  std::dynamic_pointer_cast<CPoint2D>(ann->value);
343  o->asString(str);
344  }
345  else
346  {
347  str = ObjectToString(ann->value.get());
348  }
349  tableannots->set(j, "annotation-value", str);
350  if (tablenodes->get(j, "annotation-list") == ".")
351  tablenodes->set(
352  i, "annotation-list",
353  format("%u", static_cast<unsigned int>(j)));
354  else
355  tablenodes->set(
356  i, "annotation-list",
357  tablenodes->get(j, "annotation-list") +
358  format("%u", static_cast<unsigned int>(j)));
359  }
360  }
361 
362  // for arcs
363  printf("Generating arcs (%u)\n", static_cast<unsigned int>(m_arcs.size()));
364 
365  for (TArcList::const_iterator it = m_arcs.begin(); it != m_arcs.end(); ++it)
366  {
367  size_t fromid, toid;
368 
369  fromid = (int)(*it)->getNodeFrom();
370  toid = (int)(*it)->getNodeTo();
371 
372  i = tablearcs->appendRecord();
373  tablearcs->set(i, "id", format("%u", static_cast<unsigned int>(i)));
374  tablearcs->set(
375  i, "from", format("%u", static_cast<unsigned int>(fromid)));
376  tablearcs->set(i, "to", format("%u", static_cast<unsigned int>(toid)));
377  tablearcs->set(i, "arctype", (*it)->m_arcType.getType());
378 
380  (*it)->m_annotations.begin();
381  ann != (*it)->m_annotations.end(); ++ann)
382  {
383  i = tableannots->appendRecord();
384  tableannots->set(
385  i, "id", format("%u", static_cast<unsigned int>(i)));
386  tableannots->set(i, "annotation-type", ann->name.c_str());
387 
388  // CSerializable *o=ann->value->clone(); // JL: duplicate???
389  // tableannots->set(i,"annotation-value",ObjectToString(o));
390  }
391  }
392  printf("Generating XML file\n");
393  db.saveAsXML(fileName.c_str());
394 
395  /*
396  std::string s;
397  s += format("NODE ID: %i\t LABEL:%s\tARCS: ",
398  (int)it->second->getID(), it->second->m_label.c_str() );
399  TArcList arcs;
400  it->second->getArcs(arcs);
401  for (TArcList::const_iterator a=arcs.begin();a!=arcs.end();++a)
402  s += format("%i-%i, ", (int)(*a)->getNodeFrom(),
403  (int)(*a)->getNodeTo() );
404 
405  st << s;
406 
407  for (CMHPropertiesValuesList::const_iterator ann =
408  it->second->m_annotations.begin(); ann !=
409  it->second->m_annotations.end(); ++ann)
410  {
411  s= format(" [HYPO ID #%02i] Annotation '%s' Class: ",
412  (int)ann->ID, ann->name.c_str() );
413  if ( ann->value )
414  s+= string(ann->value->GetRuntimeClass()->className);
415  else s+= "(nullptr)";
416 
417  st << s;
418 
419  if ( ann->name == NODE_ANNOTATION_REF_POSEID )
420  {
421  TPoseID refID;
422  it->second->m_annotations.getElemental(NODE_ANNOTATION_REF_POSEID,
423  refID, ann->ID );
424  st << format(" VALUE: %i",(int)refID);
425  }
426  else if ( ann->name == NODE_ANNOTATION_POSES_GRAPH )
427  {
428  CRobotPosesGraph::Ptr posesGraph =
429  it->second->m_annotations.getAs<CRobotPosesGraph>(NODE_ANNOTATION_POSES_GRAPH,ann->ID);
430  ASSERT_(posesGraph);
431 
432  st << format(" CRobotPosesGraph has %i
433  poses:",(int)posesGraph->size());
434  CPose3D pdfMean;
435  for (CRobotPosesGraph::const_iterator
436  p=posesGraph->begin();p!=posesGraph->end();++p)
437  {
438  const CPose3DPDFParticles &pdf = p->second.pdf;
439  pdf.getMean(pdfMean);
440  st << format(" Pose %i \t (%.03f,%.03f,%.03fdeg)",
441  (int)p->first,
442  pdfMean.x(),
443  pdfMean.y(),
444  RAD2DEG(pdfMean.yaw()));
445  }
446  }
447  }
448 
449  st << "";
450 
451  }
452 
453 
454  st << "";
455  st << "";
456  st << "LIST OF ARCS";
457  st << "================";
458 
459  for (TArcList::const_iterator it=m_arcs.begin();it!=m_arcs.end();++it)
460  {
461  std::string s;
462  s += format("ARC: %i -> %i\n", (int)(*it)->getNodeFrom(),
463  (int)(*it)->getNodeTo() );
464 
465  s+= string(" Arc type: ")+(*it)->m_arcType.getType();
466 
467  st << s;
468 
469  for (CMHPropertiesValuesList::const_iterator ann =
470  (*it)->m_annotations.begin(); ann != (*it)->m_annotations.end(); ++ann)
471  {
472  s= format(" [HYPO ID #%02i] Annotation '%s' Class: ",
473  (int)ann->ID, ann->name.c_str() );
474  if ( ann->value )
475  s+= string(ann->value->GetRuntimeClass()->className);
476  else s+= "(nullptr)";
477 
478  st << s;
479 
480  if ( ann->name == ARC_ANNOTATION_DELTA_SRC_POSEID )
481  {
482  TPoseID refID;
483  (*it)->m_annotations.getElemental(ARC_ANNOTATION_DELTA_SRC_POSEID,
484  refID, ann->ID );
485  st << format(" VALUE: %i",(int)refID);
486  }
487  else if ( ann->name == ARC_ANNOTATION_DELTA_TRG_POSEID )
488  {
489  TPoseID refID;
490  (*it)->m_annotations.getElemental(ARC_ANNOTATION_DELTA_TRG_POSEID,
491  refID, ann->ID );
492  st << format(" VALUE: %i",(int)refID);
493  }
494  else if ( ann->name == ARC_ANNOTATION_DELTA )
495  {
496  CSerializable::Ptr o =
497  (*it)->m_annotations.get(ARC_ANNOTATION_DELTA, ann->ID );
498  ASSERT_(o);
499 
500  CPose3DPDFGaussian relativePoseAcordToArc;
501  relativePoseAcordToArc.copyFrom(*CPose3DPDF::Ptr(o));
502 
503  st << format(" VALUE: (%f,%f,%f , %fdeg,%fdeg,%fdeg)",
504  relativePoseAcordToArc.mean.x(),
505  relativePoseAcordToArc.mean.y(),
506  relativePoseAcordToArc.mean.z(),
507  RAD2DEG( relativePoseAcordToArc.mean.yaw() ),
508  RAD2DEG( relativePoseAcordToArc.mean.pitch() ),
509  RAD2DEG( relativePoseAcordToArc.mean.roll() ) );
510  }
511  }
512 
513  st << "";
514  }
515  */
516 }
void asString(std::string &s) const
Returns a human-readable textual representation of the object (eg: "[0.02 1.04]" ) ...
Definition: CPoint.h:88
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
std::shared_ptr< CPoint2D > Ptr
Definition: CPoint2D.h:38
std::shared_ptr< CHMHMapArc > Ptr
Definition: CHMHMapArc.h:38
std::vector< TPropertyValueIDTriplet >::const_iterator const_iterator
#define COMMON_TOPOLOG_HYP
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:44
Classes related to the implementation of Hybrid Metric Topological (HMT) SLAM.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
GLenum GLsizei n
Definition: glext.h:5074
Scalar * iterator
Definition: eigen_plugins.h:26
bool loadFromXML(const std::string &fileName)
Loads the content of this database from a a XML file.
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:3531
const Scalar * const_iterator
Definition: eigen_plugins.h:27
bool saveAsXML(const std::string &fileName) const
Saves this database as a XML file.
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:189
An object for clearing an object (invokes its method ".clear()") given a pointer or smart-pointer...
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
A set of hypothesis IDs, used for arcs and nodes in multi-hypothesis hybrid maps. ...
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
std::shared_ptr< CSimpleDatabaseTable > Ptr
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
CSimpleDatabaseTable::Ptr getTable(const std::string &tableName)
Returns the table with the indicated name.
GLsizei const GLchar ** string
Definition: glext.h:4101
A class used to store a 2D point.
Definition: CPoint2D.h:36
This class impements a very simple database system.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
void tokenize(const std::string &inString, const std::string &inDelimiters, std::deque< std::string > &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
An object for clearing an object->second (invokes its method "clear()") given a pointer or smart-poin...
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::utils::CSerializable) is of t...
Definition: CObject.h:103
std::string ObjectToString(const CSerializable *o)
Used to pass MRPT objects into a CORBA-like object (strings).
GLuint in
Definition: glext.h:7274
The most high level class for storing hybrid, multi-hypothesis maps in a graph-based model...
#define ASSERT_(f)
TNodeID getID() const
Reads the ID of the node (read-only property)
std::shared_ptr< CHMHMapNode > Ptr
Definition: CHMHMapNode.h:42
GLenum GLsizei GLenum format
Definition: glext.h:3531
A class for representing an arc between two nodes in a hierarchical, multi-hypothesis map...
Definition: CHMHMapArc.h:31
std::map< CHMHMapNode::TNodeID, std::shared_ptr< CHMHMapNode > > TNodeList
A map between node IDs and nodes (used in HMT-SLAM).
Definition: CHMHMapNode.h:144
GLsizei const GLfloat * value
Definition: glext.h:4117
#define NODE_ANNOTATION_PLACE_POSE
unsigned __int32 uint32_t
Definition: rptypes.h:47
CSimpleDatabaseTable::Ptr createTable(const std::string &name)
Creates a new table in the DB, initially empty.
A class for storing a sequence of arcs (a path).
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
A class for representing a node in a hierarchical, multi-hypothesis map.
Definition: CHMHMapNode.h:36



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019