Main MRPT website > C++ reference for MRPT 1.9.9
CLocalMetricHypothesis.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 
13 #include <mrpt/system/os.h>
16 #include <mrpt/opengl/CEllipsoid.h>
18 #include <mrpt/opengl/CText.h>
19 #include <mrpt/opengl/CSphere.h>
20 #include <mrpt/opengl/CArrow.h>
22 
24 
25 using namespace mrpt;
26 using namespace mrpt::slam;
27 using namespace mrpt::hmtslam;
28 using namespace mrpt::utils;
29 using namespace mrpt::opengl;
30 using namespace mrpt::obs;
31 using namespace mrpt::maps;
32 using namespace mrpt::poses;
33 using namespace mrpt::math;
34 using namespace std;
35 
38 
39 /*---------------------------------------------------------------
40  Normal constructor
41  ---------------------------------------------------------------*/
43  : m_parent(parent), m_log_w_metric_history()
44 // m_log_w_topol_history()
45 {
46  m_log_w = 0;
47  m_accumRobotMovementIsValid = false;
48 }
49 
50 /*---------------------------------------------------------------
51  Destructor
52  ---------------------------------------------------------------*/
53 CLocalMetricHypothesis::~CLocalMetricHypothesis() { m_poseParticles.clearParticles(); }
54 /*---------------------------------------------------------------
55  getAs3DScene
56 
57  Returns a 3D representation of the current robot pose, all
58  the poses in the auxiliary graph, and each of the areas
59  they belong to.
60  ---------------------------------------------------------------*/
61 void CLocalMetricHypothesis::getAs3DScene(
62  opengl::CSetOfObjects::Ptr& objs) const
63 {
64  objs->clear();
65 
66  // -------------------------------------------
67  // Draw a grid on the ground:
68  // -------------------------------------------
69  {
71  mrpt::make_aligned_shared<opengl::CGridPlaneXY>(
72  -100, 100, -100, 100, 0, 5);
73  obj->setColor(0.4, 0.4, 0.4);
74 
75  objs->insert(obj); // it will free the memory
76  }
77 
78  // ---------------------------------------------------------
79  // Draw each of the robot poses as 2D/3D ellipsoids
80  // For the current pose, draw the robot itself as well.
81  // ---------------------------------------------------------
82  std::map<TPoseID, CPose3DPDFParticles> lstPoses;
84  getPathParticles(lstPoses);
85 
86  // -----------------------------------------------
87  // Draw a 3D coordinates corner for each cluster
88  // -----------------------------------------------
89  {
90  std::lock_guard<std::mutex> lock(m_parent->m_map_cs);
91 
92  for (TNodeIDSet::const_iterator n = m_neighbors.begin();
93  n != m_neighbors.end(); ++n)
94  {
95  const CHMHMapNode::Ptr node = m_parent->m_map.getNodeByID(*n);
96  ASSERT_(node);
97  TPoseID poseID_origin;
98  CPose3D originPose;
99  if (node->m_annotations.getElemental(
100  NODE_ANNOTATION_REF_POSEID, poseID_origin, m_ID))
101  {
102  lstPoses[poseID_origin].getMean(originPose);
103 
105  corner->setPose(originPose);
106  objs->insert(corner);
107  }
108  }
109  } // end of lock on map_cs
110 
111  // Add a camera following the robot:
112  // -----------------------------------------
113  const CPose3D meanCurPose = lstPoses[m_currentRobotPose].getMeanVal();
114  {
115  opengl::CCamera::Ptr cam = mrpt::make_aligned_shared<opengl::CCamera>();
116  cam->setZoomDistance(85);
117  cam->setAzimuthDegrees(45 + RAD2DEG(meanCurPose.yaw()));
118  cam->setElevationDegrees(45);
119  cam->setPointingAt(meanCurPose);
120  objs->insert(cam);
121  }
122 
123  map<CHMHMapNode::TNodeID, CPoint3D>
124  areas_mean; // Store the mean pose of each area
125  map<CHMHMapNode::TNodeID, int> areas_howmany;
126 
127  for (it = lstPoses.begin(); it != lstPoses.end(); it++)
128  {
130  mrpt::make_aligned_shared<opengl::CEllipsoid>();
131  // Color depending on being into the current area:
132  if (m_nodeIDmemberships.find(it->first)->second ==
133  m_nodeIDmemberships.find(m_currentRobotPose)->second)
134  ellip->setColor(0, 0, 1);
135  else
136  ellip->setColor(1, 0, 0);
137 
138  const CPose3DPDFParticles* pdfParts = &it->second;
139  CPose3DPDFGaussian pdf;
140  pdf.copyFrom(*pdfParts);
141 
142  // Mean:
143  ellip->setLocation(
144  pdf.mean.x(), pdf.mean.y(),
145  pdf.mean.z() + 0.005); // To be above the ground gridmap...
146 
147  // Cov:
148  CMatrixDouble C = CMatrixDouble(pdf.cov); // 6x6 cov.
149  C.setSize(3, 3);
150 
151  // Is a 2D pose??
152  if (pdf.mean.pitch() == 0 && pdf.mean.roll() == 0 &&
153  pdf.cov(2, 2) < 1e-4f)
154  C.setSize(2, 2);
155 
156  ellip->setCovMatrix(C);
157 
158  ellip->enableDrawSolid3D(false);
159 
160  // Name:
161  ellip->setName(format("P%u", (unsigned int)it->first));
162  ellip->enableShowName();
163 
164  // Add it:
165  objs->insert(ellip);
166 
167  // Add an arrow for the mean direction also:
168  {
170  0, 0, 0, 0.20f, 0, 0, 0.25f, 0.005f, 0.02f);
171  obj->setColor(1, 0, 0);
172  obj->setPose(pdf.mean);
173  objs->insert(obj);
174  }
175 
176  // Is this the current robot pose?
177  if (it->first == m_currentRobotPose)
178  {
179  // Draw robot:
181  robot->setPose(pdf.mean);
182 
183  // Add it:
184  objs->insert(robot);
185  }
186  else // The current robot pose does not count
187  {
188  // Compute the area means:
190  m_nodeIDmemberships.find(it->first);
191  ASSERT_(itAreaId != m_nodeIDmemberships.end());
192  CHMHMapNode::TNodeID areaId = itAreaId->second;
193  areas_howmany[areaId]++;
194  areas_mean[areaId].x_incr(pdf.mean.x());
195  areas_mean[areaId].y_incr(pdf.mean.y());
196  areas_mean[areaId].z_incr(pdf.mean.z());
197  }
198  } // end for it
199 
200  // Average area means:
203  ASSERT_(areas_howmany.size() == areas_mean.size());
204  for (itMeans = areas_mean.begin(), itHowMany = areas_howmany.begin();
205  itMeans != areas_mean.end(); itMeans++, itHowMany++)
206  {
207  ASSERT_(itHowMany->second > 0);
208 
209  float f = 1.0f / itHowMany->second;
210  itMeans->second *= f;
211  }
212 
213  // -------------------------------------------------------------------
214  // Draw lines between robot poses & their corresponding area sphere
215  // -------------------------------------------------------------------
216  for (it = lstPoses.begin(); it != lstPoses.end(); it++)
217  {
218  if (it->first != m_currentRobotPose)
219  {
220  CPoint3D areaPnt(
221  areas_mean[m_nodeIDmemberships.find(it->first)->second]);
222  areaPnt.z_incr(m_parent->m_options.VIEW3D_AREA_SPHERES_HEIGHT);
223 
224  const CPose3DPDFParticles* pdfParts = &it->second;
225  CPose3DPDFGaussian pdf;
226  pdf.copyFrom(*pdfParts);
227 
229  mrpt::make_aligned_shared<opengl::CSimpleLine>();
230  line->setColor(0.8, 0.8, 0.8, 0.3);
231  line->setLineWidth(2);
232 
233  line->setLineCoords(
234  pdf.mean.x(), pdf.mean.y(), pdf.mean.z(), areaPnt.x(),
235  areaPnt.y(), areaPnt.z());
236  objs->insert(line);
237  }
238  } // end for it
239 
240  // -------------------------------------------------------------------
241  // Draw lines for links between robot poses
242  // -------------------------------------------------------------------
243  // for (it=m_robotPoses.begin(); it!=m_robotPoses.end();it++)
244  /* for (it=lstPoses.begin(); it!=lstPoses.end();it++)
245  {
246  const CPose3DPDFParticles *myPdfParts = &it->second;
247  CPose3DPDFGaussian myPdf;
248  myPdf.copyFrom( *myPdfParts );
249 
250  std::map<TPoseID,TInterRobotPosesInfo>::const_iterator itLink;
251  for
252  (itLink=it->second.m_links.begin();itLink!=it->second.m_links.end();itLink++)
253  {
254  if (itLink->second.SSO>0.7)
255  {
256  CRobotPosesAuxiliaryGraph::const_iterator hisIt =
257  m_robotPoses.find( itLink->first );
258  ASSERT_( hisIt !=m_robotPoses.end() );
259 
260  const CPose3DPDFGaussian *hisPdf = & hisIt->second.m_pose;
261 
262  opengl::CSimpleLine::Ptr line =
263  mrpt::make_aligned_shared<opengl::CSimpleLine>();
264  line->m_color_R = 0.2f;
265  line->m_color_G = 0.8f;
266  line->m_color_B = 0.2f;
267  line->m_color_A = 0.3f;
268  line->m_lineWidth = 3.0f;
269 
270  line->m_x0 = myPdf->mean.x;
271  line->m_y0 = myPdf->mean.y;
272  line->m_z0 = myPdf->mean.z;
273 
274  line->m_x1 = hisPdf->mean.x;
275  line->m_y1 = hisPdf->mean.y;
276  line->m_z1 = hisPdf->mean.z;
277 
278  objs->insert( line );
279  }
280  }
281  } // end for it
282  */
283 
284  // ---------------------------------------------------------
285  // Draw each of the areas in the neighborhood:
286  // ---------------------------------------------------------
287  {
288  std::lock_guard<std::mutex> lock(
289  m_parent->m_map_cs); // To access nodes' labels.
290 
291  for (itMeans = areas_mean.begin(); itMeans != areas_mean.end();
292  itMeans++)
293  {
294  opengl::CSphere::Ptr sphere =
295  mrpt::make_aligned_shared<opengl::CSphere>();
296 
297  if (itMeans->first ==
298  m_nodeIDmemberships.find(m_currentRobotPose)->second)
299  { // Color of current area
300  sphere->setColor(0.1, 0.1, 0.7);
301  }
302  else
303  { // Color of other areas
304  sphere->setColor(0.7, 0, 0);
305  }
306 
307  sphere->setLocation(
308  itMeans->second.x(), itMeans->second.y(),
309  itMeans->second.z() +
310  m_parent->m_options.VIEW3D_AREA_SPHERES_HEIGHT);
311 
312  sphere->setRadius(m_parent->m_options.VIEW3D_AREA_SPHERES_RADIUS);
313 
314  // Add it:
315  objs->insert(sphere);
316 
317  // And text label:
318  opengl::CText::Ptr txt = mrpt::make_aligned_shared<opengl::CText>();
319  txt->setColor(1, 1, 1);
320 
321  const CHMHMapNode::Ptr node =
322  m_parent->m_map.getNodeByID(itMeans->first);
323  ASSERT_(node);
324 
325  txt->setLocation(
326  itMeans->second.x(), itMeans->second.y(),
327  itMeans->second.z() +
328  m_parent->m_options.VIEW3D_AREA_SPHERES_HEIGHT);
329 
330  // txt->m_str = node->m_label;
331  txt->setString(format("%li", (long int)node->getID()));
332 
333  objs->insert(txt);
334  }
335  } // end of lock on map_cs
336 
337  // ---------------------------------------------------------
338  // Draw links between areas:
339  // ---------------------------------------------------------
340  {
341  std::lock_guard<std::mutex> lock(m_parent->m_map_cs);
342 
343  for (itMeans = areas_mean.begin(); itMeans != areas_mean.end();
344  itMeans++)
345  {
346  CHMHMapNode::TNodeID srcAreaID = itMeans->first;
347  const CHMHMapNode::Ptr srcArea =
348  m_parent->m_map.getNodeByID(srcAreaID);
349  ASSERT_(srcArea);
350 
351  TArcList lstArcs;
352  srcArea->getArcs(lstArcs);
353  for (TArcList::const_iterator a = lstArcs.begin();
354  a != lstArcs.end(); ++a)
355  {
356  // target is in the neighborhood of LMH:
357  if ((*a)->getNodeFrom() == srcAreaID)
358  {
360  trgAreaPoseIt = areas_mean.find((*a)->getNodeTo());
361  if (trgAreaPoseIt != areas_mean.end())
362  {
363  // Yes, target node of the arc is in the LMH: Draw it:
365  mrpt::make_aligned_shared<opengl::CSimpleLine>();
366  line->setColor(0.8, 0.8, 0);
367  line->setLineWidth(3);
368 
369  line->setLineCoords(
370  areas_mean[srcAreaID].x(),
371  areas_mean[srcAreaID].y(),
372  areas_mean[srcAreaID].z() +
373  m_parent->m_options.VIEW3D_AREA_SPHERES_HEIGHT,
374  trgAreaPoseIt->second.x(),
375  trgAreaPoseIt->second.y(),
376  trgAreaPoseIt->second.z() +
377  m_parent->m_options.VIEW3D_AREA_SPHERES_HEIGHT);
378 
379  objs->insert(line);
380  }
381  }
382  } // end for each arc
383  } // end for each area
384 
385  } // end of lock on map_cs
386 }
387 
388 /*---------------------------------------------------------------
389  getMeans
390  Returns the mean of each robot pose in this LMH, as
391  computed from the set of particles.
392  ---------------------------------------------------------------*/
393 void CLocalMetricHypothesis::getMeans(TMapPoseID2Pose3D& outList) const
394 {
395  MRPT_START
396 
397  outList.clear();
398 
399  // Build list of particles pdfs:
400  std::map<TPoseID, CPose3DPDFParticles> parts;
401  getPathParticles(parts);
402 
404 
405  for (it = parts.begin(); it != parts.end(); it++)
406  it->second.getMean(outList[it->first]);
407 
408  MRPT_END
409 }
410 
411 /*---------------------------------------------------------------
412  getPathParticles
413  ---------------------------------------------------------------*/
414 void CLocalMetricHypothesis::getPathParticles(
415  std::map<TPoseID, CPose3DPDFParticles>& outList) const
416 {
417  MRPT_START
418 
419  outList.clear();
420 
421  if (m_poseParticles.m_particles.empty()) return;
422 
423  // For each poseID:
424  for (TMapPoseID2Pose3D::const_iterator itPoseID =
425  m_poseParticles.m_particles.begin()->d->robotPoses.begin();
426  itPoseID != m_poseParticles.m_particles.begin()->d->robotPoses.end(); ++itPoseID)
427  {
428  CPose3DPDFParticles auxPDF(m_poseParticles.m_particles.size());
431  for (it = m_poseParticles.m_particles.begin(), itP = auxPDF.m_particles.begin();
432  it != m_poseParticles.m_particles.end(); it++, itP++)
433  {
434  itP->log_w = it->log_w;
435  *itP->d = it->d->robotPoses.find(itPoseID->first)->second;
436  }
437 
438  // Save PDF:
439  outList[itPoseID->first] = auxPDF;
440  } // end for itPoseID
441 
442  MRPT_END
443 }
444 
445 /*---------------------------------------------------------------
446  getPoseParticles
447  ---------------------------------------------------------------*/
448 void CLocalMetricHypothesis::getPoseParticles(
449  const TPoseID& poseID, CPose3DPDFParticles& outPDF) const
450 {
451  MRPT_START
452 
453  ASSERT_(!m_poseParticles.m_particles.empty());
454 
456  outPDF.resetDeterministic(CPose3D(), m_poseParticles.m_particles.size());
458  for (it = m_poseParticles.m_particles.begin(), itP = outPDF.m_particles.begin();
459  it != m_poseParticles.m_particles.end(); it++, itP++)
460  {
461  itP->log_w = it->log_w;
463  it->d->robotPoses.find(poseID);
464  ASSERT_(itPose != it->d->robotPoses.end());
465  *itP->d = itPose->second;
466  }
467 
468  MRPT_END
469 }
470 
471 /*---------------------------------------------------------------
472  clearRobotPoses
473  ---------------------------------------------------------------*/
474 void CLocalMetricHypothesis::clearRobotPoses()
475 {
476  m_poseParticles.clearParticles();
477  m_poseParticles.m_particles.resize(m_parent->m_options.pf_options.sampleSize);
478  for (CParticleList::iterator it = m_poseParticles.m_particles.begin();
479  it != m_poseParticles.m_particles.end(); ++it)
480  {
481  // Create particle:
482  it->log_w = 0;
483  it->d.reset(
484  new CLSLAMParticleData(
485  &m_parent->m_options.defaultMapsInitializers));
486 
487  // Fill in:
488  it->d->robotPoses.clear();
489  }
490 }
491 
492 /*---------------------------------------------------------------
493  getCurrentPose
494  ---------------------------------------------------------------*/
495 const CPose3D* CLocalMetricHypothesis::getCurrentPose(
496  const size_t& particleIdx) const
497 {
498  if (particleIdx >= m_poseParticles.m_particles.size())
499  THROW_EXCEPTION("Particle index out of bounds!");
500 
502  m_poseParticles.m_particles[particleIdx].d->robotPoses.find(m_currentRobotPose);
503  ASSERT_(it != m_poseParticles.m_particles[particleIdx].d->robotPoses.end());
504  return &it->second;
505 }
506 
507 /*---------------------------------------------------------------
508  getCurrentPose
509  ---------------------------------------------------------------*/
510 CPose3D* CLocalMetricHypothesis::getCurrentPose(const size_t& particleIdx)
511 {
512  if (particleIdx >= m_poseParticles.m_particles.size())
513  THROW_EXCEPTION("Particle index out of bounds!");
514 
516  m_poseParticles.m_particles[particleIdx].d->robotPoses.find(m_currentRobotPose);
517  ASSERT_(it != m_poseParticles.m_particles[particleIdx].d->robotPoses.end());
518  return &it->second;
519 }
520 
521 /*---------------------------------------------------------------
522  getRelativePose
523  ---------------------------------------------------------------*/
524 void CLocalMetricHypothesis::getRelativePose(
525  const TPoseID& reference, const TPoseID& pose,
526  CPose3DPDFParticles& outPDF) const
527 {
528  MRPT_START
529 
530  // Resize output:
531  outPDF.resetDeterministic(CPose3D(), m_poseParticles.m_particles.size());
532 
535  for (it = m_poseParticles.m_particles.begin(), itP = outPDF.m_particles.begin();
536  it != m_poseParticles.m_particles.end(); it++, itP++)
537  {
538  itP->log_w = it->log_w;
539 
541  it->d->robotPoses.find(reference);
543  it->d->robotPoses.find(pose);
544 
545  ASSERT_(srcPose != it->d->robotPoses.end())
546  ASSERT_(trgPose != it->d->robotPoses.end())
547 
548  *itP->d = trgPose->second - srcPose->second;
549  }
550 
551  MRPT_END
552 }
553 
554 /*---------------------------------------------------------------
555  changeCoordinateOrigin
556  ---------------------------------------------------------------*/
557 void CLocalMetricHypothesis::changeCoordinateOrigin(const TPoseID& newOrigin)
558 {
559  CPose3DPDFParticles originPDF(m_poseParticles.m_particles.size());
560 
563 
564  for (it = m_poseParticles.m_particles.begin(), itOrgPDF = originPDF.m_particles.begin();
565  it != m_poseParticles.m_particles.end(); it++, itOrgPDF++)
566  {
567  TMapPoseID2Pose3D::iterator refPoseIt =
568  it->d->robotPoses.find(newOrigin);
569  ASSERT_(refPoseIt != it->d->robotPoses.end())
570  const CPose3D& refPose = refPoseIt->second;
571 
572  // Save in pdf to compute mean:
573  *itOrgPDF->d = refPose;
574  itOrgPDF->log_w = it->log_w;
575 
576  TMapPoseID2Pose3D::iterator End = it->d->robotPoses.end();
577  // Change all other poses first:
578  for (TMapPoseID2Pose3D::iterator itP = it->d->robotPoses.begin();
579  itP != End; ++itP)
580  if (itP != refPoseIt) itP->second = itP->second - refPose;
581 
582  // Now set new origin to 0:
583  refPoseIt->second.setFromValues(0, 0, 0);
584  }
585 
586  // Rebuild metric maps for consistency:
587  rebuildMetricMaps();
588 
589  // Change coords in incr. partitioning as well:
590  {
591  std::lock_guard<std::mutex> locker(m_robotPosesGraph.lock);
592 
593  CSimpleMap* SFseq = m_robotPosesGraph.partitioner.getSequenceOfFrames();
595  m_robotPosesGraph.idx2pose.begin();
596  it != m_robotPosesGraph.idx2pose.end(); ++it)
597  {
598  CPose3DPDF::Ptr pdf;
600  SFseq->get(it->first, pdf, sf);
601 
602  // Copy from particles:
603  ASSERT_(pdf->GetRuntimeClass() == CLASS_ID(CPose3DPDFParticles));
604  CPose3DPDFParticles::Ptr pdfParts =
605  std::dynamic_pointer_cast<CPose3DPDFParticles>(pdf);
606  getPoseParticles(it->second, *pdfParts);
607  }
608  }
609 }
610 
611 /*---------------------------------------------------------------
612  rebuildMetricMaps
613  ---------------------------------------------------------------*/
614 void CLocalMetricHypothesis::rebuildMetricMaps()
615 {
616  for (CParticleList::iterator it = m_poseParticles.m_particles.begin();
617  it != m_poseParticles.m_particles.end(); ++it)
618  {
619  it->d->metricMaps.clear();
620 
621  // Follow all robot poses:
622  TMapPoseID2Pose3D::iterator End = it->d->robotPoses.end();
623  for (TMapPoseID2Pose3D::iterator itP = it->d->robotPoses.begin();
624  itP != End; ++itP)
625  {
626  if (itP->first !=
627  m_currentRobotPose) // Current robot pose has no SF stored.
628  {
630  m_SFs.find(itP->first);
631  ASSERT_(SFit != m_SFs.end());
632  SFit->second.insertObservationsInto(
633  &it->d->metricMaps, &itP->second);
634  }
635  }
636  }
637 }
638 
639 /** Removes a given area from the LMH:
640  * - The corresponding node in the HMT map is updated with the robot poses &
641  *SFs in the LMH.
642  * - Robot poses belonging to that area are removed from:
643  * - the particles.
644  * - the graph partitioner.
645  * - the list of SFs.
646  * - the list m_nodeIDmemberships.
647  * - The weights of all particles are changed to remove the effects of the
648  *removed metric observations.
649  * - After calling this the metric maps should be updated.
650  */
651 void CLocalMetricHypothesis::removeAreaFromLMH(
652  const CHMHMapNode::TNodeID areaID)
653 {
654  MRPT_START
655 
656  // Remove from m_neighbors:
657  // -----------------------------------
658  TNodeIDSet::iterator itNeig = m_neighbors.find(areaID);
659  if (itNeig != m_neighbors.end()) m_neighbors.erase(itNeig);
660 
661  // Build the list with the poses in the area to be removed from LMH:
662  // ----------------------------------------------------------------------
663  TNodeIDList lstPoseIDs;
665  m_nodeIDmemberships.begin();
666  it != m_nodeIDmemberships.end(); ++it)
667  if (it->second == areaID) lstPoseIDs.insert(it->first);
668 
669  ASSERT_(!lstPoseIDs.empty());
670 
671  // ----------------------------------------------------------------------
672  // The corresponding node in the HMT map is updated with the
673  // robot poses & SFs in the LMH.
674  // ----------------------------------------------------------------------
675  updateAreaFromLMH(areaID, true);
676 
677  // - Robot poses belonging to that area are removed from:
678  // - the particles.
679  // ----------------------------------------------------------------------
680  for (TNodeIDList::const_iterator it = lstPoseIDs.begin();
681  it != lstPoseIDs.end(); ++it)
682  for (CParticleList::iterator p = m_poseParticles.m_particles.begin();
683  p != m_poseParticles.m_particles.end(); ++p)
684  p->d->robotPoses.erase(p->d->robotPoses.find(*it));
685 
686  // - The weights of all particles are changed to remove the effects of the
687  // removed metric observations.
688  // ----------------------------------------------------------------------
689  {
691  vector<map<TPoseID, double>>::iterator ws_it;
692  ASSERT_(m_log_w_metric_history.size() == m_poseParticles.m_particles.size());
693 
694  for (ws_it = m_log_w_metric_history.begin(), p = m_poseParticles.m_particles.begin();
695  p != m_poseParticles.m_particles.end(); ++p, ++ws_it)
696  {
697  for (TNodeIDList::const_iterator it = lstPoseIDs.begin();
698  it != lstPoseIDs.end(); ++it)
699  {
700  map<TPoseID, double>::iterator itW = ws_it->find(*it);
701  if (itW != ws_it->end())
702  {
703  MRPT_CHECK_NORMAL_NUMBER(itW->second);
704 
705  p->log_w -= itW->second;
706  // No longer required:
707  ws_it->erase(itW);
708  }
709  }
710  }
711  }
712 
713  // - Robot poses belonging to that area are removed from:
714  // - the graph partitioner.
715  // ----------------------------------------------------------------------
716  {
717  std::lock_guard<std::mutex> locker(m_robotPosesGraph.lock);
718 
719  vector_uint indexesToRemove;
720  indexesToRemove.reserve(lstPoseIDs.size());
721 
723  m_robotPosesGraph.idx2pose.begin();
724  it != m_robotPosesGraph.idx2pose.end();)
725  {
726  if (lstPoseIDs.find(it->second) != lstPoseIDs.end())
727  {
728  indexesToRemove.push_back(it->first);
729 
730  // Remove from the mapping indexes->nodeIDs as well:
732  it2++;
733  // it = m_robotPosesGraph.idx2pose.erase( it );
734  m_robotPosesGraph.idx2pose.erase(it);
735  it = it2;
736  }
737  else
738  it++;
739  }
740 
741  m_robotPosesGraph.partitioner.removeSetOfNodes(indexesToRemove);
742 
743  // Renumbering of indexes<->posesIDs to be the same than in
744  // "m_robotPosesGraph.partitioner":
745  unsigned idx = 0;
746  map<uint32_t, TPoseID> newList;
748  i = m_robotPosesGraph.idx2pose.begin();
749  i != m_robotPosesGraph.idx2pose.end(); ++i, idx++)
750  newList[idx] = i->second;
751  m_robotPosesGraph.idx2pose = newList;
752  }
753 
754  // - Robot poses belonging to that area are removed from:
755  // - the list of SFs.
756  // ----------------------------------------------------------------------
757  // Already done above.
758 
759  // - Robot poses belonging to that area are removed from:
760  // - the list m_nodeIDmemberships.
761  // ----------------------------------------------------------------------
762  for (TNodeIDList::const_iterator it = lstPoseIDs.begin();
763  it != lstPoseIDs.end(); ++it)
764  m_nodeIDmemberships.erase(m_nodeIDmemberships.find(*it));
765 
766  double out_max_log_w;
767  m_poseParticles.normalizeWeights(&out_max_log_w); // Normalize weights:
768 
769  MRPT_END
770 }
771 
772 /*---------------------------------------------------------------
773  TRobotPosesPartitioning::pose2idx
774  ---------------------------------------------------------------*/
775 unsigned int CLocalMetricHypothesis::TRobotPosesPartitioning::pose2idx(
776  const TPoseID& id) const
777 {
778  for (std::map<uint32_t, TPoseID>::const_iterator it = idx2pose.begin();
779  it != idx2pose.end(); ++it)
780  if (it->second == id) return it->first;
781  THROW_EXCEPTION_FMT("PoseID=%i not found.", static_cast<int>(id));
782 }
783 
784 /*---------------------------------------------------------------
785  updateAreaFromLMH
786 
787 // The corresponding node in the HMT map is updated with the
788 // robot poses & SFs in the LMH.
789  ---------------------------------------------------------------*/
790 void CLocalMetricHypothesis::updateAreaFromLMH(
791  const CHMHMapNode::TNodeID areaID, bool eraseSFsFromLMH)
792 {
793  // Build the list with the poses belonging to that area from LMH:
794  // ----------------------------------------------------------------------
795  TNodeIDList lstPoseIDs;
797  m_nodeIDmemberships.begin();
798  it != m_nodeIDmemberships.end(); ++it)
799  if (it->second == areaID) lstPoseIDs.insert(it->first);
800 
801  ASSERT_(!lstPoseIDs.empty());
802 
803  CHMHMapNode::Ptr node;
804  {
805  std::lock_guard<std::mutex>(m_parent->m_map_cs);
806  node = m_parent->m_map.getNodeByID(areaID);
807  ASSERT_(node);
808  ASSERT_(node->m_hypotheses.has(m_ID));
809  } // end of HMT map cs
810 
811  // The pose to become the origin:
812  TPoseID poseID_origin;
813  node->m_annotations.getElemental(
814  NODE_ANNOTATION_REF_POSEID, poseID_origin, m_ID, true);
815 
816  // 1) The set of robot poses and SFs
817  // In annotation: NODE_ANNOTATION_POSES_GRAPH
818  // ---------------------------------------------------------------------
819  CRobotPosesGraph::Ptr posesGraph;
820  {
821  CSerializable::Ptr annot =
822  node->m_annotations.get(NODE_ANNOTATION_POSES_GRAPH, m_ID);
823  if (!annot)
824  {
825  // Add it now:
826  posesGraph = mrpt::make_aligned_shared<CRobotPosesGraph>();
827  node->m_annotations.setMemoryReference(
828  NODE_ANNOTATION_POSES_GRAPH, posesGraph, m_ID);
829  }
830  else
831  {
832  posesGraph = std::dynamic_pointer_cast<CRobotPosesGraph>(annot);
833  posesGraph->clear();
834  }
835  }
836 
837  // For each pose in the area:
838  CPose3DPDFParticles pdfOrigin;
839  bool pdfOrigin_ok = false;
840  for (TNodeIDList::const_iterator it = lstPoseIDs.begin();
841  it != lstPoseIDs.end(); ++it)
842  {
843  TPoseInfo& poseInfo = (*posesGraph)[*it];
844  getPoseParticles(*it, poseInfo.pdf); // Save pose particles
845 
846  // Save the PDF of the origin:
847  if (*it == poseID_origin)
848  {
849  pdfOrigin.copyFrom(poseInfo.pdf);
850  pdfOrigin_ok = true;
851  }
852 
853  if (*it != m_currentRobotPose) // The current robot pose has no SF
854  {
855  std::map<TPoseID, CSensoryFrame>::iterator itSF = m_SFs.find(*it);
856  ASSERT_(itSF != m_SFs.end());
857 
858  if (eraseSFsFromLMH)
859  {
860  poseInfo.sf.moveFrom(itSF->second); // This leaves m_SFs[*it]
861  // without observations,
862  // but it is being erased
863  // just now:
864  m_SFs.erase(itSF);
865  }
866  else
867  {
868  poseInfo.sf = itSF->second; // Copy observations
869  }
870  }
871  }
872 
873  // Readjust to set the origin pose ID:
874  ASSERT_(pdfOrigin_ok);
875  CPose3DPDFParticles pdfOriginInv;
876  pdfOrigin.inverse(pdfOriginInv);
877  for (CRobotPosesGraph::iterator it = posesGraph->begin();
878  it != posesGraph->end(); ++it)
879  {
881  ASSERT_(it->second.pdf.size() == pdfOriginInv.size());
882  for (pdfIt = it->second.pdf.m_particles.begin(),
883  orgIt = pdfOriginInv.m_particles.begin();
884  orgIt != pdfOriginInv.m_particles.end(); orgIt++, pdfIt++)
885  *pdfIt->d = *orgIt->d + *pdfIt->d;
886  }
887 
888  // 2) One single metric map built from the most likelily robot poses
889  // In annotation: NODE_ANNOTATION_METRIC_MAPS
890  // ---------------------------------------------------------------------
891  CMultiMetricMap::Ptr metricMap = node->m_annotations.getAs<CMultiMetricMap>(
892  NODE_ANNOTATION_METRIC_MAPS, m_ID, false);
893  metricMap->clear();
894  posesGraph->insertIntoMetricMap(*metricMap);
895 }
896 
897 /*---------------------------------------------------------------
898  dumpAsText
899  ---------------------------------------------------------------*/
900 void CLocalMetricHypothesis::dumpAsText(utils::CStringList& st) const
901 {
902  st.clear();
903  st << "LIST OF POSES IN LMH";
904  st << "====================";
905 
906  string s;
907  s = "Neighbors: ";
908  for (TNodeIDSet::const_iterator it = m_neighbors.begin();
909  it != m_neighbors.end(); ++it)
910  s += format("%i ", (int)*it);
911  st << s;
912 
913  TMapPoseID2Pose3D lst;
914  getMeans(lst);
915 
916  for (TMapPoseID2Pose3D::const_iterator it = lst.begin(); it != lst.end();
917  ++it)
918  {
920  m_nodeIDmemberships.find(it->first);
921 
922  string s = format(
923  " ID: %i \t AREA: %i \t %.03f,%.03f,%.03fdeg", (int)it->first,
924  (int)area->second, it->second.x(), it->second.y(),
925  RAD2DEG(it->second.yaw()));
926  st << s;
927  }
928 }
929 
930 /*---------------------------------------------------------------
931  readFromStream
932  ---------------------------------------------------------------*/
933 void CLocalMetricHypothesis::readFromStream(
934  mrpt::utils::CStream& in, int version)
935 {
936  switch (version)
937  {
938  case 0:
939  {
940  in >> m_ID >> m_currentRobotPose >> m_neighbors >>
941  m_nodeIDmemberships >> m_SFs >> m_posesPendingAddPartitioner >>
942  m_areasPendingTBI >> m_log_w >> m_log_w_metric_history >>
943  m_robotPosesGraph.partitioner >> m_robotPosesGraph.idx2pose;
944 
945  // particles:
946  m_poseParticles.readParticlesFromStream(in);
947  }
948  break;
949  default:
951  };
952 }
953 
954 /*---------------------------------------------------------------
955  writeToStream
956  Implements the writing to a CStream capability of
957  CSerializable objects
958  ---------------------------------------------------------------*/
959 void CLocalMetricHypothesis::writeToStream(
960  mrpt::utils::CStream& out, int* version) const
961 {
962  if (version)
963  *version = 0;
964  else
965  {
966  out << m_ID << m_currentRobotPose << m_neighbors << m_nodeIDmemberships
967  << m_SFs << m_posesPendingAddPartitioner << m_areasPendingTBI
968  << m_log_w << m_log_w_metric_history
969  << m_robotPosesGraph.partitioner << m_robotPosesGraph.idx2pose;
970 
971  // particles:
972  m_poseParticles.writeParticlesToStream(out);
973  }
974 }
975 
976 /*---------------------------------------------------------------
977  readFromStream
978  ---------------------------------------------------------------*/
979 void CLSLAMParticleData::readFromStream(mrpt::utils::CStream& in, int version)
980 {
981  switch (version)
982  {
983  case 0:
984  {
985  in >> metricMaps >> robotPoses;
986  }
987  break;
988  default:
990  };
991 }
992 
993 /*---------------------------------------------------------------
994  writeToStream
995  Implements the writing to a CStream capability of
996  CSerializable objects
997  ---------------------------------------------------------------*/
998 void CLSLAMParticleData::writeToStream(
999  mrpt::utils::CStream& out, int* version) const
1000 {
1001  if (version)
1002  *version = 0;
1003  else
1004  {
1005  out << metricMaps << robotPoses;
1006  }
1007 }
void clear()
Erase all the contents of the map.
Definition: CMetricMap.cpp:31
std::shared_ptr< CRobotPosesGraph > Ptr
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
CPose3D mean
The mean value.
GLdouble GLdouble z
Definition: glext.h:3872
std::vector< uint32_t > vector_uint
Definition: types_simple.h:29
void copyFrom(const CPose3DPDF &o) override
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
This class stores a sequence of <Probabilistic Pose,SensoryFrame> pairs, thus a "metric map" can be t...
Definition: CSimpleMap.h:35
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.
std::shared_ptr< CCamera > Ptr
Definition: CCamera.h:34
void moveFrom(CSensoryFrame &sf)
Copies all the observation from another object, then erase them from the origin object (this method i...
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
#define MRPT_CHECK_NORMAL_NUMBER(val)
#define THROW_EXCEPTION(msg)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
GLenum GLsizei n
Definition: glext.h:5074
mrpt::poses::CPose3DPDFParticles pdf
The robot pose PDF.
Scalar * iterator
Definition: eigen_plugins.h:26
double pitch() const
Get the PITCH angle (in radians)
Definition: CPose3D.h:539
double yaw() const
Get the YAW angle (in radians)
Definition: CPose3D.h:533
std::shared_ptr< CPose3DPDFParticles > Ptr
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:27
uint64_t TPoseID
An integer number uniquely identifying each robot pose stored in HMT-SLAM.
GLdouble s
Definition: glext.h:3676
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
An implementation of Hybrid Metric Topological SLAM (HMT-SLAM).
Definition: CHMTSLAM.h:65
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
A class for storing a list of text lines.
Definition: CStringList.h:32
CParticleList m_particles
The array of particles.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
mrpt::aligned_containers< TPoseID, mrpt::poses::CPose3D >::map_t TMapPoseID2Pose3D
#define CLASS_ID(T)
Access to runtime class ID for a defined class name.
Definition: CObject.h:85
static Ptr Create(Args &&... args)
Definition: CArrow.h:33
#define MRPT_END
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
CMatrixTemplateNumeric< double > CMatrixDouble
Declares a matrix of double numbers (non serializable).
void clear()
Clear the whole list.
Definition: CStringList.cpp:73
std::shared_ptr< CPose3DPDF > Ptr
Definition: CPose3DPDF.h:45
std::shared_ptr< CSetOfObjects > Ptr
Definition: CSetOfObjects.h:32
This namespace contains representation of robot actions and observations.
std::shared_ptr< CMultiMetricMap > Ptr
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
std::shared_ptr< CSensoryFrame > Ptr
Definition: CSensoryFrame.h:56
size_t size() const
Get the m_particles count (equivalent to "particlesCount")
Auxiliary class used in mrpt::slam::CLocalMetricHypothesis for HMT-SLAM; this class stores a set of r...
void get(size_t index, mrpt::poses::CPose3DPDF::Ptr &out_posePDF, mrpt::obs::CSensoryFrame::Ptr &out_SF) const
Access to the i&#39;th pair, first one is index &#39;0&#39;.
Definition: CSimpleMap.cpp:78
This class is used in HMT-SLAM to represent each of the Local Metric Hypotheses (LMHs).
#define NODE_ANNOTATION_METRIC_MAPS
A class used to store a 3D point.
Definition: CPoint3D.h:32
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
double roll() const
Get the ROLL angle (in radians)
Definition: CPose3D.h:545
CSetOfObjects::Ptr RobotPioneer()
Returns a representation of a Pioneer II mobile base.
Auxiliary class used in mrpt::slam::CLocalMetricHypothesis for HMT-SLAM; this class keeps the data re...
std::shared_ptr< CSerializable > Ptr
Definition: CSerializable.h:47
void copyFrom(const CPose3DPDF &o) override
Copy operator, translating if necesary (for example, between m_particles and gaussian representations...
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
#define MRPT_START
#define RAD2DEG
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
void resetDeterministic(const CPose3D &location, size_t particlesCount=0)
Reset the PDF to a single point: All m_particles will be set exactly to the supplied pose...
CSetOfObjects::Ptr CornerXYZ(float scale=1.0)
Returns three arrows representing a X,Y,Z 3D corner.
mrpt::obs::CSensoryFrame sf
The observations.
GLuint in
Definition: glext.h:7274
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
#define ASSERT_(f)
#define NODE_ANNOTATION_REF_POSEID
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
Information kept for each robot pose used in CRobotPosesGraph.
GLenum GLint GLint y
Definition: glext.h:3538
std::shared_ptr< CHMHMapNode > Ptr
Definition: CHMHMapNode.h:42
void inverse(CPose3DPDF &o) const override
Returns a new PDF such as: NEW_PDF = (0,0,0) - THIS_PDF.
std::shared_ptr< CText > Ptr
Definition: CText.h:40
GLenum GLint x
Definition: glext.h:3538
This class stores any customizable set of metric maps.
#define NODE_ANNOTATION_POSES_GRAPH
std::list< T >::iterator find(const T &i)
std::shared_ptr< CSimpleLine > Ptr
Definition: CSimpleLine.h:24
std::shared_ptr< CSphere > Ptr
Definition: CSphere.h:33
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLfloat GLfloat p
Definition: glext.h:6305
A class for storing a sequence of arcs (a path).
std::shared_ptr< CGridPlaneXY > Ptr
Definition: CGridPlaneXY.h:34
Declares a class that represents a Probability Density function (PDF) of a 3D pose.
mrpt::utils::TNodeID TNodeID
The type of the IDs of nodes.
Definition: CHMHMapNode.h:47
std::shared_ptr< CEllipsoid > Ptr
Definition: CEllipsoid.h:49
static size_type size()
Definition: CPose3D.h:766
std::shared_ptr< CArrow > Ptr
Definition: CArrow.h:33



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