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  */
24 #include "PointCloudRegistration.h"
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
63 void
64 CPointCloudRegistration::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 
84 float
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 
482 bool
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 /*
573 bool 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 
645 float
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 
727 void
728 CPointCloudRegistration::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 
757 void
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 }
OLP_ICP_COLOR_DISTANCE_WEIGHT
#define OLP_ICP_COLOR_DISTANCE_WEIGHT
Definition: ObjectLearningByPushingDefinitions.h:252
PointCloudRegistration.h
CPointCloudRegistration::EstimateTransformation
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)
Definition: PointCloudRegistration.cpp:85
CPointCloudRegistration::RotatePoints
static void RotatePoints(std::vector< CColorICP::CPointXYZRGBI > &points, const Mat3d rot)
Definition: PointCloudRegistration.cpp:728
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:737
OLP_ICP_CUTOFF_DISTANCE
#define OLP_ICP_CUTOFF_DISTANCE
Definition: ObjectLearningByPushingDefinitions.h:254
CColorICP::CPointXYZRGBI::x
float x
Definition: ColorICP.h:38
CColorICP::CPointXYZRGBI::y
float y
Definition: ColorICP.h:38
CPointCloudRegistration::ConvertPclToXYZRGBI
static CColorICP::CPointXYZRGBI ConvertPclToXYZRGBI(pcl::PointXYZRGBA point)
Definition: PointCloudRegistration.cpp:776
CColorICP::GetPointMatchDistances
void GetPointMatchDistances(const std::vector< CPointXYZRGBI > &aObjectPoints, std::vector< float > &aPointMatchDistances)
Definition: ColorICP.cpp:279
CColorICP::SetScenePointcloud
void SetScenePointcloud(std::vector< CPointXYZRGBI > aScenePoints)
Definition: ColorICP.cpp:58
CColorICP::SetParameters
void SetParameters(float fColorWeight=OLP_ICP_COLOR_DISTANCE_WEIGHT, float fCutoffDistance=FLT_MAX, float fConvergenceDelta=0.01f, int nMaxIterations=30, int nKdTreeBucketSize=50)
Definition: ColorICP.cpp:238
CColorICP::SearchObject
float SearchObject(const std::vector< CPointXYZRGBI > &aObjectPoints, Mat3d &mRotation, Vec3d &vTranslation, const float fBestDistanceUntilNow=FLT_MAX)
Definition: ColorICP.cpp:109
CColorICP::CPointXYZRGBI::g
float g
Definition: ColorICP.h:38
CPointCloudRegistration::CPointCloudRegistration
CPointCloudRegistration()
Definition: PointCloudRegistration.cpp:36
CColorICP::CPointXYZRGBI::i
float i
Definition: ColorICP.h:38
CColorICP::CPointXYZRGBI::r
float r
Definition: ColorICP.h:38
OLPTools.h
OLP_MIN_NUM_FEATURES
#define OLP_MIN_NUM_FEATURES
Definition: ObjectLearningByPushingDefinitions.h:109
M_PI
#define M_PI
Definition: MathTools.h:17
OLP_TOLERANCE_CONCURRENT_MOTION
#define OLP_TOLERANCE_CONCURRENT_MOTION
Definition: ObjectLearningByPushingDefinitions.h:238
CObjectHypothesis::vCenter
Vec3d vCenter
Definition: ObjectHypothesis.h:311
CColorICP::GetNearestNeighbors
void GetNearestNeighbors(const std::vector< CPointXYZRGBI > &aObjectPoints, std::vector< CColorICP::CPointXYZRGBI > &aNeighbors, std::vector< float > &aPointMatchDistances)
Definition: ColorICP.cpp:305
CColorICP::CPointXYZRGBI
Definition: ColorICP.h:36
CPointCloudRegistration::GetCompleteTransformation
static void GetCompleteTransformation(Mat3d rotICP, Vec3d transICP, Mat3d rotShift, Vec3d transShift, Vec3d center, Mat3d &completeRotation, Vec3d &completeTranslation)
Definition: PointCloudRegistration.cpp:758
CColorICP::CPointXYZRGBI::b
float b
Definition: ColorICP.h:38
CObjectHypothesis
Definition: ObjectHypothesis.h:244
float
#define float
Definition: 16_Level.h:22
CObjectHypothesis::aNewPoints
std::vector< CHypothesisPoint * > aNewPoints
Definition: ObjectHypothesis.h:294
CColorICP::ConvertToXYZRGBI
static CPointXYZRGBI ConvertToXYZRGBI(CHypothesisPoint *pPoint)
Definition: ColorICP.cpp:343
CObjectHypothesis::aDoubtablePoints
std::vector< CHypothesisPoint * > aDoubtablePoints
Definition: ObjectHypothesis.h:296
CPointCloudRegistration::CheckObjectMatchAtOriginalPosition
bool CheckObjectMatchAtOriginalPosition(const CObjectHypothesis *pHypothesis, float &distance, const int nEffortLevel=OLP_EFFORT_POINTCLOUD_MATCHING)
Definition: PointCloudRegistration.cpp:483
CColorICP::CPointXYZRGBI::z
float z
Definition: ColorICP.h:38
CObjectHypothesis::aConfirmedPoints
std::vector< CHypothesisPoint * > aConfirmedPoints
Definition: ObjectHypothesis.h:295
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:95
CPointCloudRegistration::~CPointCloudRegistration
~CPointCloudRegistration()
Definition: PointCloudRegistration.cpp:50
CColorICP
Definition: ColorICP.h:33
Logging.h
OLP_MINIMAL_MOTION_MEASURE
#define OLP_MINIMAL_MOTION_MEASURE
Definition: ObjectLearningByPushingDefinitions.h:240
min
T min(T t1, T t2)
Definition: gdiam.h:44
CPointCloudRegistration::SetScenePointcloud
void SetScenePointcloud(const std::vector< CHypothesisPoint * > &aScenePoints)
Definition: PointCloudRegistration.cpp:64