PCL - ICP代碼研讀(七 ) - determineRequiredBlobData函數
-
- 前言
- determineRequiredBlobData
前言
在
computeTransformation
函數中有這麼一段代碼:
// Make blobs if necessary
// ?
determineRequiredBlobData();
PCLPointCloud2::Ptr target_blob(new PCLPointCloud2);
if (need_target_blob_)
pcl::toPCLPointCloud2(*target_, *target_blob);
// Pass in the default target for the Correspondence Estimation/Rejection code
// 目標點雲和法向量可以在循環之前設好,source點雲和法向量則需要在每一個iteration都重設一遍
correspondence_estimation_->setInputTarget(target_);
if (correspondence_estimation_->requiresTargetNormals())
correspondence_estimation_->setTargetNormals(target_blob);
// Correspondence Rejectors need a binary blob
// 為correspondence_rejectors_中的每一個rejector設置目標點雲和法向量
// 目標點雲和法向量可以在循環之前設好,source點雲和法向量則需要在每一個iteration都重設一遍
for (std::size_t i = 0; i < correspondence_rejectors_.size(); ++i) {
registration::CorrespondenceRejector::Ptr& rej = correspondence_rejectors_[i];
if (rej->requiresTargetPoints())
rej->setTargetPoints(target_blob);
if (rej->requiresTargetNormals() && target_has_normals_)
rej->setTargetNormals(target_blob);
}
可以看到,在
need_target_blob_
為true的情況下,會將
pcl::PointCloud
類型的
target_
轉為
pcl::PCLPointCloud2
類型的點雲
target_blob
,然後將它作為
correspondence_estimation_->setTargetNormals
等函數的輸入。
這是因為校正算法輸入的點雲是
pcl::PointCloud
類型的,但是
computeTransformation
內部所用到的
pcl::registration::CorrespondenceEstimationBase::setTargetNormals
,
pcl::registration::CorrespondenceRejector::setTargetPoints
和
pcl::registration::CorrespondenceRejector::setTargetNormals
函數(對應的source版本為
pcl::registration::CorrespondenceEstimationBase::setSourceNormals
,
pcl::registration::CorrespondenceRejector::setSourcePoints
和
pcl::registration::CorrespondenceRejector::setSourceNormals
函數)接受的卻是
pcl::PCLPointCloud2
類型的點雲,所以才需要做這麼一道轉換。
在
determineRequiredBlobData
成員函數中,會判定是否需要用到上述的幾個函數,如果需要,
need_source_blob_
或/和
need_target_blob_
就會被設為true。接着在
computeTransformation
函數中,會依據這兩個flag決定是否需要執行
pcl::toPCLPointCloud2
。
determineRequiredBlobData
用於判定是否需要對source點雲和target點雲執行
pcl::toPCLPointCloud2
,並將結果記錄在
need_source_blob_
和
need_target_blob_
這兩個變數裡。
template <typename PointSource, typename PointTarget, typename Scalar>
void
IterativeClosestPoint<PointSource, PointTarget, Scalar>::determineRequiredBlobData()
{
// 如果correspondence_estimation_需要source或target的法向量,就設為true
// 如果correspondence_rejectors_中有任何一個rejector需要source或target的點雲或法向量,就設為true
need_source_blob_ = false;
need_target_blob_ = false;
// Check estimator
need_source_blob_ |= correspondence_estimation_->requiresSourceNormals();
need_target_blob_ |= correspondence_estimation_->requiresTargetNormals();
// Add warnings if necessary
if (correspondence_estimation_->requiresSourceNormals() && !source_has_normals_) {
PCL_WARN("[pcl::%s::determineRequiredBlobData] Estimator expects source normals, "
"but we can't provide them.\n",
getClassName().c_str());
}
if (correspondence_estimation_->requiresTargetNormals() && !target_has_normals_) {
PCL_WARN("[pcl::%s::determineRequiredBlobData] Estimator expects target normals, "
"but we can't provide them.\n",
getClassName().c_str());
}
// Check rejectors
for (std::size_t i = 0; i < correspondence_rejectors_.size(); i++) {
registration::CorrespondenceRejector::Ptr& rej = correspondence_rejectors_[i];
need_source_blob_ |= rej->requiresSourcePoints();
need_source_blob_ |= rej->requiresSourceNormals();
need_target_blob_ |= rej->requiresTargetPoints();
need_target_blob_ |= rej->requiresTargetNormals();
if (rej->requiresSourceNormals() && !source_has_normals_) {
PCL_WARN("[pcl::%s::determineRequiredBlobData] Rejector %s expects source "
"normals, but we can't provide them.\n",
getClassName().c_str(),
rej->getClassName().c_str());
}
if (rej->requiresTargetNormals() && !target_has_normals_) {
PCL_WARN("[pcl::%s::determineRequiredBlobData] Rejector %s expects target "
"normals, but we can't provide them.\n",
getClassName().c_str(),
rej->getClassName().c_str());
}
}
}
從以上代碼中,可以看到
pcl::registration::CorrespondenceEstimationBase
自帶了
requiresTargetNormals
,
pcl::registration::CorrespondenceRejector
自帶了
requiresTargetPoints
和
requiresTargetNormals
函數,因此這邊只需要對這些函數的回傳值做or即可。