86 const std::vector<CHypothesisPoint*>& aObjectPoints,
90 const Vec3d upwardsVector,
91 const int nEffortLevel,
92 const std::vector<Vec3d>* pPossibleLocationOffsets,
93 std::vector<CColorICP::CPointXYZRGBI>* pNearestNeighbors,
94 std::vector<float>* pPointMatchDistances,
95 const std::vector<CHypothesisPoint*>* pAdditionalPoints,
96 const float maxAcceptedDistance)
99 gettimeofday(&tStart, 0);
100 const int nParallelityFactor = omp_get_num_procs();
101 omp_set_num_threads(nParallelityFactor);
104 std::vector<Vec3d> aPossibleLocationOffsets;
105 aPossibleLocationOffsets.push_back(center);
107 if (pPossibleLocationOffsets)
109 for (
size_t i = 0; i < pPossibleLocationOffsets->size(); i++)
111 aPossibleLocationOffsets.push_back(pPossibleLocationOffsets->at(i));
115 const int nNumPossibleLocations = aPossibleLocationOffsets.size();
117 ARMARX_VERBOSE_S <<
"Trying to match object around " << nNumPossibleLocations
118 <<
" different possible locations";
120 for (
size_t i = 0; i < aPossibleLocationOffsets.size(); i++)
127 int nNumSamplesPerDimensionTemp;
129 switch (nEffortLevel)
135 nNumSamplesPerDimensionTemp = 1;
140 nNumSamplesPerDimensionTemp = 2;
145 nNumSamplesPerDimensionTemp = 3;
150 nNumSamplesPerDimensionTemp = 4;
155 nNumSamplesPerDimensionTemp = 5;
160 nNumSamplesPerDimensionTemp = 6;
164 bool tryDifferentOrientations = (Math3d::Length(upwardsVector) > 0) && (nEffortLevel >= 2);
165 const int nNumOrientations = tryDifferentOrientations ? 3 : 1;
166 Mat3d baseRotationMatrices[3];
167 Math3d::SetMat(baseRotationMatrices[0], Math3d::unit_mat);
168 Math3d::SetRotationMat(baseRotationMatrices[1], upwardsVector, -20.0 *
M_PI / 180.0);
169 Math3d::SetRotationMat(baseRotationMatrices[2], upwardsVector, 20.0 *
M_PI / 180.0);
171 const float fShift = fShiftTemp;
172 const int nNumSamplesPerDimension = nNumSamplesPerDimensionTemp;
173 const int nNumSamplesPerDimension2 = nNumSamplesPerDimension * nNumSamplesPerDimension;
174 const int nNumSamplesPerDimension3 =
175 nNumSamplesPerDimension * nNumSamplesPerDimension * nNumSamplesPerDimension;
176 const int nNumSamples = nNumOrientations * nNumSamplesPerDimension3 * nNumPossibleLocations;
177 const float fMiddle = 0.5f * (nNumSamplesPerDimension - 1);
178 Vec3d* pShiftVectors =
new Vec3d[nNumSamples];
179 Mat3d* rotationMatrices =
new Mat3d[nNumSamples];
181 for (
int n = 0; n < nNumPossibleLocations; n++)
183 const Vec3d vLocationOffset = aPossibleLocationOffsets.at(n);
185 for (
int i = 0; i < nNumSamplesPerDimension; i++)
187 for (
int j = 0; j < nNumSamplesPerDimension; j++)
189 for (
int k = 0; k < nNumSamplesPerDimension; k++)
191 for (
int l = 0; l < nNumOrientations; l++)
193 const int nIndex = n * nNumSamplesPerDimension3 * nNumOrientations +
194 i * nNumSamplesPerDimension2 * nNumOrientations +
195 j * nNumSamplesPerDimension * nNumOrientations +
196 k * nNumOrientations + l;
197 pShiftVectors[nIndex].x = vLocationOffset.x + (i - fMiddle) * fShift;
198 pShiftVectors[nIndex].y = vLocationOffset.y + (j - fMiddle) * fShift;
199 pShiftVectors[nIndex].z = vLocationOffset.z + (k - fMiddle) * fShift;
200 Math3d::SetMat(rotationMatrices[nIndex], baseRotationMatrices[l]);
209 size_t maxNumPoints = 200 + nEffortLevel * 200;
210 std::vector<CHypothesisPoint*> aObjectPointsDownsampled;
212 if (aObjectPoints.size() > maxNumPoints)
214 const float ratio = (
float)maxNumPoints / (
float)aObjectPoints.size();
215 const int randomThreshold = 1000.0f * ratio;
217 for (
size_t i = 0; i < aObjectPoints.size(); i++)
219 if (rand() % 1000 <= randomThreshold)
221 aObjectPointsDownsampled.push_back(aObjectPoints.at(i));
225 ARMARX_VERBOSE_S <<
"Object pointcloud was downsampled from " << aObjectPoints.size()
226 <<
" to " << aObjectPointsDownsampled.size() <<
" points";
230 aObjectPointsDownsampled = aObjectPoints;
236 Mat3d mBestRotation = Math3d::unit_mat;
237 Mat3d mSecondBestRotation = Math3d::unit_mat;
238 Vec3d vBestTranslation = {0, 0, 0};
239 Vec3d vSecondBestTranslation = {0, 0, 0};
240 float fBestDistance = FLT_MAX;
241 float fSecondBestDistance = FLT_MAX;
242 std::vector<float> distances;
243 std::vector<Vec3d> positions;
244 int numSamplesAlreadyDone = 0;
246#pragma omp parallel for schedule(dynamic, 1)
247 for (
int k = 0; k < nNumSamples; k++)
249 const int nThreadNumber = omp_get_thread_num();
251 std::vector<CColorICP::CPointXYZRGBI> objectPointCloudPar;
252 objectPointCloudPar.resize(aObjectPointsDownsampled.size());
255 for (
size_t i = 0; i < aObjectPointsDownsampled.size(); i++)
258 vPointPar.
x -= center.x;
259 vPointPar.
y -= center.y;
260 vPointPar.
z -= center.z;
261 objectPointCloudPar.at(i) = vPointPar;
264 if (tryDifferentOrientations)
269 for (
size_t i = 0; i < objectPointCloudPar.size(); i++)
271 objectPointCloudPar.at(i).x += pShiftVectors[k].x;
272 objectPointCloudPar.at(i).y += pShiftVectors[k].y;
273 objectPointCloudPar.at(i).z += pShiftVectors[k].z;
276 Mat3d newRotation, newRotationGlobal;
277 Vec3d newTranslation, newTranslationGlobal;
278 float fNewObjectDistance = m_pColorICPInstances[nThreadNumber]->SearchObject(
282 std::min(fBestDistance, maxAcceptedDistance));
290 newTranslationGlobal);
294 distances.push_back(fNewObjectDistance);
295 positions.push_back(newTranslationGlobal);
298 if (fNewObjectDistance < fBestDistance)
300 fSecondBestDistance = fBestDistance;
301 Math3d::SetMat(mSecondBestRotation, mBestRotation);
302 Math3d::SetVec(vSecondBestTranslation, vBestTranslation);
304 fBestDistance = fNewObjectDistance;
305 Math3d::SetMat(mBestRotation, newRotationGlobal);
306 Math3d::SetVec(vBestTranslation, newTranslationGlobal);
308 else if (fNewObjectDistance < fSecondBestDistance)
310 fSecondBestDistance = fNewObjectDistance;
311 Math3d::SetMat(mSecondBestRotation, newRotationGlobal);
312 Math3d::SetVec(vSecondBestTranslation, newTranslationGlobal);
315 numSamplesAlreadyDone++;
317 if (numSamplesAlreadyDone % (3 * nNumSamplesPerDimension3) == 0)
319 ARMARX_VERBOSE_S << (int)((
float)numSamplesAlreadyDone * 100 / (
float)nNumSamples)
328 Vec3d vRefinementTranslation, vTemp;
329 Mat3d mRefinementRotation;
334 std::vector<CColorICP::CPointXYZRGBI> objectPointCloudConverted;
336 for (
size_t i = 0; i < aObjectPoints.size(); i++)
338 Math3d::MulMatVec(mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
342 vPoint.
r = aObjectPoints.at(i)->fColorR;
343 vPoint.
g = aObjectPoints.at(i)->fColorG;
344 vPoint.
b = aObjectPoints.at(i)->fColorB;
345 vPoint.
i = aObjectPoints.at(i)->fIntensity;
346 objectPointCloudConverted.push_back(vPoint);
350 std::vector<float> aPointMatchDistances;
351 m_pColorICPInstances[0]->GetPointMatchDistances(objectPointCloudConverted,
352 aPointMatchDistances);
355 objectPointCloudConverted.clear();
357 for (
size_t i = 0; i < aObjectPoints.size(); i++)
362 mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
366 vPoint.
r = aObjectPoints.at(i)->fColorR;
367 vPoint.
g = aObjectPoints.at(i)->fColorG;
368 vPoint.
b = aObjectPoints.at(i)->fColorB;
369 vPoint.
i = aObjectPoints.at(i)->fIntensity;
370 objectPointCloudConverted.push_back(vPoint);
374 m_pColorICPInstances[0]->SearchObject(
375 objectPointCloudConverted, mRefinementRotation, vRefinementTranslation, fBestDistance);
380 Math3d::SetMat(mOldBestRot, mBestRotation);
381 Math3d::MulMatMat(mRefinementRotation, mOldBestRot, mBestRotation);
383 Vec3d vOldBestTransl;
384 Math3d::SetVec(vOldBestTransl, vBestTranslation);
386 mRefinementRotation, vOldBestTransl, vRefinementTranslation, vBestTranslation);
390 if (pPointMatchDistances && pNearestNeighbors)
393 objectPointCloudConverted.clear();
395 for (
size_t i = 0; i < aObjectPoints.size(); i++)
398 mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
402 vPoint.
r = aObjectPoints.at(i)->fColorR;
403 vPoint.
g = aObjectPoints.at(i)->fColorG;
404 vPoint.
b = aObjectPoints.at(i)->fColorB;
405 vPoint.
i = aObjectPoints.at(i)->fIntensity;
406 objectPointCloudConverted.push_back(vPoint);
409 if (pAdditionalPoints)
411 for (
size_t i = 0; i < pAdditionalPoints->size(); i++)
414 mBestRotation, pAdditionalPoints->at(i)->vPosition, vBestTranslation, vTemp);
418 vPoint.
r = pAdditionalPoints->at(i)->fColorR;
419 vPoint.
g = pAdditionalPoints->at(i)->fColorG;
420 vPoint.
b = pAdditionalPoints->at(i)->fColorB;
421 vPoint.
i = pAdditionalPoints->at(i)->fIntensity;
422 objectPointCloudConverted.push_back(vPoint);
426 pNearestNeighbors->clear();
427 pPointMatchDistances->clear();
428 m_pColorICPInstances[0]->GetNearestNeighbors(
429 objectPointCloudConverted, *pNearestNeighbors, *pPointMatchDistances);
434 Math3d::SetMat(mRotation, mBestRotation);
435 Math3d::SetVec(vTranslation, vBestTranslation);
439 std::vector<float> badMatchDistances;
441 for (
size_t i = 0; i < distances.size(); i++)
443 float dist = Math3d::Distance(vBestTranslation, positions.at(i));
447 badMatchDistances.push_back(distances.at(i));
451 float averageBadMatchDistance = 0;
453 for (
size_t i = 0; i < badMatchDistances.size(); i++)
455 averageBadMatchDistance += badMatchDistances.at(i);
458 if (badMatchDistances.size() > 0)
460 averageBadMatchDistance /= badMatchDistances.size();
465 <<
" average bad match distance: " << averageBadMatchDistance;
469 delete[] pShiftVectors;
470 delete[] rotationMatrices;
473 gettimeofday(&tEnd, 0);
475 (1000 * tEnd.tv_sec + tEnd.tv_usec / 1000) - (1000 * tStart.tv_sec + tStart.tv_usec / 1000);
476 ARMARX_VERBOSE_S <<
"Time for pointcloud registration: " << tTimeDiff <<
" ms";
479 return fBestDistance;