Mapper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2010 SRI International
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <sstream>
19 #include <fstream>
20 #include <stdexcept>
21 #include <queue>
22 #include <set>
23 #include <list>
24 #include <iterator>
25 #include <karto_sdk/Types.h>
26 #include <math.h>
27 #include <assert.h>
28 #include <boost/serialization/vector.hpp>
29 
30 #include "karto_sdk/Mapper.h"
31 
40 namespace karto
41 {
42 
43  // enable this for verbose debug information
44  // #define KARTO_DEBUG
45 
46  #define MAX_VARIANCE 500.0
47  #define DISTANCE_PENALTY_GAIN 0.2
48  #define ANGLE_PENALTY_GAIN 0.2
49 
53 
58  {
59  public:
63  ScanManager(kt_int32u runningBufferMaximumSize, kt_double runningBufferMaximumDistance)
64  : m_pLastScan(NULL)
65  , m_RunningBufferMaximumSize(runningBufferMaximumSize)
66  , m_RunningBufferMaximumDistance(runningBufferMaximumDistance)
67  , m_NextStateId(0)
68  {
69  }
70 
72 
76  virtual ~ScanManager()
77  {
78  Clear();
79  }
80 
81  public:
86  inline void AddScan(LocalizedRangeScan* pScan, kt_int32s uniqueId)
87  {
88  // assign state id to scan
89  pScan->SetStateId(m_NextStateId);
90 
91  // assign unique id to scan
92  pScan->SetUniqueId(uniqueId);
93 
94  // add it to scan buffer
95  m_Scans.insert({pScan->GetStateId(), pScan});
96  m_NextStateId++;
97  }
98 
105  {
106  return m_pLastScan;
107  }
108 
113  inline void ClearLastScan()
114  {
115  m_pLastScan = NULL;
116  }
117 
123  {
124  m_pLastScan = pScan;
125  }
126 
132  {
133  return m_Scans;
134  }
135 
141  {
142  return m_RunningScans;
143  }
144 
150  {
152  }
153 
158  void SetRunningScanBufferSize(const kt_int32u & rScanBufferSize)
159  {
160  m_RunningBufferMaximumSize = rScanBufferSize;
161  }
162 
167  void SetRunningScanBufferMaximumDistance(const kt_int32u & rScanBufferMaxDistance)
168  {
169  m_RunningBufferMaximumDistance = rScanBufferMaxDistance;
170  }
171 
177  {
178  m_RunningScans.push_back(pScan);
179 
180  // vector has at least one element (first line of this function), so this is valid
181  Pose2 frontScanPose = m_RunningScans.front()->GetSensorPose();
182  Pose2 backScanPose = m_RunningScans.back()->GetSensorPose();
183 
184  // cap vector size and remove all scans from front of vector that are too far from end of vector
185  kt_double squaredDistance = frontScanPose.GetPosition().SquaredDistance(backScanPose.GetPosition());
186  while (m_RunningScans.size() > m_RunningBufferMaximumSize ||
188  {
189  // remove front of running scans
190  m_RunningScans.erase(m_RunningScans.begin());
191 
192  // recompute stats of running scans
193  frontScanPose = m_RunningScans.front()->GetSensorPose();
194  backScanPose = m_RunningScans.back()->GetSensorPose();
195  squaredDistance = frontScanPose.GetPosition().SquaredDistance(backScanPose.GetPosition());
196  }
197  }
198 
204  {
205  LocalizedRangeScanMap::iterator it = m_Scans.find(pScan->GetStateId());
206  if (it != m_Scans.end())
207  {
208  it->second = NULL;
209  m_Scans.erase(it);
210  }
211  else
212  {
213  std::cout << "Remove Scan: Failed to find scan in m_Scans" << std::endl;
214  }
215  }
216 
221  {
222  m_RunningScans.clear();
223  }
224 
228  void Clear()
229  {
230  m_Scans.clear();
231  m_RunningScans.clear();
232  }
233 
234  private:
236  template<class Archive>
237  void serialize(Archive &ar, const unsigned int version)
238  {
239  ar & BOOST_SERIALIZATION_NVP(m_Scans);
240  ar & BOOST_SERIALIZATION_NVP(m_RunningScans);
241  ar & BOOST_SERIALIZATION_NVP(m_pLastScan);
242  ar & BOOST_SERIALIZATION_NVP(m_RunningBufferMaximumSize);
243  ar & BOOST_SERIALIZATION_NVP(m_RunningBufferMaximumDistance);
244  ar & BOOST_SERIALIZATION_NVP(m_NextStateId);
245  }
246 
247  private:
252 
255  }; // ScanManager
256 
260 
261  void MapperSensorManager::RegisterSensor(const Name& rSensorName)
262  {
263  if (GetScanManager(rSensorName) == NULL)
264  {
265  m_ScanManagers[rSensorName] = new ScanManager(m_RunningBufferMaximumSize, m_RunningBufferMaximumDistance);
266  }
267  }
268 
269 
277  {
278  ScanManager* pScanManager = GetScanManager(rSensorName);
279  if (pScanManager != NULL)
280  {
281  LocalizedRangeScanMap::iterator it = pScanManager->GetScans().find(scanIndex);
282  if (it != pScanManager->GetScans().end())
283  {
284  return it->second;
285  }
286  else
287  {
288  return nullptr;
289  }
290  }
291 
292  assert(false);
293  return NULL;
294  }
295 
302  {
303  RegisterSensor(rSensorName);
304 
305  return GetScanManager(rSensorName)->GetLastScan();
306  }
307 
313  {
314  GetScanManager(pScan)->SetLastScan(pScan);
315  }
316 
322  {
323  GetScanManager(pScan)->ClearLastScan();
324  }
325 
331  {
332  GetScanManager(name)->ClearLastScan();
333  }
334 
340  {
341  GetScanManager(pScan)->AddScan(pScan, m_NextScanId);
342  m_Scans.insert({m_NextScanId, pScan});
343  m_NextScanId++;
344  }
345 
351  {
352  GetScanManager(pScan)->AddRunningScan(pScan);
353  }
354 
360  {
361  GetScanManager(pScan)->RemoveScan(pScan);
362 
363  LocalizedRangeScanMap::iterator it = m_Scans.find(pScan->GetUniqueId());
364  if (it != m_Scans.end())
365  {
366  it->second = NULL;
367  m_Scans.erase(it);
368  }
369  else
370  {
371  std::cout << "RemoveScan: Failed to find scan in m_Scans" << std::endl;
372  }
373  }
374 
381  {
382  return GetScanManager(rSensorName)->GetScans();
383  }
384 
391  {
392  return GetScanManager(rSensorName)->GetRunningScans();
393  }
394 
396  {
397  GetScanManager(rSensorName)->ClearRunningScans();
398  return;
399  }
400 
402  {
403  return GetScanManager(rSensorName)->GetRunningScanBufferSize();
404  }
405 
407  {
408  m_RunningBufferMaximumSize = rScanBufferSize;
409 
410  std::vector<Name> names = GetSensorNames();
411  for (uint i = 0; i != names.size(); i++) {
412  GetScanManager(names[i])->SetRunningScanBufferSize(rScanBufferSize);
413  }
414  }
415 
417  {
418  m_RunningBufferMaximumDistance = rScanBufferMaxDistance;
419 
420  std::vector<Name> names = GetSensorNames();
421  for (uint i = 0; i != names.size(); i++) {
422  GetScanManager(names[i])->SetRunningScanBufferMaximumDistance(rScanBufferMaxDistance);
423  }
424  }
425 
431  {
433 
434  forEach(ScanManagerMap, &m_ScanManagers)
435  {
436  LocalizedRangeScanMap& rScans = iter->second->GetScans();
437 
438  LocalizedRangeScanMap::iterator it;
439  for (it = rScans.begin(); it != rScans.end(); ++it)
440  {
441  scans.push_back(it->second);
442  }
443  }
444 
445  return scans;
446  }
447 
452  {
453 // SensorManager::Clear();
454 
455  forEach(ScanManagerMap, &m_ScanManagers)
456  {
457  delete iter->second;
458  iter->second = nullptr;
459  }
460 
461  m_ScanManagers.clear();
462  }
463 
467 
469  {
470  if (m_pCorrelationGrid)
471  {
472  delete m_pCorrelationGrid;
473  }
474  if (m_pSearchSpaceProbs)
475  {
476  delete m_pSearchSpaceProbs;
477  }
478  if (m_pGridLookup)
479  {
480  delete m_pGridLookup;
481  }
482 
483  }
484 
485  ScanMatcher* ScanMatcher::Create(Mapper* pMapper, kt_double searchSize, kt_double resolution,
486  kt_double smearDeviation, kt_double rangeThreshold)
487  {
488  // invalid parameters
489  if (resolution <= 0)
490  {
491  return NULL;
492  }
493  if (searchSize <= 0)
494  {
495  return NULL;
496  }
497  if (smearDeviation < 0)
498  {
499  return NULL;
500  }
501  if (rangeThreshold <= 0)
502  {
503  return NULL;
504  }
505 
506  assert(math::DoubleEqual(math::Round(searchSize / resolution), (searchSize / resolution)));
507 
508  // calculate search space in grid coordinates
509  kt_int32u searchSpaceSideSize = static_cast<kt_int32u>(math::Round(searchSize / resolution) + 1);
510 
511  // compute requisite size of correlation grid (pad grid so that scan points can't fall off the grid
512  // if a scan is on the border of the search space)
513  kt_int32u pointReadingMargin = static_cast<kt_int32u>(ceil(rangeThreshold / resolution));
514 
515  kt_int32s gridSize = searchSpaceSideSize + 2 * pointReadingMargin;
516 
517  // create correlation grid
518  assert(gridSize % 2 == 1);
519  CorrelationGrid* pCorrelationGrid = CorrelationGrid::CreateGrid(gridSize, gridSize, resolution, smearDeviation);
520 
521  // create search space probabilities
522  Grid<kt_double>* pSearchSpaceProbs = Grid<kt_double>::CreateGrid(searchSpaceSideSize,
523  searchSpaceSideSize, resolution);
524 
525  ScanMatcher* pScanMatcher = new ScanMatcher(pMapper);
526  pScanMatcher->m_pCorrelationGrid = pCorrelationGrid;
527  pScanMatcher->m_pSearchSpaceProbs = pSearchSpaceProbs;
528  pScanMatcher->m_pGridLookup = new GridIndexLookup<kt_int8u>(pCorrelationGrid);
529 
530  return pScanMatcher;
531  }
532 
543  template<class T>
544  kt_double ScanMatcher::MatchScan(LocalizedRangeScan* pScan, const T& rBaseScans, Pose2& rMean,
545  Matrix3& rCovariance, kt_bool doPenalize, kt_bool doRefineMatch)
546  {
548  // set scan pose to be center of grid
549 
550  // 1. get scan position
551  Pose2 scanPose = pScan->GetSensorPose();
552 
553  // scan has no readings; cannot do scan matching
554  // best guess of pose is based off of adjusted odometer reading
555  if (pScan->GetNumberOfRangeReadings() == 0)
556  {
557  rMean = scanPose;
558 
559  // maximum covariance
560  rCovariance(0, 0) = MAX_VARIANCE; // XX
561  rCovariance(1, 1) = MAX_VARIANCE; // YY
562  rCovariance(2, 2) = 4 * math::Square(m_pMapper->m_pCoarseAngleResolution->GetValue()); // TH*TH
563 
564  return 0.0;
565  }
566 
567  // 2. get size of grid
568  Rectangle2<kt_int32s> roi = m_pCorrelationGrid->GetROI();
569 
570  // 3. compute offset (in meters - lower left corner)
571  Vector2<kt_double> offset;
572  offset.SetX(scanPose.GetX() - (0.5 * (roi.GetWidth() - 1) * m_pCorrelationGrid->GetResolution()));
573  offset.SetY(scanPose.GetY() - (0.5 * (roi.GetHeight() - 1) * m_pCorrelationGrid->GetResolution()));
574 
575  // 4. set offset
576  m_pCorrelationGrid->GetCoordinateConverter()->SetOffset(offset);
577 
579 
580  // set up correlation grid
581  AddScans(rBaseScans, scanPose.GetPosition());
582 
583  // compute how far to search in each direction
584  Vector2<kt_double> searchDimensions(m_pSearchSpaceProbs->GetWidth(), m_pSearchSpaceProbs->GetHeight());
585  Vector2<kt_double> coarseSearchOffset(0.5 * (searchDimensions.GetX() - 1) * m_pCorrelationGrid->GetResolution(),
586  0.5 * (searchDimensions.GetY() - 1) * m_pCorrelationGrid->GetResolution());
587 
588  // a coarse search only checks half the cells in each dimension
589  Vector2<kt_double> coarseSearchResolution(2 * m_pCorrelationGrid->GetResolution(),
590  2 * m_pCorrelationGrid->GetResolution());
591 
592  // actual scan-matching
593  kt_double bestResponse = CorrelateScan(pScan, scanPose, coarseSearchOffset, coarseSearchResolution,
594  m_pMapper->m_pCoarseSearchAngleOffset->GetValue(),
595  m_pMapper->m_pCoarseAngleResolution->GetValue(),
596  doPenalize, rMean, rCovariance, false);
597 
598  if (m_pMapper->m_pUseResponseExpansion->GetValue() == true)
599  {
600  if (math::DoubleEqual(bestResponse, 0.0))
601  {
602 #ifdef KARTO_DEBUG
603  std::cout << "Mapper Info: Expanding response search space!" << std::endl;
604 #endif
605  // try and increase search angle offset with 20 degrees and do another match
606  kt_double newSearchAngleOffset = m_pMapper->m_pCoarseSearchAngleOffset->GetValue();
607  for (kt_int32u i = 0; i < 3; i++)
608  {
609  newSearchAngleOffset += math::DegreesToRadians(20);
610 
611  bestResponse = CorrelateScan(pScan, scanPose, coarseSearchOffset, coarseSearchResolution,
612  newSearchAngleOffset, m_pMapper->m_pCoarseAngleResolution->GetValue(),
613  doPenalize, rMean, rCovariance, false);
614 
615  if (math::DoubleEqual(bestResponse, 0.0) == false)
616  {
617  break;
618  }
619  }
620 
621 #ifdef KARTO_DEBUG
622  if (math::DoubleEqual(bestResponse, 0.0))
623  {
624  std::cout << "Mapper Warning: Unable to calculate response!" << std::endl;
625  }
626 #endif
627  }
628  }
629 
630  if (doRefineMatch)
631  {
632  Vector2<kt_double> fineSearchOffset(coarseSearchResolution * 0.5);
633  Vector2<kt_double> fineSearchResolution(m_pCorrelationGrid->GetResolution(), m_pCorrelationGrid->GetResolution());
634  bestResponse = CorrelateScan(pScan, rMean, fineSearchOffset, fineSearchResolution,
635  0.5 * m_pMapper->m_pCoarseAngleResolution->GetValue(),
636  m_pMapper->m_pFineSearchAngleOffset->GetValue(),
637  doPenalize, rMean, rCovariance, true);
638  }
639 
640 #ifdef KARTO_DEBUG
641  std::cout << " BEST POSE = " << rMean << " BEST RESPONSE = " << bestResponse << ", VARIANCE = "
642  << rCovariance(0, 0) << ", " << rCovariance(1, 1) << std::endl;
643 #endif
644  assert(math::InRange(rMean.GetHeading(), -KT_PI, KT_PI));
645 
646  return bestResponse;
647  }
648 
649  void ScanMatcher::operator() (const kt_double& y) const
650  {
651  kt_int32u poseResponseCounter;
652  kt_int32u x_pose;
653  kt_int32u y_pose = std::find(m_yPoses.begin(), m_yPoses.end(), y) - m_yPoses.begin();
654 
655  const kt_int32u size_x = m_xPoses.size();
656 
657  kt_double newPositionY = m_rSearchCenter.GetY() + y;
658  kt_double squareY = math::Square(y);
659 
660  for ( std::vector<kt_double>::const_iterator xIter = m_xPoses.begin(); xIter != m_xPoses.end(); ++xIter )
661  {
662  x_pose = std::distance(m_xPoses.begin(), xIter);
663  kt_double x = *xIter;
664  kt_double newPositionX = m_rSearchCenter.GetX() + x;
665  kt_double squareX = math::Square(x);
666 
667  Vector2<kt_int32s> gridPoint = m_pCorrelationGrid->WorldToGrid(Vector2<kt_double>(newPositionX, newPositionY));
668  kt_int32s gridIndex = m_pCorrelationGrid->GridIndex(gridPoint);
669  assert(gridIndex >= 0);
670 
671  kt_double angle = 0.0;
672  kt_double startAngle = m_rSearchCenter.GetHeading() - m_searchAngleOffset;
673  for (kt_int32u angleIndex = 0; angleIndex < m_nAngles; angleIndex++)
674  {
675  angle = startAngle + angleIndex * m_searchAngleResolution;
676 
677  kt_double response = GetResponse(angleIndex, gridIndex);
678  if (m_doPenalize && (math::DoubleEqual(response, 0.0) == false))
679  {
680  // simple model (approximate Gaussian) to take odometry into account
681  kt_double squaredDistance = squareX + squareY;
682  kt_double distancePenalty = 1.0 - (DISTANCE_PENALTY_GAIN *
683  squaredDistance / m_pMapper->m_pDistanceVariancePenalty->GetValue());
684  distancePenalty = math::Maximum(distancePenalty, m_pMapper->m_pMinimumDistancePenalty->GetValue());
685 
686  kt_double squaredAngleDistance = math::Square(angle - m_rSearchCenter.GetHeading());
687  kt_double anglePenalty = 1.0 - (ANGLE_PENALTY_GAIN *
688  squaredAngleDistance / m_pMapper->m_pAngleVariancePenalty->GetValue());
689  anglePenalty = math::Maximum(anglePenalty, m_pMapper->m_pMinimumAnglePenalty->GetValue());
690 
691  response *= (distancePenalty * anglePenalty);
692  }
693 
694  // store response and pose
695  poseResponseCounter = (y_pose*size_x + x_pose)*(m_nAngles) + angleIndex;
696  m_pPoseResponse[poseResponseCounter] = std::pair<kt_double, Pose2>(response, Pose2(newPositionX, newPositionY,
697  math::NormalizeAngle(angle)));
698  }
699  }
700  return;
701  }
702 
720  const Vector2<kt_double>& rSearchSpaceOffset,
721  const Vector2<kt_double>& rSearchSpaceResolution,
722  kt_double searchAngleOffset, kt_double searchAngleResolution,
723  kt_bool doPenalize, Pose2& rMean, Matrix3& rCovariance, kt_bool doingFineMatch)
724  {
725  assert(searchAngleResolution != 0.0);
726 
727  // setup lookup arrays
728  m_pGridLookup->ComputeOffsets(pScan, rSearchCenter.GetHeading(), searchAngleOffset, searchAngleResolution);
729 
730  // only initialize probability grid if computing positional covariance (during coarse match)
731  if (!doingFineMatch)
732  {
733  m_pSearchSpaceProbs->Clear();
734 
735  // position search grid - finds lower left corner of search grid
736  Vector2<kt_double> offset(rSearchCenter.GetPosition() - rSearchSpaceOffset);
737  m_pSearchSpaceProbs->GetCoordinateConverter()->SetOffset(offset);
738  }
739 
740  // calculate position arrays
741 
742  m_xPoses.clear();
743  kt_int32u nX = static_cast<kt_int32u>(math::Round(rSearchSpaceOffset.GetX() *
744  2.0 / rSearchSpaceResolution.GetX()) + 1);
745  kt_double startX = -rSearchSpaceOffset.GetX();
746  for (kt_int32u xIndex = 0; xIndex < nX; xIndex++)
747  {
748  m_xPoses.push_back(startX + xIndex * rSearchSpaceResolution.GetX());
749  }
750  assert(math::DoubleEqual(m_xPoses.back(), -startX));
751 
752  m_yPoses.clear();
753  kt_int32u nY = static_cast<kt_int32u>(math::Round(rSearchSpaceOffset.GetY() *
754  2.0 / rSearchSpaceResolution.GetY()) + 1);
755  kt_double startY = -rSearchSpaceOffset.GetY();
756  for (kt_int32u yIndex = 0; yIndex < nY; yIndex++)
757  {
758  m_yPoses.push_back(startY + yIndex * rSearchSpaceResolution.GetY());
759  }
760  assert(math::DoubleEqual(m_yPoses.back(), -startY));
761 
762  // calculate pose response array size
763  kt_int32u nAngles = static_cast<kt_int32u>(math::Round(searchAngleOffset * 2.0 / searchAngleResolution) + 1);
764 
765  kt_int32u poseResponseSize = static_cast<kt_int32u>(m_xPoses.size() * m_yPoses.size() * nAngles);
766 
767  // allocate array
768  m_pPoseResponse = new std::pair<kt_double, Pose2>[poseResponseSize];
769 
770  Vector2<kt_int32s> startGridPoint = m_pCorrelationGrid->WorldToGrid(Vector2<kt_double>(rSearchCenter.GetX()
771  + startX, rSearchCenter.GetY() + startY));
772 
773  // this isn't good but its the fastest way to iterate. Should clean up later.
774  m_rSearchCenter = rSearchCenter;
775  m_searchAngleOffset = searchAngleOffset;
776  m_nAngles = nAngles;
777  m_searchAngleResolution = searchAngleResolution;
778  m_doPenalize = doPenalize;
779  tbb::parallel_do(m_yPoses, (*this) );
780 
781  // find value of best response (in [0; 1])
782  kt_double bestResponse = -1;
783  for (kt_int32u i = 0; i < poseResponseSize; i++)
784  {
785  bestResponse = math::Maximum(bestResponse, m_pPoseResponse[i].first);
786 
787  // will compute positional covariance, save best relative probability for each cell
788  if (!doingFineMatch)
789  {
790  const Pose2& rPose = m_pPoseResponse[i].second;
791  Vector2<kt_int32s> grid = m_pSearchSpaceProbs->WorldToGrid(rPose.GetPosition());
792  kt_double* ptr;
793 
794  try
795  {
796  ptr = (kt_double*)(m_pSearchSpaceProbs->GetDataPointer(grid));
797  }
798  catch(...)
799  {
800  throw std::runtime_error("Mapper FATAL ERROR - unable to get pointer in probability search!");
801  }
802 
803  if (ptr == NULL)
804  {
805  throw std::runtime_error("Mapper FATAL ERROR - Index out of range in probability search!");
806  }
807 
808  *ptr = math::Maximum(m_pPoseResponse[i].first, *ptr);
809  }
810  }
811 
812  // average all poses with same highest response
813  Vector2<kt_double> averagePosition;
814  kt_double thetaX = 0.0;
815  kt_double thetaY = 0.0;
816  kt_int32s averagePoseCount = 0;
817  for (kt_int32u i = 0; i < poseResponseSize; i++)
818  {
819  if (math::DoubleEqual(m_pPoseResponse[i].first, bestResponse))
820  {
821  averagePosition += m_pPoseResponse[i].second.GetPosition();
822 
823  kt_double heading = m_pPoseResponse[i].second.GetHeading();
824  thetaX += cos(heading);
825  thetaY += sin(heading);
826 
827  averagePoseCount++;
828  }
829  }
830 
831  Pose2 averagePose;
832  if (averagePoseCount > 0)
833  {
834  averagePosition /= averagePoseCount;
835 
836  thetaX /= averagePoseCount;
837  thetaY /= averagePoseCount;
838 
839  averagePose = Pose2(averagePosition, atan2(thetaY, thetaX));
840  }
841  else
842  {
843  throw std::runtime_error("Mapper FATAL ERROR - Unable to find best position");
844  }
845 
846  // delete pose response array
847  delete [] m_pPoseResponse;
848  m_pPoseResponse = nullptr;
849 
850 #ifdef KARTO_DEBUG
851  std::cout << "bestPose: " << averagePose << std::endl;
852  std::cout << "bestResponse: " << bestResponse << std::endl;
853 #endif
854 
855  if (!doingFineMatch)
856  {
857  ComputePositionalCovariance(averagePose, bestResponse, rSearchCenter, rSearchSpaceOffset,
858  rSearchSpaceResolution, searchAngleResolution, rCovariance);
859  }
860  else
861  {
862  ComputeAngularCovariance(averagePose, bestResponse, rSearchCenter,
863  searchAngleOffset, searchAngleResolution, rCovariance);
864  }
865 
866  rMean = averagePose;
867 
868 #ifdef KARTO_DEBUG
869  std::cout << "bestPose: " << averagePose << std::endl;
870 #endif
871 
872  if (bestResponse > 1.0)
873  {
874  bestResponse = 1.0;
875  }
876 
877  assert(math::InRange(bestResponse, 0.0, 1.0));
878  assert(math::InRange(rMean.GetHeading(), -KT_PI, KT_PI));
879 
880  return bestResponse;
881  }
882 
893  void ScanMatcher::ComputePositionalCovariance(const Pose2& rBestPose, kt_double bestResponse,
894  const Pose2& rSearchCenter,
895  const Vector2<kt_double>& rSearchSpaceOffset,
896  const Vector2<kt_double>& rSearchSpaceResolution,
897  kt_double searchAngleResolution, Matrix3& rCovariance)
898  {
899  // reset covariance to identity matrix
900  rCovariance.SetToIdentity();
901 
902  // if best response is vary small return max variance
903  if (bestResponse < KT_TOLERANCE)
904  {
905  rCovariance(0, 0) = MAX_VARIANCE; // XX
906  rCovariance(1, 1) = MAX_VARIANCE; // YY
907  rCovariance(2, 2) = 4 * math::Square(searchAngleResolution); // TH*TH
908 
909  return;
910  }
911 
912  kt_double accumulatedVarianceXX = 0;
913  kt_double accumulatedVarianceXY = 0;
914  kt_double accumulatedVarianceYY = 0;
915  kt_double norm = 0;
916 
917  kt_double dx = rBestPose.GetX() - rSearchCenter.GetX();
918  kt_double dy = rBestPose.GetY() - rSearchCenter.GetY();
919 
920  kt_double offsetX = rSearchSpaceOffset.GetX();
921  kt_double offsetY = rSearchSpaceOffset.GetY();
922 
923  kt_int32u nX = static_cast<kt_int32u>(math::Round(offsetX * 2.0 / rSearchSpaceResolution.GetX()) + 1);
924  kt_double startX = -offsetX;
925  assert(math::DoubleEqual(startX + (nX - 1) * rSearchSpaceResolution.GetX(), -startX));
926 
927  kt_int32u nY = static_cast<kt_int32u>(math::Round(offsetY * 2.0 / rSearchSpaceResolution.GetY()) + 1);
928  kt_double startY = -offsetY;
929  assert(math::DoubleEqual(startY + (nY - 1) * rSearchSpaceResolution.GetY(), -startY));
930 
931  for (kt_int32u yIndex = 0; yIndex < nY; yIndex++)
932  {
933  kt_double y = startY + yIndex * rSearchSpaceResolution.GetY();
934 
935  for (kt_int32u xIndex = 0; xIndex < nX; xIndex++)
936  {
937  kt_double x = startX + xIndex * rSearchSpaceResolution.GetX();
938 
939  Vector2<kt_int32s> gridPoint = m_pSearchSpaceProbs->WorldToGrid(Vector2<kt_double>(rSearchCenter.GetX() + x,
940  rSearchCenter.GetY() + y));
941  kt_double response = *(m_pSearchSpaceProbs->GetDataPointer(gridPoint));
942 
943  // response is not a low response
944  if (response >= (bestResponse - 0.1))
945  {
946  norm += response;
947  accumulatedVarianceXX += (math::Square(x - dx) * response);
948  accumulatedVarianceXY += ((x - dx) * (y - dy) * response);
949  accumulatedVarianceYY += (math::Square(y - dy) * response);
950  }
951  }
952  }
953 
954  if (norm > KT_TOLERANCE)
955  {
956  kt_double varianceXX = accumulatedVarianceXX / norm;
957  kt_double varianceXY = accumulatedVarianceXY / norm;
958  kt_double varianceYY = accumulatedVarianceYY / norm;
959  kt_double varianceTHTH = 4 * math::Square(searchAngleResolution);
960 
961  // lower-bound variances so that they are not too small;
962  // ensures that links are not too tight
963  kt_double minVarianceXX = 0.1 * math::Square(rSearchSpaceResolution.GetX());
964  kt_double minVarianceYY = 0.1 * math::Square(rSearchSpaceResolution.GetY());
965  varianceXX = math::Maximum(varianceXX, minVarianceXX);
966  varianceYY = math::Maximum(varianceYY, minVarianceYY);
967 
968  // increase variance for poorer responses
969  kt_double multiplier = 1.0 / bestResponse;
970  rCovariance(0, 0) = varianceXX * multiplier;
971  rCovariance(0, 1) = varianceXY * multiplier;
972  rCovariance(1, 0) = varianceXY * multiplier;
973  rCovariance(1, 1) = varianceYY * multiplier;
974  rCovariance(2, 2) = varianceTHTH; // this value will be set in ComputeAngularCovariance
975  }
976 
977  // if values are 0, set to MAX_VARIANCE
978  // values might be 0 if points are too sparse and thus don't hit other points
979  if (math::DoubleEqual(rCovariance(0, 0), 0.0))
980  {
981  rCovariance(0, 0) = MAX_VARIANCE;
982  }
983 
984  if (math::DoubleEqual(rCovariance(1, 1), 0.0))
985  {
986  rCovariance(1, 1) = MAX_VARIANCE;
987  }
988  }
989 
1000  kt_double bestResponse,
1001  const Pose2& rSearchCenter,
1002  kt_double searchAngleOffset,
1003  kt_double searchAngleResolution,
1004  Matrix3& rCovariance)
1005  {
1006  // NOTE: do not reset covariance matrix
1007 
1008  // normalize angle difference
1009  kt_double bestAngle = math::NormalizeAngleDifference(rBestPose.GetHeading(), rSearchCenter.GetHeading());
1010 
1011  Vector2<kt_int32s> gridPoint = m_pCorrelationGrid->WorldToGrid(rBestPose.GetPosition());
1012  kt_int32s gridIndex = m_pCorrelationGrid->GridIndex(gridPoint);
1013 
1014  kt_int32u nAngles = static_cast<kt_int32u>(math::Round(searchAngleOffset * 2 / searchAngleResolution) + 1);
1015 
1016  kt_double angle = 0.0;
1017  kt_double startAngle = rSearchCenter.GetHeading() - searchAngleOffset;
1018 
1019  kt_double norm = 0.0;
1020  kt_double accumulatedVarianceThTh = 0.0;
1021  for (kt_int32u angleIndex = 0; angleIndex < nAngles; angleIndex++)
1022  {
1023  angle = startAngle + angleIndex * searchAngleResolution;
1024  kt_double response = GetResponse(angleIndex, gridIndex);
1025 
1026  // response is not a low response
1027  if (response >= (bestResponse - 0.1))
1028  {
1029  norm += response;
1030  accumulatedVarianceThTh += (math::Square(angle - bestAngle) * response);
1031  }
1032  }
1033  assert(math::DoubleEqual(angle, rSearchCenter.GetHeading() + searchAngleOffset));
1034 
1035  if (norm > KT_TOLERANCE)
1036  {
1037  if (accumulatedVarianceThTh < KT_TOLERANCE)
1038  {
1039  accumulatedVarianceThTh = math::Square(searchAngleResolution);
1040  }
1041 
1042  accumulatedVarianceThTh /= norm;
1043  }
1044  else
1045  {
1046  accumulatedVarianceThTh = 1000 * math::Square(searchAngleResolution);
1047  }
1048 
1049  rCovariance(2, 2) = accumulatedVarianceThTh;
1050  }
1051 
1058  {
1059  m_pCorrelationGrid->Clear();
1060 
1061  // add all scans to grid
1063  {
1064  if (*iter == NULL)
1065  {
1066  continue;
1067  }
1068 
1069  AddScan(*iter, viewPoint);
1070  }
1071  }
1072 
1079  {
1080  m_pCorrelationGrid->Clear();
1081 
1082  // add all scans to grid
1084  {
1085  if (iter->second == NULL)
1086  {
1087  continue;
1088  }
1089 
1090  AddScan(iter->second, viewPoint);
1091  }
1092  }
1093 
1100  void ScanMatcher::AddScan(LocalizedRangeScan* pScan, const Vector2<kt_double>& rViewPoint, kt_bool doSmear)
1101  {
1102  PointVectorDouble validPoints = FindValidPoints(pScan, rViewPoint);
1103 
1104  // put in all valid points
1105  const_forEach(PointVectorDouble, &validPoints)
1106  {
1107  Vector2<kt_int32s> gridPoint = m_pCorrelationGrid->WorldToGrid(*iter);
1108  if (!math::IsUpTo(gridPoint.GetX(), m_pCorrelationGrid->GetROI().GetWidth()) ||
1109  !math::IsUpTo(gridPoint.GetY(), m_pCorrelationGrid->GetROI().GetHeight()))
1110  {
1111  // point not in grid
1112  continue;
1113  }
1114 
1115  int gridIndex = m_pCorrelationGrid->GridIndex(gridPoint);
1116 
1117  // set grid cell as occupied
1118  if (m_pCorrelationGrid->GetDataPointer()[gridIndex] == GridStates_Occupied)
1119  {
1120  // value already set
1121  continue;
1122  }
1123 
1124  m_pCorrelationGrid->GetDataPointer()[gridIndex] = GridStates_Occupied;
1125 
1126  // smear grid
1127  if (doSmear == true)
1128  {
1129  m_pCorrelationGrid->SmearPoint(gridPoint);
1130  }
1131  }
1132  }
1133 
1141  {
1142  const PointVectorDouble& rPointReadings = pScan->GetPointReadings();
1143 
1144  // points must be at least 10 cm away when making comparisons of inside/outside of viewpoint
1145  const kt_double minSquareDistance = math::Square(0.1); // in m^2
1146 
1147  // this iterator lags from the main iterator adding points only when the points are on
1148  // the same side as the viewpoint
1149  PointVectorDouble::const_iterator trailingPointIter = rPointReadings.begin();
1150  PointVectorDouble validPoints;
1151 
1152  Vector2<kt_double> firstPoint;
1153  kt_bool firstTime = true;
1154  const_forEach(PointVectorDouble, &rPointReadings)
1155  {
1156  Vector2<kt_double> currentPoint = *iter;
1157 
1158  if (firstTime && !std::isnan(currentPoint.GetX()) && !std::isnan(currentPoint.GetY()))
1159  {
1160  firstPoint = currentPoint;
1161  firstTime = false;
1162  }
1163 
1164  Vector2<kt_double> delta = firstPoint - currentPoint;
1165  if (delta.SquaredLength() > minSquareDistance)
1166  {
1167  // This compute the Determinant (viewPoint FirstPoint, viewPoint currentPoint)
1168  // Which computes the direction of rotation, if the rotation is counterclock
1169  // wise then we are looking at data we should keep. If it's negative rotation
1170  // we should not included in in the matching
1171  // have enough distance, check viewpoint
1172  double a = rViewPoint.GetY() - firstPoint.GetY();
1173  double b = firstPoint.GetX() - rViewPoint.GetX();
1174  double c = firstPoint.GetY() * rViewPoint.GetX() - firstPoint.GetX() * rViewPoint.GetY();
1175  double ss = currentPoint.GetX() * a + currentPoint.GetY() * b + c;
1176 
1177  // reset beginning point
1178  firstPoint = currentPoint;
1179 
1180  if (ss < 0.0) // wrong side, skip and keep going
1181  {
1182  trailingPointIter = iter;
1183  }
1184  else
1185  {
1186  for (; trailingPointIter != iter; ++trailingPointIter)
1187  {
1188  validPoints.push_back(*trailingPointIter);
1189  }
1190  }
1191  }
1192  }
1193 
1194  return validPoints;
1195  }
1196 
1203  kt_double ScanMatcher::GetResponse(kt_int32u angleIndex, kt_int32s gridPositionIndex) const
1204  {
1205  kt_double response = 0.0;
1206 
1207  // add up value for each point
1208  kt_int8u* pByte = m_pCorrelationGrid->GetDataPointer() + gridPositionIndex;
1209 
1210  const LookupArray* pOffsets = m_pGridLookup->GetLookupArray(angleIndex);
1211  assert(pOffsets != NULL);
1212 
1213  // get number of points in offset list
1214  kt_int32u nPoints = pOffsets->GetSize();
1215  if (nPoints == 0)
1216  {
1217  return response;
1218  }
1219 
1220  // calculate response
1221  kt_int32s* pAngleIndexPointer = pOffsets->GetArrayPointer();
1222  for (kt_int32u i = 0; i < nPoints; i++)
1223  {
1224  // ignore points that fall off the grid
1225  kt_int32s pointGridIndex = gridPositionIndex + pAngleIndexPointer[i];
1226  if (!math::IsUpTo(pointGridIndex, m_pCorrelationGrid->GetDataSize()) || pAngleIndexPointer[i] == INVALID_SCAN)
1227  {
1228  continue;
1229  }
1230 
1231  // uses index offsets to efficiently find location of point in the grid
1232  response += pByte[pAngleIndexPointer[i]];
1233  }
1234 
1235  // normalize response
1236  response /= (nPoints * GridStates_Occupied);
1237  assert(fabs(response) <= 1.0);
1238 
1239  return response;
1240  }
1241 
1242 
1246 
1247  template<typename T>
1249  {
1250  public:
1255  {
1256  }
1258  : GraphTraversal<T>(pGraph)
1259  {
1260  }
1261 
1266  {
1267  }
1268 
1269  public:
1276  virtual std::vector<T*> TraverseForScans(Vertex<T>* pStartVertex, Visitor<T>* pVisitor)
1277  {
1278  std::vector<Vertex<T>*> validVertices = TraverseForVertices(pStartVertex, pVisitor);
1279 
1280  std::vector<T*> objects;
1281  forEach(typename std::vector<Vertex<T>*>, &validVertices)
1282  {
1283  objects.push_back((*iter)->GetObject());
1284  }
1285 
1286  return objects;
1287  }
1288 
1295  virtual std::vector<Vertex<T>*> TraverseForVertices(Vertex<T>* pStartVertex, Visitor<T>* pVisitor)
1296  {
1297  std::queue<Vertex<T>*> toVisit;
1298  std::set<Vertex<T>*> seenVertices;
1299  std::vector<Vertex<T>*> validVertices;
1300 
1301  toVisit.push(pStartVertex);
1302  seenVertices.insert(pStartVertex);
1303 
1304  do
1305  {
1306  Vertex<T>* pNext = toVisit.front();
1307  toVisit.pop();
1308 
1309  if (pNext != NULL && pVisitor->Visit(pNext))
1310  {
1311  // vertex is valid, explore neighbors
1312  validVertices.push_back(pNext);
1313 
1314  std::vector<Vertex<T>*> adjacentVertices = pNext->GetAdjacentVertices();
1315  forEach(typename std::vector<Vertex<T>*>, &adjacentVertices)
1316  {
1317  Vertex<T>* pAdjacent = *iter;
1318 
1319  // adjacent vertex has not yet been seen, add to queue for processing
1320  if (seenVertices.find(pAdjacent) == seenVertices.end())
1321  {
1322  toVisit.push(pAdjacent);
1323  seenVertices.insert(pAdjacent);
1324  }
1325  }
1326  }
1327  } while (toVisit.empty() == false);
1328 
1329  return validVertices;
1330  }
1331 
1332  friend class boost::serialization::access;
1333  template<class Archive>
1334  void serialize(Archive &ar, const unsigned int version)
1335  {
1336  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(GraphTraversal<T>);
1337  }
1338  }; // class BreadthFirstTraversal
1339 
1343 
1344  class NearScanVisitor : public Visitor<LocalizedRangeScan>
1345  {
1346  public:
1347  NearScanVisitor(LocalizedRangeScan* pScan, kt_double maxDistance, kt_bool useScanBarycenter)
1348  : m_MaxDistanceSquared(math::Square(maxDistance))
1349  , m_UseScanBarycenter(useScanBarycenter)
1350  {
1351  m_CenterPose = pScan->GetReferencePose(m_UseScanBarycenter);
1352  }
1353 
1355  {
1356  try
1357  {
1358  LocalizedRangeScan* pScan = pVertex->GetObject();
1359  Pose2 pose = pScan->GetReferencePose(m_UseScanBarycenter);
1360  kt_double squaredDistance = pose.GetPosition().SquaredDistance(m_CenterPose.GetPosition());
1361  return (squaredDistance <= m_MaxDistanceSquared - KT_TOLERANCE);
1362  }
1363  catch(...)
1364  {
1365  // relocalization vertex elements missing
1366  std::cout << "Unable to visit valid vertex elements!" << std::endl;
1367  return false;
1368  }
1369  }
1370 
1371  protected:
1375  friend class boost::serialization::access;
1376  template<class Archive>
1377  void serialize(Archive &ar, const unsigned int version)
1378  {
1379  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Visitor<LocalizedRangeScan>);
1380  ar & BOOST_SERIALIZATION_NVP(m_CenterPose);
1381  ar & BOOST_SERIALIZATION_NVP(m_MaxDistanceSquared);
1382  ar & BOOST_SERIALIZATION_NVP(m_UseScanBarycenter);
1383  }
1384  }; // NearScanVisitor
1385 
1389 
1390  class NearPoseVisitor : public Visitor<LocalizedRangeScan>
1391  {
1392  public:
1393  NearPoseVisitor(Pose2 refPose, kt_double maxDistance, kt_bool useScanBarycenter)
1394  : m_MaxDistanceSquared(math::Square(maxDistance))
1395  , m_UseScanBarycenter(useScanBarycenter)
1396  {
1397  m_CenterPose = refPose;
1398  }
1399 
1401  {
1402  LocalizedRangeScan* pScan = pVertex->GetObject();
1403 
1404  Pose2 pose = pScan->GetReferencePose(m_UseScanBarycenter);
1405 
1406  kt_double squaredDistance = pose.GetPosition().SquaredDistance(m_CenterPose.GetPosition());
1407  return (squaredDistance <= m_MaxDistanceSquared - KT_TOLERANCE);
1408  }
1409 
1410  protected:
1414  friend class boost::serialization::access;
1415  template<class Archive>
1416  void serialize(Archive &ar, const unsigned int version)
1417  {
1418  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Visitor<LocalizedRangeScan>);
1419  ar & BOOST_SERIALIZATION_NVP(m_CenterPose);
1420  ar & BOOST_SERIALIZATION_NVP(m_MaxDistanceSquared);
1421  ar & BOOST_SERIALIZATION_NVP(m_UseScanBarycenter);
1422  }
1423  }; // NearPoseVisitor
1424 
1428 
1429 
1430  MapperGraph::MapperGraph(Mapper* pMapper, kt_double rangeThreshold)
1431  : m_pMapper(pMapper)
1432  {
1436  assert(m_pLoopScanMatcher);
1437 
1439  }
1440 
1442  {
1443  if (m_pLoopScanMatcher)
1444  {
1445  delete m_pLoopScanMatcher;
1447  }
1448  if (m_pTraversal)
1449  {
1450  delete m_pTraversal;
1451  m_pTraversal = NULL;
1452  }
1453  }
1454 
1456  {
1457  assert(pScan);
1458 
1459  if (pScan != NULL)
1460  {
1464  {
1465  m_pMapper->m_pScanOptimizer->AddNode(pVertex);
1466  }
1467  return pVertex;
1468  }
1469  }
1470 
1471  void MapperGraph::AddEdges(LocalizedRangeScan* pScan, const Matrix3& rCovariance)
1472  {
1474 
1475  const Name rSensorName = pScan->GetSensorName();
1476 
1477  // link to previous scan
1478  kt_int32s previousScanNum = pScan->GetStateId() - 1;
1479  if (pSensorManager->GetLastScan(rSensorName) != NULL)
1480  {
1481  assert(previousScanNum >= 0);
1482  LocalizedRangeScan* pPrevScan = pSensorManager->GetScan(rSensorName, previousScanNum);
1483  if (!pPrevScan)
1484  {
1485  return;
1486  }
1487  LinkScans(pPrevScan, pScan, pScan->GetSensorPose(), rCovariance);
1488  }
1489 
1490  Pose2Vector means;
1491  std::vector<Matrix3> covariances;
1492 
1493  // first scan (link to first scan of other robots)
1494  if (pSensorManager->GetLastScan(rSensorName) == NULL)
1495  {
1496  assert(pSensorManager->GetScans(rSensorName).size() == 1);
1497 
1498  std::vector<Name> deviceNames = pSensorManager->GetSensorNames();
1499  forEach(std::vector<Name>, &deviceNames)
1500  {
1501  const Name& rCandidateSensorName = *iter;
1502 
1503  // skip if candidate device is the same or other device has no scans
1504  if ((rCandidateSensorName == rSensorName) || (pSensorManager->GetScans(rCandidateSensorName).empty()))
1505  {
1506  continue;
1507  }
1508 
1509  Pose2 bestPose;
1510  Matrix3 covariance;
1512  pSensorManager->GetScans(rCandidateSensorName),
1513  bestPose, covariance);
1514  LinkScans(pScan, pSensorManager->GetScan(rCandidateSensorName, 0), bestPose, covariance);
1515 
1516  // only add to means and covariances if response was high "enough"
1518  {
1519  means.push_back(bestPose);
1520  covariances.push_back(covariance);
1521  }
1522  }
1523  }
1524  else
1525  {
1526  // link to running scans
1527  Pose2 scanPose = pScan->GetSensorPose();
1528  means.push_back(scanPose);
1529  covariances.push_back(rCovariance);
1530  LinkChainToScan(pSensorManager->GetRunningScans(rSensorName), pScan, scanPose, rCovariance);
1531  }
1532 
1533  // link to other near chains (chains that include new scan are invalid)
1534  LinkNearChains(pScan, means, covariances);
1535 
1536  if (!means.empty())
1537  {
1538  pScan->SetSensorPose(ComputeWeightedMean(means, covariances));
1539  }
1540  }
1541 
1543  {
1544  kt_bool loopClosed = false;
1545 
1546  kt_int32u scanIndex = 0;
1547 
1548  LocalizedRangeScanVector candidateChain = FindPossibleLoopClosure(pScan, rSensorName, scanIndex);
1549 
1550  while (!candidateChain.empty())
1551  {
1552  Pose2 bestPose;
1553  Matrix3 covariance;
1554  kt_double coarseResponse = m_pLoopScanMatcher->MatchScan(pScan, candidateChain,
1555  bestPose, covariance, false, false);
1556 
1557  std::stringstream stream;
1558  stream << "COARSE RESPONSE: " << coarseResponse
1559  << " (> " << m_pMapper->m_pLoopMatchMinimumResponseCoarse->GetValue() << ")"
1560  << std::endl;
1561  stream << " var: " << covariance(0, 0) << ", " << covariance(1, 1)
1562  << " (< " << m_pMapper->m_pLoopMatchMaximumVarianceCoarse->GetValue() << ")";
1563 
1564  m_pMapper->FireLoopClosureCheck(stream.str());
1565 
1566  if ((coarseResponse > m_pMapper->m_pLoopMatchMinimumResponseCoarse->GetValue()) &&
1567  (covariance(0, 0) < m_pMapper->m_pLoopMatchMaximumVarianceCoarse->GetValue()) &&
1568  (covariance(1, 1) < m_pMapper->m_pLoopMatchMaximumVarianceCoarse->GetValue()))
1569  {
1570  LocalizedRangeScan tmpScan(pScan->GetSensorName(), pScan->GetRangeReadingsVector());
1571  tmpScan.SetUniqueId(pScan->GetUniqueId());
1572  tmpScan.SetTime(pScan->GetTime());
1573  tmpScan.SetStateId(pScan->GetStateId());
1574  tmpScan.SetCorrectedPose(pScan->GetCorrectedPose());
1575  tmpScan.SetSensorPose(bestPose); // This also updates OdometricPose.
1576  kt_double fineResponse = m_pMapper->m_pSequentialScanMatcher->MatchScan(&tmpScan, candidateChain,
1577  bestPose, covariance, false);
1578 
1579  std::stringstream stream1;
1580  stream1 << "FINE RESPONSE: " << fineResponse << " (>"
1581  << m_pMapper->m_pLoopMatchMinimumResponseFine->GetValue() << ")" << std::endl;
1582  m_pMapper->FireLoopClosureCheck(stream1.str());
1583 
1584  if (fineResponse < m_pMapper->m_pLoopMatchMinimumResponseFine->GetValue())
1585  {
1586  m_pMapper->FireLoopClosureCheck("REJECTED!");
1587  }
1588  else
1589  {
1590  m_pMapper->FireBeginLoopClosure("Closing loop...");
1591 
1592  pScan->SetSensorPose(bestPose);
1593  LinkChainToScan(candidateChain, pScan, bestPose, covariance);
1594  CorrectPoses();
1595 
1596  m_pMapper->FireEndLoopClosure("Loop closed!");
1597 
1598  loopClosed = true;
1599  }
1600  }
1601 
1602  candidateChain = FindPossibleLoopClosure(pScan, rSensorName, scanIndex);
1603  }
1604 
1605  return loopClosed;
1606  }
1607 
1609  const Pose2& rPose) const
1610  {
1611  LocalizedRangeScan* pClosestScan = NULL;
1612  kt_double bestSquaredDistance = DBL_MAX;
1613 
1615  {
1616  Pose2 scanPose = (*iter)->GetReferencePose(m_pMapper->m_pUseScanBarycenter->GetValue());
1617 
1618  kt_double squaredDistance = rPose.GetPosition().SquaredDistance(scanPose.GetPosition());
1619  if (squaredDistance < bestSquaredDistance)
1620  {
1621  bestSquaredDistance = squaredDistance;
1622  pClosestScan = *iter;
1623  }
1624  }
1625 
1626  return pClosestScan;
1627  }
1628 
1630  LocalizedRangeScan* pTargetScan, kt_bool& rIsNewEdge)
1631  {
1632  std::map<int, Vertex<LocalizedRangeScan>* >::iterator v1 = m_Vertices[pSourceScan->GetSensorName()].find(pSourceScan->GetStateId());
1633  std::map<int, Vertex<LocalizedRangeScan>* >::iterator v2 = m_Vertices[pTargetScan->GetSensorName()].find(pTargetScan->GetStateId());
1634 
1635  if (v1 == m_Vertices[pSourceScan->GetSensorName()].end() ||
1636  v2 == m_Vertices[pSourceScan->GetSensorName()].end())
1637  {
1638  std::cout << "AddEdge: At least one vertex is invalid." << std::endl;
1639  return NULL;
1640  }
1641 
1642  // see if edge already exists
1643  const_forEach(std::vector<Edge<LocalizedRangeScan>*>, &(v1->second->GetEdges()))
1644  {
1645  Edge<LocalizedRangeScan>* pEdge = *iter;
1646 
1647  if (pEdge->GetTarget() == v2->second)
1648  {
1649  rIsNewEdge = false;
1650  return pEdge;
1651  }
1652  }
1653 
1654  Edge<LocalizedRangeScan>* pEdge = new Edge<LocalizedRangeScan>(v1->second, v2->second);
1656  rIsNewEdge = true;
1657  return pEdge;
1658  }
1659 
1661  const Pose2& rMean, const Matrix3& rCovariance)
1662  {
1663  kt_bool isNewEdge = true;
1664  Edge<LocalizedRangeScan>* pEdge = AddEdge(pFromScan, pToScan, isNewEdge);
1665 
1666  if (pEdge == NULL)
1667  {
1668  return;
1669  }
1670 
1671  // only attach link information if the edge is new
1672  if (isNewEdge == true)
1673  {
1674  pEdge->SetLabel(new LinkInfo(pFromScan->GetCorrectedPose(), pToScan->GetCorrectedAt(rMean), rCovariance));
1676  {
1678  }
1679  }
1680  }
1681 
1682  void MapperGraph::LinkNearChains(LocalizedRangeScan* pScan, Pose2Vector& rMeans, std::vector<Matrix3>& rCovariances)
1683  {
1684  const std::vector<LocalizedRangeScanVector> nearChains = FindNearChains(pScan);
1685  const_forEach(std::vector<LocalizedRangeScanVector>, &nearChains)
1686  {
1687  if (iter->size() < m_pMapper->m_pLoopMatchMinimumChainSize->GetValue())
1688  {
1689  continue;
1690  }
1691 
1692  Pose2 mean;
1693  Matrix3 covariance;
1694  // match scan against "near" chain
1695  kt_double response = m_pMapper->m_pSequentialScanMatcher->MatchScan(pScan, *iter, mean, covariance, false);
1697  {
1698  rMeans.push_back(mean);
1699  rCovariances.push_back(covariance);
1700  LinkChainToScan(*iter, pScan, mean, covariance);
1701  }
1702  }
1703  }
1704 
1706  const Pose2& rMean, const Matrix3& rCovariance)
1707  {
1709 
1710  LocalizedRangeScan* pClosestScan = GetClosestScanToPose(rChain, pose);
1711  assert(pClosestScan != NULL);
1712 
1713  Pose2 closestScanPose = pClosestScan->GetReferencePose(m_pMapper->m_pUseScanBarycenter->GetValue());
1714 
1715  kt_double squaredDistance = pose.GetPosition().SquaredDistance(closestScanPose.GetPosition());
1717  {
1718  LinkScans(pClosestScan, pScan, rMean, rCovariance);
1719  }
1720  }
1721 
1722  std::vector<LocalizedRangeScanVector> MapperGraph::FindNearChains(LocalizedRangeScan* pScan)
1723  {
1724  std::vector<LocalizedRangeScanVector> nearChains;
1725 
1727 
1728  // to keep track of which scans have been added to a chain
1729  LocalizedRangeScanVector processed;
1730 
1731  const LocalizedRangeScanVector nearLinkedScans = FindNearLinkedScans(pScan,
1733  const_forEach(LocalizedRangeScanVector, &nearLinkedScans)
1734  {
1735  LocalizedRangeScan* pNearScan = *iter;
1736 
1737  if (pNearScan == pScan)
1738  {
1739  continue;
1740  }
1741 
1742  // scan has already been processed, skip
1743  if (find(processed.begin(), processed.end(), pNearScan) != processed.end())
1744  {
1745  continue;
1746  }
1747 
1748  processed.push_back(pNearScan);
1749 
1750  // build up chain
1751  kt_bool isValidChain = true;
1752  std::list<LocalizedRangeScan*> chain;
1753 
1754  // add scans before current scan being processed
1755  for (kt_int32s candidateScanNum = pNearScan->GetStateId() - 1; candidateScanNum >= 0; candidateScanNum--)
1756  {
1757  LocalizedRangeScan* pCandidateScan = m_pMapper->m_pMapperSensorManager->GetScan(pNearScan->GetSensorName(),
1758  candidateScanNum);
1759 
1760  // chain is invalid--contains scan being added
1761  if (pCandidateScan == pScan)
1762  {
1763  isValidChain = false;
1764  }
1765 
1766  // probably removed in localization mode
1767  if (pCandidateScan == NULL)
1768  {
1769  continue;
1770  }
1771 
1772  Pose2 candidatePose = pCandidateScan->GetReferencePose(m_pMapper->m_pUseScanBarycenter->GetValue());
1773  kt_double squaredDistance = scanPose.GetPosition().SquaredDistance(candidatePose.GetPosition());
1774 
1776  {
1777  chain.push_front(pCandidateScan);
1778  processed.push_back(pCandidateScan);
1779  }
1780  else
1781  {
1782  break;
1783  }
1784  }
1785 
1786  chain.push_back(pNearScan);
1787 
1788  // add scans after current scan being processed
1789  kt_int32u end = static_cast<kt_int32u>(m_pMapper->m_pMapperSensorManager->GetScans(pNearScan->GetSensorName()).size());
1790  for (kt_int32u candidateScanNum = pNearScan->GetStateId() + 1; candidateScanNum < end; candidateScanNum++)
1791  {
1792  LocalizedRangeScan* pCandidateScan = m_pMapper->m_pMapperSensorManager->GetScan(pNearScan->GetSensorName(),
1793  candidateScanNum);
1794 
1795  if (pCandidateScan == pScan)
1796  {
1797  isValidChain = false;
1798  }
1799 
1800  // probably removed in localization mode
1801  if (pCandidateScan == NULL)
1802  {
1803  continue;
1804  }
1805 
1806  Pose2 candidatePose = pCandidateScan->GetReferencePose(m_pMapper->m_pUseScanBarycenter->GetValue());;
1807  kt_double squaredDistance = scanPose.GetPosition().SquaredDistance(candidatePose.GetPosition());
1808 
1810  {
1811  chain.push_back(pCandidateScan);
1812  processed.push_back(pCandidateScan);
1813  }
1814  else
1815  {
1816  break;
1817  }
1818  }
1819 
1820  if (isValidChain)
1821  {
1822  // change list to vector
1823  LocalizedRangeScanVector tempChain;
1824  std::copy(chain.begin(), chain.end(), std::inserter(tempChain, tempChain.begin()));
1825  // add chain to collection
1826  nearChains.push_back(tempChain);
1827  }
1828  }
1829 
1830  return nearChains;
1831  }
1832 
1834  {
1835  NearScanVisitor* pVisitor = new NearScanVisitor(pScan, maxDistance, m_pMapper->m_pUseScanBarycenter->GetValue());
1836  LocalizedRangeScanVector nearLinkedScans = m_pTraversal->TraverseForScans(GetVertex(pScan), pVisitor);
1837  delete pVisitor;
1838 
1839  return nearLinkedScans;
1840  }
1841 
1842  std::vector<Vertex<LocalizedRangeScan>*> MapperGraph::FindNearLinkedVertices(LocalizedRangeScan* pScan, kt_double maxDistance)
1843  {
1844  NearScanVisitor* pVisitor = new NearScanVisitor(pScan, maxDistance, m_pMapper->m_pUseScanBarycenter->GetValue());
1845  std::vector<Vertex<LocalizedRangeScan>*> nearLinkedVertices = m_pTraversal->TraverseForVertices(GetVertex(pScan), pVisitor);
1846  delete pVisitor;
1847 
1848  return nearLinkedVertices;
1849  }
1850 
1852  {
1853  NearPoseVisitor* pVisitor = new NearPoseVisitor(refPose, maxDistance, m_pMapper->m_pUseScanBarycenter->GetValue());
1854 
1855  Vertex<LocalizedRangeScan>* closestVertex = FindNearByScan(name, refPose);
1856 
1857  LocalizedRangeScanVector nearLinkedScans = m_pTraversal->TraverseForScans(closestVertex, pVisitor);
1858  delete pVisitor;
1859 
1860  return nearLinkedScans;
1861  }
1862 
1863  std::vector<Vertex<LocalizedRangeScan>*> MapperGraph::FindNearByVertices(Name name, const Pose2 refPose, kt_double maxDistance)
1864  {
1865  VertexMap vertexMap = GetVertices();
1866  std::map<int, Vertex<LocalizedRangeScan>*>& vertices = vertexMap[name];
1867 
1868  std::vector<Vertex<LocalizedRangeScan>*> vertices_to_search;
1869  std::map<int, Vertex<LocalizedRangeScan>*>::iterator it;
1870  for (it = vertices.begin(); it != vertices.end(); ++it)
1871  {
1872  if (it->second)
1873  {
1874  vertices_to_search.push_back(it->second);
1875  }
1876  }
1877 
1878  const size_t dim = 2;
1879 
1881  const P2KD p2kd(vertices_to_search);
1882 
1884 
1885  my_kd_tree_t index(dim, p2kd, nanoflann::KDTreeSingleIndexAdaptorParams(10) );
1886  index.buildIndex();
1887 
1888  std::vector<std::pair<size_t,double> > ret_matches;
1889  const double query_pt[2] = {refPose.GetX(), refPose.GetY()};
1890  nanoflann::SearchParams params;
1891  const size_t num_results = index.radiusSearch(&query_pt[0], maxDistance, ret_matches, params);
1892 
1893  std::vector<Vertex<LocalizedRangeScan>*> rtn_vertices;
1894  rtn_vertices.reserve(ret_matches.size());
1895  for (uint i = 0; i != ret_matches.size(); i++)
1896  {
1897  rtn_vertices.push_back(vertices_to_search[ret_matches[i].first]);
1898  }
1899  return rtn_vertices;
1900  }
1901 
1903  {
1904  VertexMap vertexMap = GetVertices();
1905  std::map<int, Vertex<LocalizedRangeScan>*>& vertices = vertexMap[name];
1906 
1907  std::vector<Vertex<LocalizedRangeScan>*> vertices_to_search;
1908  std::map<int, Vertex<LocalizedRangeScan>*>::iterator it;
1909  for (it = vertices.begin(); it != vertices.end(); ++it)
1910  {
1911  if (it->second)
1912  {
1913  vertices_to_search.push_back(it->second);
1914  }
1915  }
1916 
1917  size_t num_results = 1;
1918  const size_t dim = 2;
1919 
1921  const P2KD p2kd(vertices_to_search);
1922 
1924 
1925  my_kd_tree_t index(dim, p2kd, nanoflann::KDTreeSingleIndexAdaptorParams(10) );
1926  index.buildIndex();
1927 
1928  std::vector<size_t> ret_index(num_results);
1929  std::vector<double> out_dist_sqr(num_results);
1930  const double query_pt[2] = {refPose.GetX(), refPose.GetY()};
1931  num_results = index.knnSearch(&query_pt[0], num_results, &ret_index[0], &out_dist_sqr[0]);
1932 
1933  if (num_results > 0)
1934  {
1935  return vertices_to_search[ret_index[0]];
1936  }
1937  else
1938  {
1939  return NULL;
1940  }
1941  }
1942 
1943  Pose2 MapperGraph::ComputeWeightedMean(const Pose2Vector& rMeans, const std::vector<Matrix3>& rCovariances) const
1944  {
1945  assert(rMeans.size() == rCovariances.size());
1946 
1947  // compute sum of inverses and create inverse list
1948  std::vector<Matrix3> inverses;
1949  inverses.reserve(rCovariances.size());
1950 
1951  Matrix3 sumOfInverses;
1952  const_forEach(std::vector<Matrix3>, &rCovariances)
1953  {
1954  Matrix3 inverse = iter->Inverse();
1955  inverses.push_back(inverse);
1956 
1957  sumOfInverses += inverse;
1958  }
1959  Matrix3 inverseOfSumOfInverses = sumOfInverses.Inverse();
1960 
1961  // compute weighted mean
1962  Pose2 accumulatedPose;
1963  kt_double thetaX = 0.0;
1964  kt_double thetaY = 0.0;
1965 
1966  Pose2Vector::const_iterator meansIter = rMeans.begin();
1967  const_forEach(std::vector<Matrix3>, &inverses)
1968  {
1969  Pose2 pose = *meansIter;
1970  kt_double angle = pose.GetHeading();
1971  thetaX += cos(angle);
1972  thetaY += sin(angle);
1973 
1974  Matrix3 weight = inverseOfSumOfInverses * (*iter);
1975  accumulatedPose += weight * pose;
1976 
1977  ++meansIter;
1978  }
1979 
1980  thetaX /= rMeans.size();
1981  thetaY /= rMeans.size();
1982  accumulatedPose.SetHeading(atan2(thetaY, thetaX));
1983 
1984  return accumulatedPose;
1985  }
1986 
1988  const Name& rSensorName,
1989  kt_int32u& rStartNum)
1990  {
1991  LocalizedRangeScanVector chain; // return value
1992 
1994 
1995  // possible loop closure chain should not include close scans that have a
1996  // path of links to the scan of interest
1997  const LocalizedRangeScanVector nearLinkedScans =
1999 
2000  kt_int32u nScans = static_cast<kt_int32u>(m_pMapper->m_pMapperSensorManager->GetScans(rSensorName).size());
2001  for (; rStartNum < nScans; rStartNum++)
2002  {
2003  LocalizedRangeScan* pCandidateScan = m_pMapper->m_pMapperSensorManager->GetScan(rSensorName, rStartNum);
2004 
2005  if (pCandidateScan == NULL)
2006  {
2007  continue;
2008  }
2009 
2010  Pose2 candidateScanPose = pCandidateScan->GetReferencePose(m_pMapper->m_pUseScanBarycenter->GetValue());
2011 
2012  kt_double squaredDistance = candidateScanPose.GetPosition().SquaredDistance(pose.GetPosition());
2014  {
2015  // a linked scan cannot be in the chain
2016  if (find(nearLinkedScans.begin(), nearLinkedScans.end(), pCandidateScan) != nearLinkedScans.end())
2017  {
2018  chain.clear();
2019  }
2020  else
2021  {
2022  chain.push_back(pCandidateScan);
2023  }
2024  }
2025  else
2026  {
2027  // return chain if it is long "enough"
2028  if (chain.size() >= m_pMapper->m_pLoopMatchMinimumChainSize->GetValue())
2029  {
2030  return chain;
2031  }
2032  else
2033  {
2034  chain.clear();
2035  }
2036  }
2037  }
2038 
2039  return chain;
2040  }
2041 
2043  {
2044  // optimize scans!
2046  if (pSolver != NULL)
2047  {
2048  pSolver->Compute();
2049 
2051  {
2053  if (scan == NULL)
2054  {
2055  continue;
2056  }
2057  scan->SetCorrectedPoseAndUpdate(iter->second);
2058  }
2059 
2060  pSolver->Clear();
2061  }
2062  }
2063 
2065  {
2066  if (m_pLoopScanMatcher) {
2067  delete m_pLoopScanMatcher;
2068  }
2073  assert(m_pLoopScanMatcher);
2074  }
2075 
2079 
2084  : Module("Mapper"),
2085  m_Initialized(false),
2086  m_Deserialized(false),
2087  m_pSequentialScanMatcher(NULL),
2088  m_pMapperSensorManager(NULL),
2089  m_pGraph(NULL),
2090  m_pScanOptimizer(NULL)
2091  {
2093  }
2094 
2098  Mapper::Mapper(const std::string & rName)
2099  : Module(rName),
2100  m_Initialized(false),
2101  m_Deserialized(false),
2104  m_pGraph(NULL),
2106  {
2108  }
2109 
2114  {
2115  Reset();
2116 
2117  delete m_pMapperSensorManager;
2118  }
2119 
2121  {
2123  "UseScanMatching",
2124  "When set to true, the mapper will use a scan matching algorithm. "
2125  "In most real-world situations this should be set to true so that the "
2126  "mapper algorithm can correct for noise and errors in odometry and "
2127  "scan data. In some simulator environments where the simulated scan "
2128  "and odometry data are very accurate, the scan matching algorithm can "
2129  "produce worse results. In those cases set this to false to improve "
2130  "results.",
2131  true,
2133 
2135  "UseScanBarycenter",
2136  "Use the barycenter of scan endpoints to define distances between "
2137  "scans.",
2138  true, GetParameterManager());
2139 
2141  "MinimumTimeInterval",
2142  "Sets the minimum time between scans. If a new scan's time stamp is "
2143  "longer than MinimumTimeInterval from the previously processed scan, "
2144  "the mapper will use the data from the new scan. Otherwise, it will "
2145  "discard the new scan if it also does not meet the minimum travel "
2146  "distance and heading requirements. For performance reasons, it is "
2147  "generally it is a good idea to only process scans if a reasonable "
2148  "amount of time has passed. This parameter is particularly useful "
2149  "when there is a need to process scans while the robot is stationary.",
2150  3600, GetParameterManager());
2151 
2153  "MinimumTravelDistance",
2154  "Sets the minimum travel between scans. If a new scan's position is "
2155  "more than minimumTravelDistance from the previous scan, the mapper "
2156  "will use the data from the new scan. Otherwise, it will discard the "
2157  "new scan if it also does not meet the minimum change in heading "
2158  "requirement. For performance reasons, generally it is a good idea to "
2159  "only process scans if the robot has moved a reasonable amount.",
2160  0.2, GetParameterManager());
2161 
2163  "MinimumTravelHeading",
2164  "Sets the minimum heading change between scans. If a new scan's "
2165  "heading is more than MinimumTravelHeading from the previous scan, the "
2166  "mapper will use the data from the new scan. Otherwise, it will "
2167  "discard the new scan if it also does not meet the minimum travel "
2168  "distance requirement. For performance reasons, generally it is a good "
2169  "idea to only process scans if the robot has moved a reasonable "
2170  "amount.",
2172 
2174  "ScanBufferSize",
2175  "Scan buffer size is the length of the scan chain stored for scan "
2176  "matching. \"ScanBufferSize\" should be set to approximately "
2177  "\"ScanBufferMaximumScanDistance\" / \"MinimumTravelDistance\". The "
2178  "idea is to get an area approximately 20 meters long for scan "
2179  "matching. For example, if we add scans every MinimumTravelDistance == "
2180  "0.3 meters, then \"scanBufferSize\" should be 20 / 0.3 = 67.)",
2181  70, GetParameterManager());
2182 
2184  "ScanBufferMaximumScanDistance",
2185  "Scan buffer maximum scan distance is the maximum distance between the "
2186  "first and last scans in the scan chain stored for matching.",
2187  20.0, GetParameterManager());
2188 
2190  "LinkMatchMinimumResponseFine",
2191  "Scans are linked only if the correlation response value is greater "
2192  "than this value.",
2193  0.8, GetParameterManager());
2194 
2196  "LinkScanMaximumDistance",
2197  "Maximum distance between linked scans. Scans that are farther apart "
2198  "will not be linked regardless of the correlation response value.",
2199  10.0, GetParameterManager());
2200 
2202  "LoopSearchMaximumDistance",
2203  "Scans less than this distance from the current position will be "
2204  "considered for a match in loop closure.",
2205  4.0, GetParameterManager());
2206 
2208  "DoLoopClosing",
2209  "Enable/disable loop closure.",
2210  true, GetParameterManager());
2211 
2213  "LoopMatchMinimumChainSize",
2214  "When the loop closure detection finds a candidate it must be part of "
2215  "a large set of linked scans. If the chain of scans is less than this "
2216  "value we do not attempt to close the loop.",
2217  10, GetParameterManager());
2218 
2220  "LoopMatchMaximumVarianceCoarse",
2221  "The co-variance values for a possible loop closure have to be less "
2222  "than this value to consider a viable solution. This applies to the "
2223  "coarse search.",
2225 
2227  "LoopMatchMinimumResponseCoarse",
2228  "If response is larger then this, then initiate loop closure search at "
2229  "the coarse resolution.",
2230  0.8, GetParameterManager());
2231 
2233  "LoopMatchMinimumResponseFine",
2234  "If response is larger then this, then initiate loop closure search at "
2235  "the fine resolution.",
2236  0.8, GetParameterManager());
2237 
2239  // CorrelationParameters correlationParameters;
2240 
2242  "CorrelationSearchSpaceDimension",
2243  "The size of the search grid used by the matcher. The search grid will "
2244  "have the size CorrelationSearchSpaceDimension * "
2245  "CorrelationSearchSpaceDimension",
2246  0.3, GetParameterManager());
2247 
2249  "CorrelationSearchSpaceResolution",
2250  "The resolution (size of a grid cell) of the correlation grid.",
2251  0.01, GetParameterManager());
2252 
2254  "CorrelationSearchSpaceSmearDeviation",
2255  "The point readings are smeared by this value in X and Y to create a "
2256  "smoother response.",
2257  0.03, GetParameterManager());
2258 
2259 
2261  // CorrelationParameters loopCorrelationParameters;
2262 
2264  "LoopSearchSpaceDimension",
2265  "The size of the search grid used by the matcher.",
2266  8.0, GetParameterManager());
2267 
2269  "LoopSearchSpaceResolution",
2270  "The resolution (size of a grid cell) of the correlation grid.",
2271  0.05, GetParameterManager());
2272 
2274  "LoopSearchSpaceSmearDeviation",
2275  "The point readings are smeared by this value in X and Y to create a "
2276  "smoother response.",
2277  0.03, GetParameterManager());
2278 
2280  // ScanMatcherParameters;
2281 
2283  "DistanceVariancePenalty",
2284  "Variance of penalty for deviating from odometry when scan-matching. "
2285  "The penalty is a multiplier (less than 1.0) is a function of the "
2286  "delta of the scan position being tested and the odometric pose.",
2288 
2290  "AngleVariancePenalty",
2291  "See DistanceVariancePenalty.",
2293 
2295  "FineSearchAngleOffset",
2296  "The range of angles to search during a fine search.",
2298 
2300  "CoarseSearchAngleOffset",
2301  "The range of angles to search during a coarse search.",
2303 
2305  "CoarseAngleResolution",
2306  "Resolution of angles to search during a coarse search.",
2308 
2310  "MinimumAnglePenalty",
2311  "Minimum value of the angle penalty multiplier so scores do not become "
2312  "too small.",
2313  0.9, GetParameterManager());
2314 
2316  "MinimumDistancePenalty",
2317  "Minimum value of the distance penalty multiplier so scores do not "
2318  "become too small.",
2319  0.5, GetParameterManager());
2320 
2322  "UseResponseExpansion",
2323  "Whether to increase the search space if no good matches are initially "
2324  "found.",
2325  false, GetParameterManager());
2326  }
2327  /* Adding in getters and setters here for easy parameter access */
2328 
2329  // General Parameters
2330 
2332  {
2333  return static_cast<bool>(m_pUseScanMatching->GetValue());
2334  }
2335 
2337  {
2338  return static_cast<bool>(m_pUseScanBarycenter->GetValue());
2339  }
2340 
2342  {
2343  return static_cast<double>(m_pMinimumTimeInterval->GetValue());
2344  }
2345 
2347  {
2348  return static_cast<double>(m_pMinimumTravelDistance->GetValue());
2349  }
2350 
2352  {
2353  return math::RadiansToDegrees(static_cast<double>(m_pMinimumTravelHeading->GetValue()));
2354  }
2355 
2357  {
2358  return static_cast<int>(m_pScanBufferSize->GetValue());
2359  }
2360 
2362  {
2363  return static_cast<double>(m_pScanBufferMaximumScanDistance->GetValue());
2364  }
2365 
2367  {
2368  return static_cast<double>(m_pLinkMatchMinimumResponseFine->GetValue());
2369  }
2370 
2372  {
2373  return static_cast<double>(m_pLinkScanMaximumDistance->GetValue());
2374  }
2375 
2377  {
2378  return static_cast<double>(m_pLoopSearchMaximumDistance->GetValue());
2379  }
2380 
2382  {
2383  return static_cast<bool>(m_pDoLoopClosing->GetValue());
2384  }
2385 
2387  {
2388  return static_cast<int>(m_pLoopMatchMinimumChainSize->GetValue());
2389  }
2390 
2392  {
2393  return static_cast<double>(std::sqrt(m_pLoopMatchMaximumVarianceCoarse->GetValue()));
2394  }
2395 
2397  {
2398  return static_cast<double>(m_pLoopMatchMinimumResponseCoarse->GetValue());
2399  }
2400 
2402  {
2403  return static_cast<double>(m_pLoopMatchMinimumResponseFine->GetValue());
2404  }
2405 
2406  // Correlation Parameters - Correlation Parameters
2407 
2409  {
2410  return static_cast<double>(m_pCorrelationSearchSpaceDimension->GetValue());
2411  }
2412 
2414  {
2415  return static_cast<double>(m_pCorrelationSearchSpaceResolution->GetValue());
2416  }
2417 
2419  {
2420  return static_cast<double>(m_pCorrelationSearchSpaceSmearDeviation->GetValue());
2421  }
2422 
2423  // Correlation Parameters - Loop Correlation Parameters
2424 
2426  {
2427  return static_cast<double>(m_pLoopSearchSpaceDimension->GetValue());
2428  }
2429 
2431  {
2432  return static_cast<double>(m_pLoopSearchSpaceResolution->GetValue());
2433  }
2434 
2436  {
2437  return static_cast<double>(m_pLoopSearchSpaceSmearDeviation->GetValue());
2438  }
2439 
2440  // ScanMatcher Parameters
2441 
2443  {
2444  return std::sqrt(static_cast<double>(m_pDistanceVariancePenalty->GetValue()));
2445  }
2446 
2448  {
2449  return std::sqrt(static_cast<double>(m_pAngleVariancePenalty->GetValue()));
2450  }
2451 
2453  {
2454  return static_cast<double>(m_pFineSearchAngleOffset->GetValue());
2455  }
2456 
2458  {
2459  return static_cast<double>(m_pCoarseSearchAngleOffset->GetValue());
2460  }
2461 
2463  {
2464  return static_cast<double>(m_pCoarseAngleResolution->GetValue());
2465  }
2466 
2468  {
2469  return static_cast<double>(m_pMinimumAnglePenalty->GetValue());
2470  }
2471 
2473  {
2474  return static_cast<double>(m_pMinimumDistancePenalty->GetValue());
2475  }
2476 
2478  {
2479  return static_cast<bool>(m_pUseResponseExpansion->GetValue());
2480  }
2481 
2482  /* Setters for parameters */
2483  // General Parameters
2485  {
2487  }
2488 
2490  {
2492  }
2493 
2495  {
2497  }
2498 
2500  {
2502  }
2503 
2505  {
2507  }
2508 
2510  {
2512  }
2513 
2515  {
2517  }
2518 
2520  {
2522  }
2523 
2525  {
2527  }
2528 
2530  {
2532  }
2533 
2535  {
2537  }
2538 
2540  {
2542  }
2543 
2545  {
2547  }
2548 
2550  {
2552  }
2553 
2555  {
2557  }
2558 
2559  // Correlation Parameters - Correlation Parameters
2561  {
2563  }
2564 
2566  {
2568  }
2569 
2571  {
2573  }
2574 
2575 
2576  // Correlation Parameters - Loop Closure Parameters
2578  {
2580  }
2581 
2583  {
2585  }
2586 
2588  {
2590  }
2591 
2592 
2593  // Scan Matcher Parameters
2595  {
2597  }
2598 
2600  {
2602  }
2603 
2605  {
2607  }
2608 
2610  {
2612  }
2613 
2615  {
2617  }
2618 
2620  {
2622  }
2623 
2625  {
2627  }
2628 
2630  {
2632  }
2633 
2634 
2635 
2636  void Mapper::Initialize(kt_double rangeThreshold)
2637  {
2638  if (m_Initialized)
2639  {
2640  return;
2641  }
2642  // create sequential scan and loop matcher, update if deserialized
2643 
2645  delete m_pSequentialScanMatcher;
2646  }
2651  rangeThreshold);
2652  assert(m_pSequentialScanMatcher);
2653 
2654  if (m_Deserialized) {
2657 
2658  m_pGraph->UpdateLoopScanMatcher(rangeThreshold);
2659  } else {
2662 
2663  m_pGraph = new MapperGraph(this, rangeThreshold);
2664  }
2665 
2666  m_Initialized = true;
2667  }
2668 
2669  void Mapper::SaveToFile(const std::string& filename)
2670  {
2671  printf("Save To File %s \n", filename.c_str());
2672  std::ofstream ofs(filename.c_str());
2673  boost::archive::binary_oarchive oa(ofs, boost::archive::no_codecvt);
2674  oa << BOOST_SERIALIZATION_NVP(*this);
2675  }
2676 
2677  void Mapper::LoadFromFile(const std::string& filename)
2678  {
2679  printf("Load From File %s \n", filename.c_str());
2680  std::ifstream ifs(filename.c_str());
2681  boost::archive::binary_iarchive ia(ifs, boost::archive::no_codecvt);
2682  ia >> BOOST_SERIALIZATION_NVP(*this);
2683  m_Deserialized = true;
2684  m_Initialized = false;
2685  }
2686 
2688  {
2690  {
2691  delete m_pSequentialScanMatcher;
2693  }
2694  if (m_pGraph)
2695  {
2696  delete m_pGraph;
2697  m_pGraph = NULL;
2698  }
2700  {
2701  delete m_pMapperSensorManager;
2703  }
2704  m_Initialized = false;
2705  m_Deserialized = false;
2706  while (!m_LocalizationScanVertices.empty())
2707  {
2709  }
2710  }
2711 
2713  {
2714  return true;
2715  }
2716 
2718  {
2719  if (pScan != NULL)
2720  {
2721  karto::LaserRangeFinder* pLaserRangeFinder = pScan->GetLaserRangeFinder();
2722 
2723  // validate scan
2724  if (pLaserRangeFinder == NULL || pScan == NULL || pLaserRangeFinder->Validate(pScan) == false)
2725  {
2726  return false;
2727  }
2728 
2729  if (m_Initialized == false)
2730  {
2731  // initialize mapper with range threshold from device
2732  Initialize(pLaserRangeFinder->GetRangeThreshold());
2733  }
2734 
2735  // get last scan
2737 
2738  // update scans corrected pose based on last correction
2739  if (pLastScan != NULL)
2740  {
2741  Transform lastTransform(pLastScan->GetOdometricPose(), pLastScan->GetCorrectedPose());
2742  pScan->SetCorrectedPose(lastTransform.TransformPose(pScan->GetOdometricPose()));
2743  }
2744 
2745  // test if scan is outside minimum boundary or if heading is larger then minimum heading
2746  if (!HasMovedEnough(pScan, pLastScan))
2747  {
2748  return false;
2749  }
2750 
2751  Matrix3 covariance;
2752  covariance.SetToIdentity();
2753 
2754  // correct scan (if not first scan)
2755  if (m_pUseScanMatching->GetValue() && pLastScan != NULL)
2756  {
2757  Pose2 bestPose;
2760  bestPose,
2761  covariance);
2762  pScan->SetSensorPose(bestPose);
2763  }
2764 
2765  // add scan to buffer and assign id
2767 
2769  {
2770  // add to graph
2771  m_pGraph->AddVertex(pScan);
2772  m_pGraph->AddEdges(pScan, covariance);
2773 
2775 
2776  if (m_pDoLoopClosing->GetValue())
2777  {
2778  std::vector<Name> deviceNames = m_pMapperSensorManager->GetSensorNames();
2779  const_forEach(std::vector<Name>, &deviceNames)
2780  {
2781  m_pGraph->TryCloseLoop(pScan, *iter);
2782  }
2783  }
2784  }
2785 
2787 
2788  return true;
2789  }
2790 
2791  return false;
2792  }
2793 
2795  {
2796  if (pScan != NULL)
2797  {
2798  karto::LaserRangeFinder* pLaserRangeFinder = pScan->GetLaserRangeFinder();
2799 
2800  // validate scan
2801  if (pLaserRangeFinder == NULL || pScan == NULL ||
2802  pLaserRangeFinder->Validate(pScan) == false)
2803  {
2804  return false;
2805  }
2806 
2807  if (m_Initialized == false)
2808  {
2809  // initialize mapper with range threshold from device
2810  Initialize(pLaserRangeFinder->GetRangeThreshold());
2811  }
2812 
2814  pScan->GetSensorName(), pScan->GetOdometricPose());
2815  LocalizedRangeScan* pLastScan = NULL;
2816  if (closetVertex)
2817  {
2818  pLastScan = m_pMapperSensorManager->GetScan(pScan->GetSensorName(),
2819  closetVertex->GetObject()->GetStateId());
2822  m_pMapperSensorManager->SetLastScan(pLastScan);
2823  }
2824 
2825  Matrix3 covariance;
2826  covariance.SetToIdentity();
2827 
2828  // correct scan (if not first scan)
2829  if (m_pUseScanMatching->GetValue() && pLastScan != NULL)
2830  {
2831  Pose2 bestPose;
2834  bestPose,
2835  covariance);
2836  pScan->SetSensorPose(bestPose);
2837  }
2838 
2839  pScan->SetOdometricPose(pScan->GetCorrectedPose());
2840 
2841  // add scan to buffer and assign id
2843 
2844  Vertex<LocalizedRangeScan>* scan_vertex = NULL;
2846  {
2847  scan_vertex = m_pGraph->AddVertex(pScan);
2848  // add to graph
2849  m_pGraph->AddVertex(pScan);
2850  m_pGraph->AddEdges(pScan, covariance);
2851 
2853 
2854  if (m_pDoLoopClosing->GetValue())
2855  {
2856  std::vector<Name> deviceNames =
2858  const_forEach(std::vector<Name>, &deviceNames)
2859  {
2860  m_pGraph->TryCloseLoop(pScan, *iter);
2861  }
2862  }
2863  }
2864 
2866 
2867  if (addScanToLocalizationBuffer)
2868  {
2869  AddScanToLocalizationBuffer(pScan, scan_vertex);
2870  }
2871 
2872  return true;
2873  }
2874 
2875  return false;
2876  }
2877 
2879  {
2880  if (pScan == NULL)
2881  {
2882  return false;
2883  }
2884 
2885  karto::LaserRangeFinder* pLaserRangeFinder = pScan->GetLaserRangeFinder();
2886 
2887  // validate scan
2888  if (pLaserRangeFinder == NULL || pScan == NULL ||
2889  pLaserRangeFinder->Validate(pScan) == false)
2890  {
2891  return false;
2892  }
2893 
2894  if (m_Initialized == false)
2895  {
2896  // initialize mapper with range threshold from device
2897  Initialize(pLaserRangeFinder->GetRangeThreshold());
2898  }
2899 
2900  // get last scan
2902  pScan->GetSensorName());
2903 
2904  // update scans corrected pose based on last correction
2905  if (pLastScan != NULL)
2906  {
2907  Transform lastTransform(pLastScan->GetOdometricPose(),
2908  pLastScan->GetCorrectedPose());
2909  pScan->SetCorrectedPose(lastTransform.TransformPose(
2910  pScan->GetOdometricPose()));
2911  }
2912 
2913  // test if scan is outside minimum boundary
2914  // or if heading is larger then minimum heading
2915  if (!HasMovedEnough(pScan, pLastScan))
2916  {
2917  return false;
2918  }
2919 
2920  Matrix3 covariance;
2921  covariance.SetToIdentity();
2922 
2923  // correct scan (if not first scan)
2924  if (m_pUseScanMatching->GetValue() && pLastScan != NULL)
2925  {
2926  Pose2 bestPose;
2929  bestPose,
2930  covariance);
2931  pScan->SetSensorPose(bestPose);
2932  }
2933 
2934  // add scan to buffer and assign id
2936 
2937  Vertex<LocalizedRangeScan>* scan_vertex = NULL;
2939  {
2940  // add to graph
2941  scan_vertex = m_pGraph->AddVertex(pScan);
2942  m_pGraph->AddEdges(pScan, covariance);
2943 
2945 
2946  if (m_pDoLoopClosing->GetValue())
2947  {
2948  std::vector<Name> deviceNames = m_pMapperSensorManager->GetSensorNames();
2949  const_forEach(std::vector<Name>, &deviceNames)
2950  {
2951  m_pGraph->TryCloseLoop(pScan, *iter);
2952  }
2953  }
2954  }
2955 
2957  AddScanToLocalizationBuffer(pScan, scan_vertex);
2958 
2959  return true;
2960  }
2961 
2963  {
2964 
2965  // generate the info to store and later decay, outside of dataset
2967  lsv.scan = pScan;
2968  lsv.vertex = scan_vertex;
2969  m_LocalizationScanVertices.push(lsv);
2970 
2972  {
2974  RemoveNodeFromGraph(oldLSV.vertex);
2975 
2976  // delete node and scans
2977  // free hat!
2978  // No need to delete from m_scans as those pointers will be freed memory
2979  oldLSV.vertex->RemoveObject();
2981  if (oldLSV.scan)
2982  {
2983  delete oldLSV.scan;
2984  oldLSV.scan = NULL;
2985  }
2986 
2988  }
2989  }
2990 
2992  {
2993  while (!m_LocalizationScanVertices.empty())
2994  {
2996  RemoveNodeFromGraph(oldLSV.vertex);
2997  oldLSV.vertex->RemoveObject();
2999  if (oldLSV.scan)
3000  {
3001  delete oldLSV.scan;
3002  oldLSV.scan = NULL;
3003  }
3004 
3006  }
3007 
3008  std::vector<Name> names = m_pMapperSensorManager->GetSensorNames();
3009  for (uint i = 0; i != names.size(); i++)
3010  {
3013  }
3014 
3015  return;
3016  }
3017 
3019  {
3020  // 1) delete edges in adjacent vertices, graph, and optimizer
3021  std::vector<Vertex<LocalizedRangeScan>*> adjVerts =
3022  vertex_to_remove->GetAdjacentVertices();
3023  for (int i = 0; i != adjVerts.size(); i++)
3024  {
3025  std::vector<Edge<LocalizedRangeScan>*> adjEdges = adjVerts[i]->GetEdges();
3026  bool found = false;
3027  for (int j=0; j!=adjEdges.size(); j++)
3028  {
3029  if (adjEdges[j]->GetTarget() == vertex_to_remove ||
3030  adjEdges[j]->GetSource() == vertex_to_remove)
3031  {
3032  adjVerts[i]->RemoveEdge(j);
3034  adjEdges[j]->GetSource()->GetObject()->GetUniqueId(),
3035  adjEdges[j]->GetTarget()->GetObject()->GetUniqueId());
3036  std::vector<Edge<LocalizedRangeScan>*> edges = m_pGraph->GetEdges();
3037  std::vector<Edge<LocalizedRangeScan>*>::iterator edgeGraphIt =
3038  std::find(edges.begin(), edges.end(), adjEdges[j]);
3039 
3040  if (edgeGraphIt == edges.end())
3041  {
3042  std::cout << "Edge not found in graph to remove!" << std::endl;
3043  continue;
3044  }
3045 
3046  int posEdge = edgeGraphIt - edges.begin();
3047  m_pGraph->RemoveEdge(posEdge); // remove from graph
3048  delete *edgeGraphIt; // free hat!
3049  *edgeGraphIt = NULL;
3050  found = true;
3051  }
3052  }
3053  if (!found)
3054  {
3055  std::cout << "Failed to find any edge in adj. vertex" <<
3056  " with a matching vertex to current!" << std::endl;
3057  }
3058  }
3059 
3060  // 2) delete vertex from optimizer
3061  m_pScanOptimizer->RemoveNode(vertex_to_remove->GetObject()->GetUniqueId());
3062 
3063  // 3) delete from vertex map
3064  std::map<Name, std::map<int, Vertex<LocalizedRangeScan>*> >
3065  vertexMap = m_pGraph->GetVertices();
3066  std::map<int, Vertex<LocalizedRangeScan>*> graphVertices =
3067  vertexMap[vertex_to_remove->GetObject()->GetSensorName()];
3068  std::map<int, Vertex<LocalizedRangeScan>*>::iterator
3069  vertexGraphIt = graphVertices.find(vertex_to_remove->GetObject()->GetStateId());
3070  if (vertexGraphIt != graphVertices.end())
3071  {
3072  m_pGraph->RemoveVertex(vertex_to_remove->GetObject()->GetSensorName(),
3073  vertexGraphIt->second->GetObject()->GetStateId());
3074  }
3075  else
3076  {
3077  std::cout << "Vertex not found in graph to remove!" << std::endl;
3078  return false;
3079  }
3080 
3081  return true;
3082  }
3083 
3085  const int& nodeId)
3086  {
3087  if (pScan != NULL)
3088  {
3089  karto::LaserRangeFinder* pLaserRangeFinder = pScan->GetLaserRangeFinder();
3090 
3091  // validate scan
3092  if (pLaserRangeFinder == NULL || pScan == NULL ||
3093  pLaserRangeFinder->Validate(pScan) == false)
3094  {
3095  return false;
3096  }
3097 
3098  if (m_Initialized == false)
3099  {
3100  // initialize mapper with range threshold from device
3101  Initialize(pLaserRangeFinder->GetRangeThreshold());
3102  }
3103 
3104  // If we're matching against a node from an older mapping session
3105  // lets get the first scan as the last scan and populate running scans
3106  // with the first few from that run as well.
3107  LocalizedRangeScan* pLastScan =
3108  m_pMapperSensorManager->GetScan(pScan->GetSensorName(), nodeId);
3111  m_pMapperSensorManager->SetLastScan(pLastScan);
3112 
3113  Matrix3 covariance;
3114  covariance.SetToIdentity();
3115 
3116  // correct scan (if not first scan)
3117  if (m_pUseScanMatching->GetValue() && pLastScan != NULL)
3118  {
3119  Pose2 bestPose;
3122  bestPose,
3123  covariance);
3124  pScan->SetSensorPose(bestPose);
3125  }
3126 
3127  pScan->SetOdometricPose(pScan->GetCorrectedPose());
3128 
3129  // add scan to buffer and assign id
3131 
3133  {
3134  // add to graph
3135  m_pGraph->AddVertex(pScan);
3136  m_pGraph->AddEdges(pScan, covariance);
3137 
3139 
3140  if (m_pDoLoopClosing->GetValue())
3141  {
3142  std::vector<Name> deviceNames =
3144  const_forEach(std::vector<Name>, &deviceNames)
3145  {
3146  m_pGraph->TryCloseLoop(pScan, *iter);
3147  }
3148  }
3149  }
3150 
3152 
3153  return true;
3154  }
3155 
3156  return false;
3157  }
3158 
3160  {
3161  // Special case of processing against node where node is the starting point
3162  return ProcessAgainstNode(pScan, 0);
3163  }
3164 
3172  {
3173  // test if first scan
3174  if (pLastScan == NULL)
3175  {
3176  return true;
3177  }
3178 
3179  // test if enough time has passed
3180  kt_double timeInterval = pScan->GetTime() - pLastScan->GetTime();
3181  if (timeInterval >= m_pMinimumTimeInterval->GetValue())
3182  {
3183  return true;
3184  }
3185 
3186  Pose2 lastScannerPose = pLastScan->GetSensorAt(pLastScan->GetOdometricPose());
3187  Pose2 scannerPose = pScan->GetSensorAt(pScan->GetOdometricPose());
3188 
3189  // test if we have turned enough
3190  kt_double deltaHeading = math::NormalizeAngle(scannerPose.GetHeading() - lastScannerPose.GetHeading());
3191  if (fabs(deltaHeading) >= m_pMinimumTravelHeading->GetValue())
3192  {
3193  return true;
3194  }
3195 
3196  // test if we have moved enough
3197  kt_double squaredTravelDistance = lastScannerPose.GetPosition().SquaredDistance(scannerPose.GetPosition());
3198  if (squaredTravelDistance >= math::Square(m_pMinimumTravelDistance->GetValue()) - KT_TOLERANCE)
3199  {
3200  return true;
3201  }
3202 
3203  return false;
3204  }
3205 
3211  {
3212  LocalizedRangeScanVector allScans;
3213 
3215  {
3216  allScans = m_pMapperSensorManager->GetAllScans();
3217  }
3218 
3219  return allScans;
3220  }
3221 
3227  {
3228  m_Listeners.push_back(pListener);
3229  }
3230 
3236  {
3237  std::vector<MapperListener*>::iterator iter = std::find(m_Listeners.begin(), m_Listeners.end(), pListener);
3238  if (iter != m_Listeners.end())
3239  {
3240  m_Listeners.erase(iter);
3241  }
3242  }
3243 
3244  void Mapper::FireInfo(const std::string& rInfo) const
3245  {
3246  const_forEach(std::vector<MapperListener*>, &m_Listeners)
3247  {
3248  (*iter)->Info(rInfo);
3249  }
3250  }
3251 
3252  void Mapper::FireDebug(const std::string& rInfo) const
3253  {
3254  const_forEach(std::vector<MapperListener*>, &m_Listeners)
3255  {
3256  MapperDebugListener* pListener = dynamic_cast<MapperDebugListener*>(*iter);
3257 
3258  if (pListener != NULL)
3259  {
3260  pListener->Debug(rInfo);
3261  }
3262  }
3263  }
3264 
3265  void Mapper::FireLoopClosureCheck(const std::string& rInfo) const
3266  {
3267  const_forEach(std::vector<MapperListener*>, &m_Listeners)
3268  {
3269  MapperLoopClosureListener* pListener = dynamic_cast<MapperLoopClosureListener*>(*iter);
3270 
3271  if (pListener != NULL)
3272  {
3273  pListener->LoopClosureCheck(rInfo);
3274  }
3275  }
3276  }
3277 
3278  void Mapper::FireBeginLoopClosure(const std::string& rInfo) const
3279  {
3280  const_forEach(std::vector<MapperListener*>, &m_Listeners)
3281  {
3282  MapperLoopClosureListener* pListener = dynamic_cast<MapperLoopClosureListener*>(*iter);
3283 
3284  if (pListener != NULL)
3285  {
3286  pListener->BeginLoopClosure(rInfo);
3287  }
3288  }
3289  }
3290 
3291  void Mapper::FireEndLoopClosure(const std::string& rInfo) const
3292  {
3293  const_forEach(std::vector<MapperListener*>, &m_Listeners)
3294  {
3295  MapperLoopClosureListener* pListener = dynamic_cast<MapperLoopClosureListener*>(*iter);
3296 
3297  if (pListener != NULL)
3298  {
3299  pListener->EndLoopClosure(rInfo);
3300  }
3301  }
3302  }
3303 
3304  void Mapper::SetScanSolver(ScanSolver* pScanOptimizer)
3305  {
3306  m_pScanOptimizer = pScanOptimizer;
3307  }
3308 
3310  {
3311  return m_pScanOptimizer;
3312  }
3313 
3315  {
3316  return m_pGraph;
3317  }
3318 
3320  {
3321  return m_pSequentialScanMatcher;
3322  }
3323 
3325  {
3326  return m_pGraph->GetLoopScanMatcher();
3327  }
3328 } // namespace karto
std::vector< LocalizedRangeScanVector > FindNearChains(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:1722
virtual kt_bool Process(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:2717
std::map< Name, ScanManager * > ScanManagerMap
Definition: Mapper.h:1540
T GetHeight() const
Definition: Karto.h:1923
void InitializeParameters()
Definition: Mapper.cpp:2120
void RemoveScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:203
LaserRangeFinder * GetLaserRangeFinder() const
Definition: Karto.h:5395
#define NULL
virtual std::vector< Vertex< T > * > TraverseForVertices(Vertex< T > *pStartVertex, Visitor< T > *pVisitor)
Definition: Mapper.cpp:1295
ScanMatcher * m_pSequentialScanMatcher
Definition: Mapper.h:2145
void RemoveListener(MapperListener *pListener)
Definition: Mapper.cpp:3235
virtual kt_bool Visit(Vertex< LocalizedRangeScan > *pVertex)
Definition: Mapper.cpp:1400
double getParamMinimumAnglePenalty()
Definition: Mapper.cpp:2467
double getParamLinkScanMaximumDistance()
Definition: Mapper.cpp:2371
#define DISTANCE_PENALTY_GAIN
Definition: Mapper.cpp:47
bool getParamDoLoopClosing()
Definition: Mapper.cpp:2381
int32_t kt_int32s
Definition: Types.h:51
virtual kt_bool Validate()
Definition: Karto.h:4150
void setParamCorrelationSearchSpaceResolution(double d)
Definition: Mapper.cpp:2565
void FireEndLoopClosure(const std::string &rInfo) const
Definition: Mapper.cpp:3291
void setParamLoopMatchMinimumChainSize(int i)
Definition: Mapper.cpp:2539
Matrix3 Inverse() const
Definition: Karto.h:2543
const kt_int32s INVALID_SCAN
Definition: Math.h:47
Parameter< kt_double > * m_pLinkScanMaximumDistance
Definition: Mapper.h:2232
kt_double Round(kt_double value)
Definition: Math.h:87
void LinkNearChains(LocalizedRangeScan *pScan, Pose2Vector &rMeans, std::vector< Matrix3 > &rCovariances)
Definition: Mapper.cpp:1682
virtual void AddNode(Vertex< LocalizedRangeScan > *)
Definition: Mapper.h:984
void SetUniqueId(kt_int32u uniqueId)
Definition: Karto.h:5170
Parameter< kt_double > * m_pCoarseAngleResolution
Definition: Mapper.h:2331
Pose2 GetSensorPose() const
Definition: Karto.h:5632
kt_int32s GetStateId() const
Definition: Karto.h:5143
virtual ScanMatcher * GetLoopScanMatcher() const
Definition: Mapper.cpp:3324
NearScanVisitor(LocalizedRangeScan *pScan, kt_double maxDistance, kt_bool useScanBarycenter)
Definition: Mapper.cpp:1347
const Pose2 & GetOdometricPose() const
Definition: Karto.h:5538
Parameter< kt_double > * m_pLoopMatchMaximumVarianceCoarse
Definition: Mapper.h:2260
std::vector< Vector2< kt_double > > PointVectorDouble
Definition: Karto.h:1281
Parameter< kt_double > * m_pMinimumTravelHeading
Definition: Mapper.h:2202
virtual void EndLoopClosure(const std::string &)
Definition: Mapper.h:96
void SetValue(const T &rValue)
Definition: Karto.h:3280
void setParamUseScanMatching(bool b)
Definition: Mapper.cpp:2484
void AddEdge(Edge< T > *pEdge)
Definition: Mapper.h:620
kt_bool ProcessAgainstNode(LocalizedRangeScan *pScan, const int &nodeId)
Definition: Mapper.cpp:3084
int getParamLoopMatchMinimumChainSize()
Definition: Mapper.cpp:2386
void ComputeAngularCovariance(const Pose2 &rBestPose, kt_double bestResponse, const Pose2 &rSearchCenter, kt_double searchAngleOffset, kt_double searchAngleResolution, Matrix3 &rCovariance)
Definition: Mapper.cpp:999
Parameter< kt_double > * m_pMinimumAnglePenalty
Definition: Mapper.h:2335
std::vector< MapperListener * > m_Listeners
Definition: Mapper.h:2154
virtual void Clear()
Definition: Mapper.h:1012
double getParamCoarseSearchAngleOffset()
Definition: Mapper.cpp:2457
void SetRunningScanBufferMaximumDistance(const kt_int32u &rScanBufferMaxDistance)
Definition: Mapper.cpp:167
void FireBeginLoopClosure(const std::string &rInfo) const
Definition: Mapper.cpp:3278
kt_bool m_UseScanBarycenter
Definition: Mapper.cpp:1374
kt_int32s * GetArrayPointer()
Definition: Karto.h:6836
virtual void RemoveNode(kt_int32s)
Definition: Mapper.h:991
const Pose2 & GetCorrectedPose() const
Definition: Karto.h:5560
kt_int32u GetNumberOfRangeReadings() const
Definition: Karto.h:5404
const Vector2< kt_double > & GetPosition() const
Definition: Karto.h:2133
void SetRunningScanBufferSize(const kt_int32u &rScanBufferSize)
Definition: Mapper.cpp:158
void ClearLocalizationBuffer()
Definition: Mapper.cpp:2991
uint8_t kt_int8u
Definition: Types.h:46
const T & Maximum(const T &value1, const T &value2)
Definition: Math.h:111
virtual void RemoveConstraint(kt_int32s, kt_int32s)
Definition: Mapper.h:1005
kt_double DegreesToRadians(kt_double degrees)
Definition: Math.h:56
double getParamCoarseAngleResolution()
Definition: Mapper.cpp:2462
friend class MapperGraph
Definition: Mapper.h:1929
std::map< Name, std::map< int, Vertex< LocalizedRangeScan > *> > VertexMap
Definition: Mapper.h:567
std::vector< Name > GetSensorNames()
Definition: Mapper.h:1584
Vertex< LocalizedRangeScan > * vertex
Definition: Mapper.h:1922
double getParamMinimumDistancePenalty()
Definition: Mapper.cpp:2472
void ClearRunningScans()
Definition: Mapper.cpp:220
virtual void LoopClosureCheck(const std::string &)
Definition: Mapper.h:86
void SetX(const T &x)
Definition: Karto.h:1035
Parameter< kt_double > * m_pLoopSearchSpaceSmearDeviation
Definition: Mapper.h:2315
kt_int32u GetSize() const
Definition: Karto.h:6782
void setParamDoLoopClosing(bool b)
Definition: Mapper.cpp:2534
const std::vector< Edge< T > * > & GetEdges() const
Definition: Mapper.h:665
virtual kt_bool Visit(Vertex< LocalizedRangeScan > *pVertex)
Definition: Mapper.cpp:1354
const PointVectorDouble & GetPointReadings(kt_bool wantFiltered=false) const
Definition: Karto.h:5708
Parameter< kt_int32u > * m_pLoopMatchMinimumChainSize
Definition: Mapper.h:2253
void LoadFromFile(const std::string &filename)
Definition: Mapper.cpp:2677
void setParamCorrelationSearchSpaceSmearDeviation(double d)
Definition: Mapper.cpp:2570
Parameter< kt_double > * m_pCorrelationSearchSpaceResolution
Definition: Mapper.h:2287
void Initialize(kt_double rangeThreshold)
Definition: Mapper.cpp:2636
double getParamMinimumTimeInterval()
Definition: Mapper.cpp:2341
Parameter< kt_double > * m_pMinimumDistancePenalty
Definition: Mapper.h:2336
LocalizedRangeScanVector FindNearByScans(Name name, const Pose2 refPose, kt_double maxDistance)
Definition: Mapper.cpp:1851
void setParamDistanceVariancePenalty(double d)
Definition: Mapper.cpp:2594
void AddVertex(const Name &rName, Vertex< T > *pVertex)
Definition: Mapper.h:591
void ComputePositionalCovariance(const Pose2 &rBestPose, kt_double bestResponse, const Pose2 &rSearchCenter, const Vector2< kt_double > &rSearchSpaceOffset, const Vector2< kt_double > &rSearchSpaceResolution, kt_double searchAngleResolution, Matrix3 &rCovariance)
Definition: Mapper.cpp:893
virtual void AddConstraint(Edge< LocalizedRangeScan > *)
Definition: Mapper.h:998
Parameter< kt_double > * m_pDistanceVariancePenalty
Definition: Mapper.h:2323
void SetStateId(kt_int32s stateId)
Definition: Karto.h:5152
Parameter< kt_bool > * m_pUseScanMatching
Definition: Mapper.h:2164
Vertex< T > * GetTarget() const
Definition: Mapper.h:448
Pose2 ComputeWeightedMean(const Pose2Vector &rMeans, const std::vector< Matrix3 > &rCovariances) const
Definition: Mapper.cpp:1943
LocalizedRangeScanVector & GetRunningScans(const Name &rSensorName)
Definition: Mapper.cpp:390
#define forEach(listtype, list)
Definition: Macros.h:66
void setParamScanBufferSize(int i)
Definition: Mapper.cpp:2509
void AddScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:339
void setParamCorrelationSearchSpaceDimension(double d)
Definition: Mapper.cpp:2560
void SetSensorPose(const Pose2 &rScanPose)
Definition: Karto.h:5646
LocalizedRangeScan * GetLastScan()
Definition: Mapper.cpp:104
Pose2 GetSensorAt(const Pose2 &rPose) const
Definition: Karto.h:5658
void setParamMinimumTimeInterval(double d)
Definition: Mapper.cpp:2494
kt_double GetResponse(kt_int32u angleIndex, kt_int32s gridPositionIndex) const
Definition: Mapper.cpp:1203
T * GetObject() const
Definition: Mapper.h:319
void SetLastScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:312
kt_double m_MaxDistanceSquared
Definition: Mapper.cpp:1412
LocalizedRangeScanVector m_RunningScans
Definition: Mapper.cpp:249
kt_int32s GetUniqueId() const
Definition: Karto.h:5161
#define ANGLE_PENALTY_GAIN
Definition: Mapper.cpp:48
void LinkChainToScan(const LocalizedRangeScanVector &rChain, LocalizedRangeScan *pScan, const Pose2 &rMean, const Matrix3 &rCovariance)
Definition: Mapper.cpp:1705
void SetToIdentity()
Definition: Karto.h:2465
double getParamLoopMatchMinimumResponseCoarse()
Definition: Mapper.cpp:2396
void LinkScans(LocalizedRangeScan *pFromScan, LocalizedRangeScan *pToScan, const Pose2 &rMean, const Matrix3 &rCovariance)
Definition: Mapper.cpp:1660
MapperSensorManager * m_pMapperSensorManager
Definition: Mapper.h:2147
void SetRunningScanBufferMaximumDistance(kt_double rScanBufferMaxDistance)
Definition: Mapper.cpp:416
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
GraphTraversal< LocalizedRangeScan > * m_pTraversal
Definition: Mapper.h:919
double getParamLoopMatchMinimumResponseFine()
Definition: Mapper.cpp:2401
kt_bool ProcessAgainstNodesNearBy(LocalizedRangeScan *pScan, kt_bool addScanToLocalizationBuffer=false)
Definition: Mapper.cpp:2794
Parameter< kt_bool > * m_pDoLoopClosing
Definition: Mapper.h:2238
virtual kt_bool Visit(Vertex< T > *pVertex)=0
BreadthFirstTraversal(Graph< T > *pGraph)
Definition: Mapper.cpp:1257
virtual ScanMatcher * GetSequentialScanMatcher() const
Definition: Mapper.cpp:3319
void setParamAngleVariancePenalty(double d)
Definition: Mapper.cpp:2599
Parameter< kt_double > * m_pFineSearchAngleOffset
Definition: Mapper.h:2327
std::vector< Vertex< LocalizedRangeScan > * > FindNearByVertices(Name name, const Pose2 refPose, kt_double maxDistance)
Definition: Mapper.cpp:1863
kt_int32u m_RunningBufferMaximumSize
Definition: Mapper.cpp:253
LocalizedRangeScan * GetClosestScanToPose(const LocalizedRangeScanVector &rScans, const Pose2 &rPose) const
Definition: Mapper.cpp:1608
kt_double SquaredLength() const
Definition: Karto.h:1082
kt_double RadiansToDegrees(kt_double radians)
Definition: Math.h:66
Parameter< kt_double > * m_pScanBufferMaximumScanDistance
Definition: Mapper.h:2219
ScanSolver * m_pScanOptimizer
Definition: Mapper.h:2150
LocalizedRangeScan * scan
Definition: Mapper.h:1920
void setParamLoopMatchMaximumVarianceCoarse(double d)
Definition: Mapper.cpp:2544
virtual void Debug(const std::string &)
Definition: Mapper.h:69
kt_int32u & GetRunningScanBufferSize()
Definition: Mapper.cpp:149
void AddListener(MapperListener *pListener)
Definition: Mapper.cpp:3226
void AddScanToLocalizationBuffer(LocalizedRangeScan *pScan, Vertex< LocalizedRangeScan > *scan_vertex)
Definition: Mapper.cpp:2962
Parameter< kt_double > * m_pLoopSearchSpaceDimension
Definition: Mapper.h:2303
void setParamLinkScanMaximumDistance(double d)
Definition: Mapper.cpp:2524
kt_double SquaredDistance(const Vector2 &rOther) const
Definition: Karto.h:1100
void SetLastScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:122
friend class boost::serialization::access
Definition: Mapper.cpp:235
void setParamMinimumAnglePenalty(double d)
Definition: Mapper.cpp:2619
kt_double GetRangeThreshold() const
Definition: Karto.h:3983
virtual MapperGraph * GetGraph() const
Definition: Mapper.cpp:3314
virtual ParameterManager * GetParameterManager()
Definition: Karto.h:677
const Name & GetSensorName() const
Definition: Karto.h:5197
virtual const IdPoseVector & GetCorrections() const =0
void ClearRunningScans(const Name &rSensorName)
Definition: Mapper.cpp:395
double getParamCorrelationSearchSpaceSmearDeviation()
Definition: Mapper.cpp:2418
ScanManager(kt_int32u runningBufferMaximumSize, kt_double runningBufferMaximumDistance)
Definition: Mapper.cpp:63
Parameter< kt_double > * m_pMinimumTravelDistance
Definition: Mapper.h:2192
kt_bool ProcessLocalization(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:2878
void AddRunningScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:350
virtual ~Mapper()
Definition: Mapper.cpp:2113
void AddRunningScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:176
virtual std::vector< T * > TraverseForScans(Vertex< T > *pStartVertex, Visitor< T > *pVisitor)
Definition: Mapper.cpp:1276
RangeReadingsVector GetRangeReadingsVector() const
Definition: Karto.h:5343
Mapper * m_pMapper
Definition: Mapper.h:909
double getParamMinimumTravelHeading()
Definition: Mapper.cpp:2351
void setParamLoopSearchSpaceDimension(double d)
Definition: Mapper.cpp:2577
void setParamLoopSearchSpaceResolution(double d)
Definition: Mapper.cpp:2582
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
static Grid * CreateGrid(kt_int32s width, kt_int32s height, kt_double resolution)
Definition: Karto.h:4653
void setParamScanBufferMaximumScanDistance(double d)
Definition: Mapper.cpp:2514
void setParamMinimumDistancePenalty(double d)
Definition: Mapper.cpp:2624
void serialize(Archive &ar, const unsigned int version)
Definition: Mapper.cpp:1377
kt_double GetX() const
Definition: Karto.h:2097
LocalizedRangeScanVector & GetRunningScans()
Definition: Mapper.cpp:140
double getParamMinimumTravelDistance()
Definition: Mapper.cpp:2346
kt_bool m_UseScanBarycenter
Definition: Mapper.cpp:1413
std::vector< Pose2 > Pose2Vector
Definition: Karto.h:2269
void serialize(Archive &ar, const unsigned int version)
Definition: Mapper.cpp:1334
double getParamLoopSearchSpaceSmearDeviation()
Definition: Mapper.cpp:2435
ScanMatcher * GetLoopScanMatcher() const
Definition: Mapper.h:806
ScanSolver * getScanSolver()
Definition: Mapper.cpp:3309
double getParamFineSearchAngleOffset()
Definition: Mapper.cpp:2452
void setParamLoopSearchMaximumDistance(double d)
Definition: Mapper.cpp:2529
const T & GetValue() const
Definition: Karto.h:3271
void SetRunningScanBufferSize(kt_int32u rScanBufferSize)
Definition: Mapper.cpp:406
T GetWidth() const
Definition: Karto.h:1905
kt_bool ProcessAtDock(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:3159
void setParamLoopMatchMinimumResponseCoarse(double d)
Definition: Mapper.cpp:2549
kt_bool HasMovedEnough(LocalizedRangeScan *pScan, LocalizedRangeScan *pLastScan) const
Definition: Mapper.cpp:3171
void serialize(Archive &ar, const unsigned int version)
Definition: Mapper.cpp:237
void RemoveVertex(const Name &rName, const int &idx)
Definition: Mapper.h:601
PointVectorDouble FindValidPoints(LocalizedRangeScan *pScan, const Vector2< kt_double > &rViewPoint) const
Definition: Mapper.cpp:1140
bool getParamUseScanBarycenter()
Definition: Mapper.cpp:2336
void FireDebug(const std::string &rInfo) const
Definition: Mapper.cpp:3252
kt_bool InRange(const T &value, const T &a, const T &b)
Definition: Math.h:172
void AddScan(LocalizedRangeScan *pScan, kt_int32s uniqueId)
Definition: Mapper.cpp:86
kt_bool m_Deserialized
Definition: Mapper.h:2143
void setParamMinimumTravelDistance(double d)
Definition: Mapper.cpp:2499
const kt_double KT_TOLERANCE
Definition: Math.h:41
kt_double NormalizeAngle(kt_double angle)
Definition: Math.h:182
const T & GetX() const
Definition: Karto.h:1026
LocalizedRangeScan * GetScan(const Name &rSensorName, kt_int32s scanIndex)
Definition: Mapper.cpp:276
bool getParamUseScanMatching()
Definition: Mapper.cpp:2331
#define const_forEach(listtype, list)
Definition: Macros.h:72
LocalizationScanVertices m_LocalizationScanVertices
Definition: Mapper.h:2151
double getParamScanBufferMaximumScanDistance()
Definition: Mapper.cpp:2361
void SetScanSolver(ScanSolver *pSolver)
Definition: Mapper.cpp:3304
virtual void BeginLoopClosure(const std::string &)
Definition: Mapper.h:91
LocalizedRangeScanVector FindPossibleLoopClosure(LocalizedRangeScan *pScan, const Name &rSensorName, kt_int32u &rStartNum)
Definition: Mapper.cpp:1987
int getParamScanBufferSize()
Definition: Mapper.cpp:2356
bool getParamUseResponseExpansion()
Definition: Mapper.cpp:2477
double getParamCorrelationSearchSpaceDimension()
Definition: Mapper.cpp:2408
void SaveToFile(const std::string &filename)
Definition: Mapper.cpp:2669
std::vector< Vertex< T > * > GetAdjacentVertices() const
Definition: Mapper.h:336
GridIndexLookup< kt_int8u > * m_pGridLookup
Definition: Mapper.h:1477
LocalizedRangeScanMap & GetScans(const Name &rSensorName)
Definition: Mapper.cpp:380
Pose2 GetReferencePose(kt_bool useBarycenter) const
Definition: Karto.h:5614
void SetOdometricPose(const Pose2 &rPose)
Definition: Karto.h:5547
virtual ~ScanMatcher()
Definition: Mapper.cpp:468
bool kt_bool
Definition: Types.h:64
static CorrelationGrid * CreateGrid(kt_int32s width, kt_int32s height, kt_double resolution, kt_double smearDeviation)
Definition: Mapper.h:1087
kt_double GetTime() const
Definition: Karto.h:5179
void AddScans(const LocalizedRangeScanVector &rScans, Vector2< kt_double > viewPoint)
Definition: Mapper.cpp:1057
void serialize(Archive &ar, const unsigned int version)
Definition: Mapper.cpp:1416
kt_double NormalizeAngleDifference(kt_double minuend, kt_double subtrahend)
Definition: Math.h:221
const kt_double KT_PI
Definition: Math.h:32
void AddScan(LocalizedRangeScan *pScan, const Vector2< kt_double > &rViewPoint, kt_bool doSmear=true)
Definition: Mapper.cpp:1100
void setParamLinkMatchMinimumResponseFine(double d)
Definition: Mapper.cpp:2519
CorrelationGrid * m_pCorrelationGrid
Definition: Mapper.h:1475
kt_double CorrelateScan(LocalizedRangeScan *pScan, const Pose2 &rSearchCenter, const Vector2< kt_double > &rSearchSpaceOffset, const Vector2< kt_double > &rSearchSpaceResolution, kt_double searchAngleOffset, kt_double searchAngleResolution, kt_bool doPenalize, Pose2 &rMean, Matrix3 &rCovariance, kt_bool doingFineMatch)
Definition: Mapper.cpp:719
Pose2 GetCorrectedAt(const Pose2 &sPose) const
Computes the pose of the robot if the sensor were at the given pose.
Definition: Karto.h:5668
Parameter< kt_double > * m_pLoopSearchSpaceResolution
Definition: Mapper.h:2309
#define MAX_VARIANCE
Definition: Mapper.cpp:46
kt_bool m_Initialized
Definition: Mapper.h:2142
void RemoveEdge(const int &idx)
Definition: Mapper.h:629
void UpdateLoopScanMatcher(kt_double rangeThreshold)
Definition: Mapper.cpp:2064
Parameter< kt_double > * m_pCorrelationSearchSpaceDimension
Definition: Mapper.h:2281
kt_int32u GetRunningScanBufferSize(const Name &rSensorName)
Definition: Mapper.cpp:401
void SetCorrectedPoseAndUpdate(const Pose2 &rPose)
Definition: Karto.h:5580
void setParamCoarseSearchAngleOffset(double d)
Definition: Mapper.cpp:2609
double getParamDistanceVariancePenalty()
Definition: Mapper.cpp:2442
double getParamCorrelationSearchSpaceResolution()
Definition: Mapper.cpp:2413
kt_double MatchScan(LocalizedRangeScan *pScan, const T &rBaseScans, Pose2 &rMean, Matrix3 &rCovariance, kt_bool doPenalize=true, kt_bool doRefineMatch=true)
Definition: Mapper.cpp:544
void RegisterSensor(const Name &rSensorName)
Definition: Mapper.cpp:261
std::vector< std::pair< kt_int32s, Pose2 > > IdPoseVector
Definition: Mapper.h:953
void SetCorrectedPose(const Pose2 &rPose)
Definition: Karto.h:5569
LocalizedRangeScanVector GetAllScans()
Definition: Mapper.cpp:430
void setParamFineSearchAngleOffset(double d)
Definition: Mapper.cpp:2604
void RemoveScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:359
Parameter< kt_double > * m_pLinkMatchMinimumResponseFine
Definition: Mapper.h:2225
Vertex< LocalizedRangeScan > * GetVertex(LocalizedRangeScan *pScan)
Definition: Mapper.h:823
void ClearLastScan()
Definition: Mapper.cpp:113
void FireInfo(const std::string &rInfo) const
Definition: Mapper.cpp:3244
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
void ClearLastScan(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:321
T Square(T value)
Definition: Math.h:77
virtual ~ScanManager()
Definition: Mapper.cpp:76
BOOST_CLASS_EXPORT(karto::MapperGraph)
double getParamAngleVariancePenalty()
Definition: Mapper.cpp:2447
static ScanMatcher * Create(Mapper *pMapper, kt_double searchSize, kt_double resolution, kt_double smearDeviation, kt_double rangeThreshold)
Definition: Mapper.cpp:485
ScanMatcher * m_pLoopScanMatcher
Definition: Mapper.h:914
void SetLabel(EdgeLabel *pLabel)
Definition: Mapper.h:466
Grid< kt_double > * m_pSearchSpaceProbs
Definition: Mapper.h:1476
kt_bool DoubleEqual(kt_double a, kt_double b)
Definition: Math.h:135
Edge< LocalizedRangeScan > * AddEdge(LocalizedRangeScan *pSourceScan, LocalizedRangeScan *pTargetScan, kt_bool &rIsNewEdge)
Definition: Mapper.cpp:1629
void SetHeading(kt_double heading)
Definition: Karto.h:2160
LocalizedRangeScanVector FindNearLinkedScans(LocalizedRangeScan *pScan, kt_double maxDistance)
Definition: Mapper.cpp:1833
double kt_double
Definition: Types.h:67
double getParamLoopSearchSpaceResolution()
Definition: Mapper.cpp:2430
Parameter< kt_double > * m_pCorrelationSearchSpaceSmearDeviation
Definition: Mapper.h:2293
Definition: Karto.h:86
void setParamMinimumTravelHeading(double d)
Definition: Mapper.cpp:2504
const T & GetY() const
Definition: Karto.h:1044
void AddEdges(LocalizedRangeScan *pScan, const Matrix3 &rCovariance)
Definition: Mapper.cpp:1471
double getParamLoopSearchMaximumDistance()
Definition: Mapper.cpp:2376
void setParamUseResponseExpansion(bool b)
Definition: Mapper.cpp:2629
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Vertex< LocalizedRangeScan > * AddVertex(LocalizedRangeScan *pScan)
Definition: Mapper.cpp:1455
virtual void Reset()
Definition: Mapper.cpp:2687
kt_double GetY() const
Definition: Karto.h:2115
virtual void Compute()=0
MapperGraph * m_pGraph
Definition: Mapper.h:2149
Parameter< kt_double > * m_pLoopMatchMinimumResponseCoarse
Definition: Mapper.h:2266
void FireLoopClosureCheck(const std::string &rInfo) const
Definition: Mapper.cpp:3265
double getParamLoopMatchMaximumVarianceCoarse()
Definition: Mapper.cpp:2391
kt_bool TryCloseLoop(LocalizedRangeScan *pScan, const Name &rSensorName)
Definition: Mapper.cpp:1542
LocalizedRangeScan * m_pLastScan
Definition: Mapper.cpp:250
double getParamLinkMatchMinimumResponseFine()
Definition: Mapper.cpp:2366
virtual ~MapperGraph()
Definition: Mapper.cpp:1441
void operator()(const kt_double &y) const
Definition: Mapper.cpp:649
kt_double m_RunningBufferMaximumDistance
Definition: Mapper.cpp:254
const VertexMap & GetVertices() const
Definition: Mapper.h:674
Parameter< kt_double > * m_pCoarseSearchAngleOffset
Definition: Mapper.h:2328
void setParamLoopMatchMinimumResponseFine(double d)
Definition: Mapper.cpp:2554
std::vector< Vertex< LocalizedRangeScan > * > FindNearLinkedVertices(LocalizedRangeScan *pScan, kt_double maxDistance)
Definition: Mapper.cpp:1842
Parameter< kt_double > * m_pLoopSearchMaximumDistance
Definition: Mapper.h:2245
NearPoseVisitor(Pose2 refPose, kt_double maxDistance, kt_bool useScanBarycenter)
Definition: Mapper.cpp:1393
void setParamUseScanBarycenter(bool b)
Definition: Mapper.cpp:2489
Parameter< kt_double > * m_pAngleVariancePenalty
Definition: Mapper.h:2324
void SetY(const T &y)
Definition: Karto.h:1053
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
uint32_t kt_int32u
Definition: Types.h:52
double getParamLoopSearchSpaceDimension()
Definition: Mapper.cpp:2425
LocalizedRangeScanMap m_Scans
Definition: Mapper.cpp:248
LocalizedRangeScanMap & GetScans()
Definition: Mapper.cpp:131
Parameter< kt_double > * m_pMinimumTimeInterval
Definition: Mapper.h:2182
Parameter< kt_bool > * m_pUseResponseExpansion
Definition: Mapper.h:2339
Parameter< kt_int32u > * m_pScanBufferSize
Definition: Mapper.h:2212
virtual const LocalizedRangeScanVector GetAllProcessedScans() const
Definition: Mapper.cpp:3210
kt_bool IsUpTo(const T &value, const T &maximum)
Definition: Math.h:147
const std::string response
LocalizedRangeScan * GetLastScan(const Name &rSensorName)
Definition: Mapper.cpp:301
void setParamLoopSearchSpaceSmearDeviation(double d)
Definition: Mapper.cpp:2587
kt_int32u m_NextStateId
Definition: Mapper.cpp:251
std::vector< LocalizedRangeScan * > LocalizedRangeScanVector
Definition: Karto.h:5877
Parameter< kt_bool > * m_pUseScanBarycenter
Definition: Mapper.h:2169
std::map< int, LocalizedRangeScan * > LocalizedRangeScanMap
Definition: Karto.h:5878
Parameter< kt_double > * m_pLoopMatchMinimumResponseFine
Definition: Mapper.h:2272
void setParamCoarseAngleResolution(double d)
Definition: Mapper.cpp:2614
Vertex< LocalizedRangeScan > * FindNearByScan(Name name, const Pose2 refPose)
Definition: Mapper.cpp:1902
kt_double GetHeading() const
Definition: Karto.h:2151
kt_bool RemoveNodeFromGraph(Vertex< LocalizedRangeScan > *)
Definition: Mapper.cpp:3018
kt_double m_MaxDistanceSquared
Definition: Mapper.cpp:1373


slam_toolbox
Author(s): Steve Macenski
autogenerated on Mon Feb 28 2022 23:46:49