49 #ifdef SYSTEM_YAML_CPP
50 #include "yaml-cpp/yaml.h"
53 #endif // HAVE_YAML_CPP
59 InvalidModuleType::InvalidModuleType(
const std::string& reason):
66 prefilteredReadingPtsCount(0),
67 prefilteredReferencePtsCount(0),
68 maxNumIterationsReached(false)
81 transformations.clear();
82 readingDataPointsFilters.clear();
83 readingStepDataPointsFilters.clear();
84 referenceDataPointsFilters.clear();
86 outlierFilters.clear();
87 errorMinimizer.reset();
88 transformationCheckers.clear();
108 this->matcher = std::make_shared<typename MatchersImpl<T>::KDTreeMatcher>();
109 this->errorMinimizer = std::make_shared<PointToPlaneErrorMinimizer<T> >();
112 this->inspector = std::make_shared<typename InspectorsImpl<T>::NullInspector>();
124 typedef set<string> StringSet;
125 StringSet usedModuleTypes;
134 usedModuleTypes.insert(createModuleFromRegistrar(
"logger", doc, pm.REG(
Logger),
logger));
136 usedModuleTypes.insert(createModulesFromRegistrar(
"readingDataPointsFilters", doc, pm.REG(
DataPointsFilter), readingDataPointsFilters));
137 usedModuleTypes.insert(createModulesFromRegistrar(
"readingStepDataPointsFilters", doc, pm.REG(
DataPointsFilter), readingStepDataPointsFilters));
138 usedModuleTypes.insert(createModulesFromRegistrar(
"referenceDataPointsFilters", doc, pm.REG(
DataPointsFilter), referenceDataPointsFilters));
140 usedModuleTypes.insert(createModuleFromRegistrar(
"matcher", doc, pm.REG(
Matcher), matcher));
141 usedModuleTypes.insert(createModulesFromRegistrar(
"outlierFilters", doc, pm.REG(
OutlierFilter), outlierFilters));
142 usedModuleTypes.insert(createModuleFromRegistrar(
"errorMinimizer", doc, pm.REG(
ErrorMinimizer), errorMinimizer));
145 if (nodeVal(
"errorMinimizer", doc) !=
"PointToPointSimilarityErrorMinimizer")
150 usedModuleTypes.insert(createModulesFromRegistrar(
"transformationCheckers", doc, pm.REG(
TransformationChecker), transformationCheckers));
151 usedModuleTypes.insert(createModuleFromRegistrar(
"inspector", doc, pm.REG(
Inspector),inspector));
161 moduleTypeIt.first() >> moduleType;
162 if (usedModuleTypes.find(moduleType) == usedModuleTypes.end())
164 (boost::format(
"Module type %1% does not exist") % moduleType).str()
173 return prefilteredReadingPtsCount;
180 return prefilteredReferencePtsCount;
187 return maxNumIterationsReached;
202 modules.push_back(registrar.createFromYAML(module));
217 module = registrar.createFromYAML(*reg);
248 const int dim = readingIn.
features.rows();
250 return this->compute(readingIn, referenceIn, identity);
260 return this->compute(readingIn, referenceIn, initialTransformationParameters);
272 throw runtime_error(
"You must setup a matcher before running ICP");
273 if (!this->errorMinimizer)
274 throw runtime_error(
"You must setup an error minimizer before running ICP");
275 if (!this->inspector)
276 throw runtime_error(
"You must setup an inspector before running ICP");
278 this->inspector->init();
281 const int dim(referenceIn.
features.rows());
286 this->referenceDataPointsFilters.init();
287 this->referenceDataPointsFilters.apply(reference);
291 const int nbPtsReference = reference.
features.cols();
292 const Vector meanReference = reference.
features.rowwise().sum() / nbPtsReference;
294 T_refIn_refMean.block(0,dim-1, dim-1, 1) = meanReference.head(dim-1);
299 reference.
features.topRows(dim-1).colwise() -= meanReference.head(dim-1);
302 this->matcher->init(reference);
305 this->inspector->addStat(
"ReferencePreprocessingDuration",
t.elapsed());
306 this->inspector->addStat(
"ReferenceInPointCount", referenceIn.
features.cols());
307 this->inspector->addStat(
"ReferencePointCount", reference.
features.cols());
308 LOG_INFO_STREAM(
"PointMatcher::icp - reference pre-processing took " <<
t.elapsed() <<
" [s]");
309 this->prefilteredReferencePtsCount = reference.
features.cols();
311 return computeWithTransformedReference(readingIn, reference, T_refIn_refMean, T_refIn_dataIn);
323 const int dim(reference.
features.rows());
325 if (T_refIn_dataIn.cols() != T_refIn_dataIn.rows()) {
326 throw runtime_error(
"The initial transformation matrix must be squared.");
328 if (dim != T_refIn_dataIn.cols()) {
329 throw runtime_error(
"The shape of initial transformation matrix must be NxN. "
330 "Where N is the number of rows in the read/reference scans.");
339 this->readingDataPointsFilters.init();
340 this->readingDataPointsFilters.apply(reading);
341 readingFiltered = reading;
346 T_refMean_dataIn = T_refIn_refMean.inverse() * T_refIn_dataIn;
347 this->transformations.apply(reading, T_refMean_dataIn);
350 this->readingStepDataPointsFilters.init();
357 this->maxNumIterationsReached =
false;
358 this->transformationCheckers.init(T_iter, iterate);
360 size_t iterationCount(0);
363 this->inspector->addStat(
"ReadingPreprocessingDuration",
t.elapsed());
364 this->inspector->addStat(
"ReadingInPointCount", readingIn.
features.cols());
365 this->inspector->addStat(
"ReadingPointCount", reading.
features.cols());
366 LOG_INFO_STREAM(
"PointMatcher::icp - reading pre-processing took " <<
t.elapsed() <<
" [s]");
367 this->prefilteredReadingPtsCount = reading.
features.cols();
377 this->readingStepDataPointsFilters.apply(stepReading);
381 this->transformations.apply(stepReading, T_iter);
386 this->matcher->findClosests(stepReading)
392 this->outlierFilters.compute(stepReading, reference, matches)
395 assert(outlierWeights.rows() == matches.
ids.rows());
396 assert(outlierWeights.cols() == matches.
ids.cols());
403 this->inspector->dumpIteration(
404 iterationCount, T_iter, reference, stepReading, matches, outlierWeights, this->transformationCheckers
411 T_iter = this->errorMinimizer->compute(
412 stepReading, reference, outlierWeights, matches) * T_iter;
421 this->transformationCheckers.check(T_iter, iterate);
426 this->maxNumIterationsReached =
true;
432 this->inspector->addStat(
"IterationsCount", iterationCount);
433 this->inspector->addStat(
"PointCountTouched", this->matcher->getVisitCount());
434 this->matcher->resetVisitCount();
435 this->inspector->addStat(
"OverlapRatio", this->errorMinimizer->getWeightedPointUsedRatio());
436 this->inspector->addStat(
"ConvergenceDuration",
t.elapsed());
437 this->inspector->finish(iterationCount);
439 LOG_INFO_STREAM(
"PointMatcher::icp - " << iterationCount <<
" iterations took " <<
t.elapsed() <<
" [s]");
448 return (T_refIn_refMean * T_iter * T_refMean_dataIn);
459 return (mapPointCloud.features.cols() != 0);
468 throw runtime_error(
"You must setup a matcher before running ICP");
469 if (!this->inspector)
470 throw runtime_error(
"You must setup an inspector before running ICP");
473 const int dim(inputCloud.
features.rows());
474 const int ptCount(inputCloud.
features.cols());
483 this->inspector->addStat(
"MapPointCount", inputCloud.
features.cols());
486 mapPointCloud = inputCloud;
490 const Vector meanMap = mapPointCloud.
features.rowwise().sum() / ptCount;
491 T_refIn_refMean = Matrix::Identity(dim, dim);
492 T_refIn_refMean.block(0,dim-1, dim-1, 1) = meanMap.head(dim-1);
497 mapPointCloud.features.topRows(dim-1).colwise() -= meanMap.head(dim-1);
500 this->referenceDataPointsFilters.init();
501 this->referenceDataPointsFilters.apply(mapPointCloud);
503 this->matcher->init(mapPointCloud);
505 this->inspector->addStat(
"SetMapDuration",
t.elapsed());
514 const int dim(mapPointCloud.features.rows());
515 T_refIn_refMean = Matrix::Identity(dim, dim);
524 if(mapPointCloud.getNbPoints() > 0)
526 this->matcher->init(mapPointCloud);
535 if(mapPointCloud.getNbPoints() > 0)
537 this->matcher->init(mapPointCloud);
548 const int dim(mapPointCloud.features.rows());
549 const Vector meanMapNonHomo(T_refIn_refMean.block(0,dim-1, dim-1, 1));
550 globalMap.
features.topRows(dim-1).colwise() += meanMapNonHomo;
566 return mapPointCloud;
580 const int dim = cloudIn.
features.rows();
582 return this->compute(cloudIn, identity);
590 return this->compute(cloudIn, T_dataInOld_dataInNew);
601 const int dim(cloudIn.
features.rows());
603 return Matrix::Identity(dim, dim);
606 this->inspector->init();
608 return this->computeWithTransformedReference(cloudIn, mapPointCloud, T_refIn_refMean, T_refIn_dataIn);