PointCloudRegistration.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package
19 * @author
20 * @date
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
25
26#include "OLPTools.h"
27
28// OpenMP
29#include <omp.h>
30
31// system
32#include <sys/time.h>
33
35
37{
38 // create parallel instances of CColorICP
39 const int nParallelityFactor = omp_get_num_procs();
40 m_pColorICPInstances = new CColorICP*[nParallelityFactor];
41
42 for (int i = 0; i < nParallelityFactor; i++)
43 {
44 m_pColorICPInstances[i] = new CColorICP();
45 m_pColorICPInstances[i]->SetParameters(OLP_ICP_COLOR_DISTANCE_WEIGHT,
47 }
48}
49
51{
52 const int nParallelityFactor = omp_get_num_procs();
53
54 for (int i = 0; i < nParallelityFactor; i++)
55 {
56 delete m_pColorICPInstances[i];
57 }
58
59 delete m_pColorICPInstances;
60}
61
62// set the point cloud in which the object should be searched
63void
64CPointCloudRegistration::SetScenePointcloud(const std::vector<CHypothesisPoint*>& aScenePoints)
65{
66 // convert points to simple format for ICP
67 std::vector<CColorICP::CPointXYZRGBI> aScenePointsConverted;
68 aScenePointsConverted.resize(aScenePoints.size());
69
70 for (size_t i = 0; i < aScenePoints.size(); i++)
71 {
72 aScenePointsConverted.at(i) = CColorICP::ConvertToXYZRGBI(aScenePoints.at(i));
73 }
74
75 // update the parallel instances of CColorICP
76 const int nParallelityFactor = omp_get_num_procs();
77
78 for (int i = 0; i < nParallelityFactor; i++)
79 {
80 m_pColorICPInstances[i]->SetScenePointcloud(aScenePointsConverted);
81 }
82}
83
84float
86 const std::vector<CHypothesisPoint*>& aObjectPoints,
87 const Vec3d center,
88 Mat3d& mRotation,
89 Vec3d& vTranslation,
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)
97{
98 timeval tStart, tEnd;
99 gettimeofday(&tStart, 0);
100 const int nParallelityFactor = omp_get_num_procs();
101 omp_set_num_threads(nParallelityFactor);
102
103 // create grid of initial positions around the possible object locations
104 std::vector<Vec3d> aPossibleLocationOffsets;
105 aPossibleLocationOffsets.push_back(center); // original position
106
107 if (pPossibleLocationOffsets)
108 {
109 for (size_t i = 0; i < pPossibleLocationOffsets->size(); i++)
110 {
111 aPossibleLocationOffsets.push_back(pPossibleLocationOffsets->at(i));
112 }
113 }
114
115 const int nNumPossibleLocations = aPossibleLocationOffsets.size();
116
117 ARMARX_VERBOSE_S << "Trying to match object around " << nNumPossibleLocations
118 << " different possible locations";
119
120 for (size_t i = 0; i < aPossibleLocationOffsets.size(); i++)
121 {
122 //ARMARX_VERBOSE_S << aPossibleLocationOffsets.at(i).x << " " << aPossibleLocationOffsets.at(i).y << " " << aPossibleLocationOffsets.at(i).z;
123 }
124
125
126 float fShiftTemp;
127 int nNumSamplesPerDimensionTemp;
128
129 switch (nEffortLevel)
130 {
131 case 0:
132 case 1:
133 case 2:
134 fShiftTemp = 0;
135 nNumSamplesPerDimensionTemp = 1;
136 break;
137
138 case 3:
139 fShiftTemp = 100;
140 nNumSamplesPerDimensionTemp = 2;
141 break;
142
143 case 4:
144 fShiftTemp = 70;
145 nNumSamplesPerDimensionTemp = 3;
146 break;
147
148 case 5:
149 fShiftTemp = 80;
150 nNumSamplesPerDimensionTemp = 4;
151 break;
152
153 case 6:
154 fShiftTemp = 70;
155 nNumSamplesPerDimensionTemp = 5;
156 break;
157
158 default:
159 fShiftTemp = 70;
160 nNumSamplesPerDimensionTemp = 6;
161 break;
162 }
163
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);
170
171 const float fShift = fShiftTemp; // unit shift values for the sample points
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];
180
181 for (int n = 0; n < nNumPossibleLocations; n++)
182 {
183 const Vec3d vLocationOffset = aPossibleLocationOffsets.at(n);
184
185 for (int i = 0; i < nNumSamplesPerDimension; i++)
186 {
187 for (int j = 0; j < nNumSamplesPerDimension; j++)
188 {
189 for (int k = 0; k < nNumSamplesPerDimension; k++)
190 {
191 for (int l = 0; l < nNumOrientations; l++)
192 {
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]);
201 }
202 }
203 }
204 }
205 }
206
207
208 // downsample object cloud if necessary
209 size_t maxNumPoints = 200 + nEffortLevel * 200;
210 std::vector<CHypothesisPoint*> aObjectPointsDownsampled;
211
212 if (aObjectPoints.size() > maxNumPoints)
213 {
214 const float ratio = (float)maxNumPoints / (float)aObjectPoints.size();
215 const int randomThreshold = 1000.0f * ratio;
216
217 for (size_t i = 0; i < aObjectPoints.size(); i++)
218 {
219 if (rand() % 1000 <= randomThreshold)
220 {
221 aObjectPointsDownsampled.push_back(aObjectPoints.at(i));
222 }
223 }
224
225 ARMARX_VERBOSE_S << "Object pointcloud was downsampled from " << aObjectPoints.size()
226 << " to " << aObjectPointsDownsampled.size() << " points";
227 }
228 else
229 {
230 aObjectPointsDownsampled = aObjectPoints;
231 }
232
233
234 // try ICP with different start positions
235
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;
245
246#pragma omp parallel for schedule(dynamic, 1)
247 for (int k = 0; k < nNumSamples; k++)
248 {
249 const int nThreadNumber = omp_get_thread_num();
250
251 std::vector<CColorICP::CPointXYZRGBI> objectPointCloudPar;
252 objectPointCloudPar.resize(aObjectPointsDownsampled.size());
253 CColorICP::CPointXYZRGBI vPointPar;
254
255 for (size_t i = 0; i < aObjectPointsDownsampled.size(); i++)
256 {
257 vPointPar = CColorICP::ConvertToXYZRGBI(aObjectPointsDownsampled.at(i));
258 vPointPar.x -= center.x;
259 vPointPar.y -= center.y;
260 vPointPar.z -= center.z;
261 objectPointCloudPar.at(i) = vPointPar;
262 }
263
264 if (tryDifferentOrientations)
265 {
266 RotatePoints(objectPointCloudPar, rotationMatrices[k]);
267 }
268
269 for (size_t i = 0; i < objectPointCloudPar.size(); i++)
270 {
271 objectPointCloudPar.at(i).x += pShiftVectors[k].x;
272 objectPointCloudPar.at(i).y += pShiftVectors[k].y;
273 objectPointCloudPar.at(i).z += pShiftVectors[k].z;
274 }
275
276 Mat3d newRotation, newRotationGlobal;
277 Vec3d newTranslation, newTranslationGlobal;
278 float fNewObjectDistance = m_pColorICPInstances[nThreadNumber]->SearchObject(
279 objectPointCloudPar,
280 newRotation,
281 newTranslation,
282 std::min(fBestDistance, maxAcceptedDistance));
283
284 GetCompleteTransformation(newRotation,
285 newTranslation,
286 rotationMatrices[k],
287 pShiftVectors[k],
288 center,
289 newRotationGlobal,
290 newTranslationGlobal);
291
292#pragma omp critical
293 {
294 distances.push_back(fNewObjectDistance);
295 positions.push_back(newTranslationGlobal);
296
297 // if better solution found, save it
298 if (fNewObjectDistance < fBestDistance)
299 {
300 fSecondBestDistance = fBestDistance;
301 Math3d::SetMat(mSecondBestRotation, mBestRotation);
302 Math3d::SetVec(vSecondBestTranslation, vBestTranslation);
303
304 fBestDistance = fNewObjectDistance;
305 Math3d::SetMat(mBestRotation, newRotationGlobal);
306 Math3d::SetVec(vBestTranslation, newTranslationGlobal);
307 }
308 else if (fNewObjectDistance < fSecondBestDistance)
309 {
310 fSecondBestDistance = fNewObjectDistance;
311 Math3d::SetMat(mSecondBestRotation, newRotationGlobal);
312 Math3d::SetVec(vSecondBestTranslation, newTranslationGlobal);
313 }
314
315 numSamplesAlreadyDone++;
316
317 if (numSamplesAlreadyDone % (3 * nNumSamplesPerDimension3) == 0)
318 {
319 ARMARX_VERBOSE_S << (int)((float)numSamplesAlreadyDone * 100 / (float)nNumSamples)
320 << "% done";
321 }
322 }
323 }
324
325
326 // apply best found transformation, remove object points that do not match in the new scene, and do one more iteration of ICP
327
328 Vec3d vRefinementTranslation, vTemp;
329 Mat3d mRefinementRotation;
330
331
332 // convert the points belonging to the object
334 std::vector<CColorICP::CPointXYZRGBI> objectPointCloudConverted;
335
336 for (size_t i = 0; i < aObjectPoints.size(); i++)
337 {
338 Math3d::MulMatVec(mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
339 vPoint.x = vTemp.x;
340 vPoint.y = vTemp.y;
341 vPoint.z = vTemp.z;
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);
347 }
348
349 // determine "bad" points
350 std::vector<float> aPointMatchDistances;
351 m_pColorICPInstances[0]->GetPointMatchDistances(objectPointCloudConverted,
352 aPointMatchDistances);
353
354 // ICP using only the good points
355 objectPointCloudConverted.clear();
356
357 for (size_t i = 0; i < aObjectPoints.size(); i++)
358 {
359 if (aPointMatchDistances.at(i) < OLP_TOLERANCE_CONCURRENT_MOTION)
360 {
361 Math3d::MulMatVec(
362 mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
363 vPoint.x = vTemp.x;
364 vPoint.y = vTemp.y;
365 vPoint.z = vTemp.z;
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);
371 }
372 }
373
374 m_pColorICPInstances[0]->SearchObject(
375 objectPointCloudConverted, mRefinementRotation, vRefinementTranslation, fBestDistance);
376
377 // save the result
378 // rotation is Rot * initial rotation
379 Mat3d mOldBestRot;
380 Math3d::SetMat(mOldBestRot, mBestRotation);
381 Math3d::MulMatMat(mRefinementRotation, mOldBestRot, mBestRotation);
382 // translation is Rot*shift+trans
383 Vec3d vOldBestTransl;
384 Math3d::SetVec(vOldBestTransl, vBestTranslation);
385 Math3d::MulMatVec(
386 mRefinementRotation, vOldBestTransl, vRefinementTranslation, vBestTranslation);
387
388
389 // get the point match distances for the resulting transformation
390 if (pPointMatchDistances && pNearestNeighbors)
391 {
392 Vec3d vTemp;
393 objectPointCloudConverted.clear();
394
395 for (size_t i = 0; i < aObjectPoints.size(); i++)
396 {
397 Math3d::MulMatVec(
398 mBestRotation, aObjectPoints.at(i)->vPosition, vBestTranslation, vTemp);
399 vPoint.x = vTemp.x;
400 vPoint.y = vTemp.y;
401 vPoint.z = vTemp.z;
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);
407 }
408
409 if (pAdditionalPoints)
410 {
411 for (size_t i = 0; i < pAdditionalPoints->size(); i++)
412 {
413 Math3d::MulMatVec(
414 mBestRotation, pAdditionalPoints->at(i)->vPosition, vBestTranslation, vTemp);
415 vPoint.x = vTemp.x;
416 vPoint.y = vTemp.y;
417 vPoint.z = vTemp.z;
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);
423 }
424 }
425
426 pNearestNeighbors->clear();
427 pPointMatchDistances->clear();
428 m_pColorICPInstances[0]->GetNearestNeighbors(
429 objectPointCloudConverted, *pNearestNeighbors, *pPointMatchDistances);
430 }
431
432
433 // set return values
434 Math3d::SetMat(mRotation, mBestRotation);
435 Math3d::SetVec(vTranslation, vBestTranslation);
436
437
438 // compare best distance to bad matches
439 std::vector<float> badMatchDistances;
440
441 for (size_t i = 0; i < distances.size(); i++)
442 {
443 float dist = Math3d::Distance(vBestTranslation, positions.at(i));
444
445 if (dist > 300)
446 {
447 badMatchDistances.push_back(distances.at(i));
448 }
449 }
450
451 float averageBadMatchDistance = 0;
452
453 for (size_t i = 0; i < badMatchDistances.size(); i++)
454 {
455 averageBadMatchDistance += badMatchDistances.at(i);
456 }
457
458 if (badMatchDistances.size() > 0)
459 {
460 averageBadMatchDistance /= badMatchDistances.size();
461 }
462
463
464 ARMARX_VERBOSE_S << "Distance: " << fBestDistance
465 << " average bad match distance: " << averageBadMatchDistance;
466
467
468 // clean up
469 delete[] pShiftVectors;
470 delete[] rotationMatrices;
471
472
473 gettimeofday(&tEnd, 0);
474 long tTimeDiff =
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";
477
478
479 return fBestDistance;
480}
481
482bool
484 float& distance,
485 const int nEffortLevel)
486{
487 // get the object points
488 std::vector<CHypothesisPoint*> aObjectPoints;
489
490 for (size_t i = 0; i < pHypothesis->aConfirmedPoints.size(); i++)
491 {
492 aObjectPoints.push_back(pHypothesis->aConfirmedPoints.at(i));
493 }
494
495 // dont use too many candidate points
496 const size_t nNewPointsLimit = (pHypothesis->aConfirmedPoints.size() > OLP_MIN_NUM_FEATURES)
497 ? 3 * pHypothesis->aConfirmedPoints.size() / 2
498 : pHypothesis->aNewPoints.size();
499
500 for (size_t i = 0; i < pHypothesis->aNewPoints.size() && i < nNewPointsLimit; i++)
501 {
502 aObjectPoints.push_back(pHypothesis->aNewPoints.at(i));
503 }
504
505 // downsample object cloud if necessary
506 size_t maxNumPoints = 200 + nEffortLevel * 200;
507 std::vector<CHypothesisPoint*> aObjectPointsDownsampled;
508
509 if (aObjectPoints.size() > maxNumPoints)
510 {
511 const float ratio = (float)maxNumPoints / (float)aObjectPoints.size();
512 const int randomThreshold = 1000.0f * ratio;
513
514 for (size_t i = 0; i < aObjectPoints.size(); i++)
515 {
516 if (rand() % 1000 <= randomThreshold)
517 {
518 aObjectPointsDownsampled.push_back(aObjectPoints.at(i));
519 }
520 }
521
522 ARMARX_VERBOSE_S << "Object pointcloud was downsampled from " << aObjectPoints.size()
523 << " to " << aObjectPointsDownsampled.size() << " points";
524 }
525 else
526 {
527 aObjectPointsDownsampled = aObjectPoints;
528 }
529
530 // convert the points belonging to the object
531 std::vector<CColorICP::CPointXYZRGBI> objectPointCloudConverted;
532
533 for (size_t i = 0; i < aObjectPointsDownsampled.size(); i++)
534 {
535 objectPointCloudConverted.push_back(
536 CColorICP::ConvertToXYZRGBI(aObjectPointsDownsampled.at(i)));
537 }
538
539 Mat3d mRotation;
540 Vec3d vTranslation;
541 distance =
542 m_pColorICPInstances[0]->SearchObject(objectPointCloudConverted, mRotation, vTranslation);
543
544
545 // check if the object seems to have moved
546 Vec3d vObjectCenter = {0, 0, 0};
547
548 for (size_t i = 0; i < aObjectPointsDownsampled.size(); i++)
549 {
550 Math3d::AddToVec(vObjectCenter, aObjectPointsDownsampled.at(i)->vPosition);
551 }
552
553 Math3d::MulVecScalar(vObjectCenter, 1.0f / aObjectPointsDownsampled.size(), vObjectCenter);
554 Vec3d vTemp1;
555 Math3d::MulMatVec(mRotation, vObjectCenter, vTranslation, vTemp1);
556 float fTranslationLength = Math3d::Distance(vTemp1, vObjectCenter);
557
558 // check for rotation
559 float fAngle;
560 Math3d::GetAxisAndAngle(mRotation, vTemp1, fAngle);
561
562
563 bool bRet = (fTranslationLength < 0.33f * OLP_MINIMAL_MOTION_MEASURE) &&
564 (distance < 0.33f * OLP_TOLERANCE_CONCURRENT_MOTION) && (fAngle < 10 * M_PI / 180);
565
566 ARMARX_VERBOSE_S << "Check at original position: Translation: " << fTranslationLength
567 << " Rotation: " << 180 * fAngle / M_PI << "deg";
568
569 return bRet;
570}
571
572/*
573bool CPointCloudRegistration::EstimateTransformationPCL(const std::vector<CHypothesisPoint*>& aOldPoints, const std::vector<CHypothesisPoint*>& aNewPoints, Mat3d& mRotation, Vec3d& vTranslation)
574{
575#ifdef OLP_USE_PCL
576
577 // copy points to PCL pointclouds
578 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr aOldPointsPCL (new pcl::PointCloud<pcl::PointXYZRGBA>);
579 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr aNewPointsPCL (new pcl::PointCloud<pcl::PointXYZRGBA>);
580
581 aOldPointsPCL->resize(aOldPoints.size());
582 aNewPointsPCL->resize(aNewPoints.size());
583 for (int i=0; i<(int)aOldPoints.size(); i++)
584 {
585 aOldPointsPCL->points[i].x = aOldPoints.at(i)->vPosition.x/1000; // convert to meters
586 aOldPointsPCL->points[i].y = aOldPoints.at(i)->vPosition.y/1000;
587 aOldPointsPCL->points[i].z = aOldPoints.at(i)->vPosition.z/1000;
588 aOldPointsPCL->points[i].r = (int)(255*aOldPoints.at(i)->fIntensity*aOldPoints.at(i)->fColorR);
589 aOldPointsPCL->points[i].g = (int)(255*aOldPoints.at(i)->fIntensity*aOldPoints.at(i)->fColorG);
590 aOldPointsPCL->points[i].b = (int)(255*aOldPoints.at(i)->fIntensity*aOldPoints.at(i)->fColorB);
591 aOldPointsPCL->points[i].a = 1;
592 }
593 for (int i=0; i<(int)aNewPoints.size(); i++)
594 {
595 aNewPointsPCL->points[i].x = aNewPoints.at(i)->vPosition.x/1000;
596 aNewPointsPCL->points[i].y = aNewPoints.at(i)->vPosition.y/1000;
597 aNewPointsPCL->points[i].z = aNewPoints.at(i)->vPosition.z/1000;
598 aNewPointsPCL->points[i].r = (int)(255*aNewPoints.at(i)->fIntensity*aNewPoints.at(i)->fColorR);
599 aNewPointsPCL->points[i].g = (int)(255*aNewPoints.at(i)->fIntensity*aNewPoints.at(i)->fColorG);
600 aNewPointsPCL->points[i].b = (int)(255*aNewPoints.at(i)->fIntensity*aNewPoints.at(i)->fColorB);
601 aNewPointsPCL->points[i].a = 1;
602 }
603
604 // i.e. this is an unorganized pointcloud
605 aOldPointsPCL->width = aOldPoints.size();
606 aOldPointsPCL->height = 1;
607 // set to false if points may contain inf or nan values
608 aOldPointsPCL->is_dense = true;
609
610 // do ICP
611 pcl::IterativeClosestPoint<pcl::PointXYZRGBA, pcl::PointXYZRGBA> icp;
612 icp.setInputCloud(aOldPointsPCL);
613 icp.setInputTarget(aNewPointsPCL);
614 pcl::PointCloud<pcl::PointXYZRGBA> Final;
615 icp.align(Final);
616
617 bool bSuccess = icp.hasConverged();
618 float fScore = icp.getFitnessScore();
619 Eigen::Matrix4f mTrafo = icp.getFinalTransformation();
620
621 mRotation.r1 = mTrafo(0,0);
622 mRotation.r2 = mTrafo(0,1);
623 mRotation.r3 = mTrafo(0,2);
624 mRotation.r4 = mTrafo(1,0);
625 mRotation.r5 = mTrafo(1,1);
626 mRotation.r6 = mTrafo(1,2);
627 mRotation.r7 = mTrafo(2,0);
628 mRotation.r8 = mTrafo(2,1);
629 mRotation.r9 = mTrafo(2,2);
630
631 vTranslation.x = mTrafo(0,3);
632 vTranslation.y = mTrafo(1,3);
633 vTranslation.z = mTrafo(2,3);
634
635 cout << "Success: " << bSuccess << " Score: " << fScore << " "; // << " Transformation:" << endl << mTrafo << endl;
636
637 return bSuccess;
638#else
639 return false;
640#endif
641}
642*/
643
644
645float
647 const CObjectHypothesis* pHypothesis,
648 Mat3d& mRotation,
649 Vec3d& vTranslation,
650 const Vec3d upwardsVector,
651 const int nEffortLevel,
652 const std::vector<Vec3d>* pPossibleLocations,
653 std::vector<CColorICP::CPointXYZRGBI>* pNearestNeighbors,
654 std::vector<float>* pPointMatchDistances,
655 const float maxAcceptedDistance)
656{
657#ifdef OLP_USE_DEPTH_MAP
658
659 // hypothesis points that will be used for matching
660 std::vector<CHypothesisPoint*> aHypothesisPoints = pHypothesis->aConfirmedPoints;
661
662
663 // fill up with candidate points, but dont use too many
664 size_t maxNumPoints = 200 + nEffortLevel * 200;
665 size_t nNewPointsLimit;
666
667 if (aHypothesisPoints.size() >= maxNumPoints)
668 {
669 nNewPointsLimit = 0;
670 }
671 else
672 {
673 nNewPointsLimit = maxNumPoints - aHypothesisPoints.size();
674
675 if ((pHypothesis->aConfirmedPoints.size() > OLP_MIN_NUM_FEATURES) &&
676 (pHypothesis->aConfirmedPoints.size() < nNewPointsLimit))
677 {
678 nNewPointsLimit = pHypothesis->aConfirmedPoints.size();
679 }
680 }
681
682 for (size_t i = 0; i < pHypothesis->aNewPoints.size() && i < nNewPointsLimit; i++)
683 {
684 aHypothesisPoints.push_back(pHypothesis->aNewPoints.at(i));
685 }
686
687
688 // additional points that will not be used for matching
689 std::vector<CHypothesisPoint*> aAdditionalPoints;
690
691 for (size_t i = nNewPointsLimit; i < pHypothesis->aNewPoints.size(); i++)
692 {
693 aAdditionalPoints.push_back(pHypothesis->aNewPoints.at(i));
694 }
695
696 for (size_t i = 0; i < pHypothesis->aDoubtablePoints.size(); i++)
697 {
698 aAdditionalPoints.push_back(pHypothesis->aDoubtablePoints.at(i));
699 }
700
701
702 float fDistance = EstimateTransformation(aHypothesisPoints,
703 pHypothesis->vCenter,
704 mRotation,
705 vTranslation,
706 upwardsVector,
707 nEffortLevel,
708 pPossibleLocations,
709 pNearestNeighbors,
710 pPointMatchDistances,
711 &aAdditionalPoints,
712 maxAcceptedDistance);
713
714 //Vec3d vTemp1, vTemp2;
715 //Math3d::MulMatVec(mRotation, pHypothesis->vCenter, vTemp1);
716 //Math3d::MulVecScalar(vTranslation, 1, vTemp2);
717 //Math3d::AddToVec(vTemp1, vTemp2);
718 //float fDist = Math3d::Distance(vTemp1, pHypothesis->vCenter);
719 //ARMARX_VERBOSE_S << "Translation: (%.1f, %.1f, %.1f), length %.1f mm\n\n", (vTemp1.x-pHypothesis->vCenter.x), (vTemp1.y-pHypothesis->vCenter.y), (vTemp1.z-pHypothesis->vCenter.z), fDist);
720
721 return fDistance;
722#else
723 return FLT_MAX;
724#endif
725}
726
727void
728CPointCloudRegistration::RotatePoints(std::vector<CColorICP::CPointXYZRGBI>& points,
729 const Mat3d rot)
730{
731 Vec3d center = {0, 0, 0};
732 // for (size_t i=0; i<points.size(); i++)
733 // {
734 // center.x += points.at(i).x;
735 // center.y += points.at(i).y;
736 // center.z += points.at(i).z;
737 // }
738 // if (points.size()>0)
739 // {
740 // center.x /= points.size();
741 // center.y /= points.size();
742 // center.z /= points.size();
743 // }
744
745 for (size_t i = 0; i < points.size(); i++)
746 {
747 Vec3d point = {
748 points.at(i).x - center.x, points.at(i).y - center.y, points.at(i).z - center.z};
749 Vec3d pointRot;
750 Math3d::MulMatVec(rot, point, pointRot);
751 points.at(i).x = pointRot.x + center.x;
752 points.at(i).y = pointRot.y + center.y;
753 points.at(i).z = pointRot.z + center.z;
754 }
755}
756
757void
759 Vec3d transICP,
760 Mat3d rotShift,
761 Vec3d transShift,
762 Vec3d center,
763 Mat3d& completeRotation,
764 Vec3d& completeTranslation)
765{
766 Math3d::MulMatMat(rotICP, rotShift, completeRotation);
767
768 Vec3d temp1, temp2;
769 Math3d::MulMatVec(completeRotation, center, temp1);
770 Math3d::MulMatVec(rotICP, transShift, temp2);
771 Math3d::SubtractVecVec(temp2, temp1, completeTranslation);
772 Math3d::AddToVec(completeTranslation, transICP);
773}
774
777{
779 result.x = point.x;
780 result.y = point.y;
781 result.z = point.z;
782 float intensity = point.r + point.g + point.b + 3;
783 float intensityInverse = 1.0f / intensity;
784 result.r = intensityInverse * (point.r + 1);
785 result.g = intensityInverse * (point.g + 1);
786 result.b = intensityInverse * (point.b + 1);
787 result.i = intensity / (3.0f * 256.0f);
788 return result;
789}
#define float
Definition 16_Level.h:22
#define M_PI
Definition MathTools.h:17
#define OLP_MINIMAL_MOTION_MEASURE
#define OLP_ICP_COLOR_DISTANCE_WEIGHT
#define OLP_ICP_CUTOFF_DISTANCE
#define OLP_TOLERANCE_CONCURRENT_MOTION
static CPointXYZRGBI ConvertToXYZRGBI(CHypothesisPoint *pPoint)
Definition ColorICP.cpp:343
std::vector< CHypothesisPoint * > aNewPoints
std::vector< CHypothesisPoint * > aDoubtablePoints
std::vector< CHypothesisPoint * > aConfirmedPoints
void SetScenePointcloud(const std::vector< CHypothesisPoint * > &aScenePoints)
static void GetCompleteTransformation(Mat3d rotICP, Vec3d transICP, Mat3d rotShift, Vec3d transShift, Vec3d center, Mat3d &completeRotation, Vec3d &completeTranslation)
static CColorICP::CPointXYZRGBI ConvertPclToXYZRGBI(pcl::PointXYZRGBA point)
static void RotatePoints(std::vector< CColorICP::CPointXYZRGBI > &points, const Mat3d rot)
float EstimateTransformation(const std::vector< CHypothesisPoint * > &aObjectPoints, const Vec3d center, Mat3d &mRotation, Vec3d &vTranslation, const Vec3d upwardsVector, const int nEffortLevel=OLP_EFFORT_POINTCLOUD_MATCHING, const std::vector< Vec3d > *pPossibleLocationOffsets=NULL, std::vector< CColorICP::CPointXYZRGBI > *pNearestNeighbors=NULL, std::vector< float > *pPointMatchDistances=NULL, const std::vector< CHypothesisPoint * > *pAdditionalPoints=NULL, const float maxAcceptedDistance=FLT_MAX)
bool CheckObjectMatchAtOriginalPosition(const CObjectHypothesis *pHypothesis, float &distance, const int nEffortLevel=OLP_EFFORT_POINTCLOUD_MATCHING)
#define ARMARX_VERBOSE_S
Definition Logging.h:207
double distance(const Point &a, const Point &b)
Definition point.hpp:95