00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00038 #include <gtest/gtest.h>
00039 
00040 #include <vector>
00041 
00042 #include <stdio.h>
00043 
00044 using namespace std;
00045 
00046 #include <pcl/common/time.h>
00047 #include <pcl/point_cloud.h>
00048 #include <pcl/point_types.h>
00049 
00050 using namespace pcl;
00051 
00052 #include <pcl/search/pcl_search.h>
00053 
00054 
00055 
00056 class prioPointQueueEntry
00057 {
00058 public:
00059   prioPointQueueEntry ()
00060   {
00061   }
00062   prioPointQueueEntry (PointXYZ& point_arg, double pointDistance_arg, int pointIdx_arg)
00063   {
00064     point_ = point_arg;
00065     pointDistance_ = pointDistance_arg;
00066     pointIdx_ = pointIdx_arg;
00067   }
00068 
00069   bool
00070   operator< (const prioPointQueueEntry& rhs_arg) const
00071   {
00072     return (this->pointDistance_ < rhs_arg.pointDistance_);
00073   }
00074 
00075   PointXYZ point_;
00076   double pointDistance_;int pointIdx_;
00077 
00078 };
00079 
00080 TEST (PCL, Organized_Neighbor_Pointcloud_Nearest_K_Neighbour_Search)
00081 {
00082 
00083   const unsigned int test_runs = 2;
00084   unsigned int test_id;
00085 
00086   
00087   PointCloud<PointXYZ>::Ptr cloudIn (new PointCloud<PointXYZ> ());
00088 
00089   size_t i;
00090 
00091   srand (int (time (NULL)));
00092 
00093   unsigned int K;
00094 
00095   
00096         search::OrganizedNeighbor<PointXYZ> organizedNeighborSearch;
00097 
00098   std::vector<int> k_indices;
00099   std::vector<float> k_sqr_distances;
00100 
00101   std::vector<int> k_indices_bruteforce;
00102   std::vector<float> k_sqr_distances_bruteforce;
00103 
00104   
00105   const double oneOverFocalLength = 0.0018;
00106   double x,y,z;
00107 
00108   int xpos, ypos, centerX, centerY;
00109 
00110   for (test_id = 0; test_id < test_runs; test_id++)
00111   {
00112     
00113 
00114     K = (rand () % 10)+1;
00115 
00116     
00117     cloudIn->width = 128;
00118     cloudIn->height = 32;
00119     cloudIn->points.clear();
00120     cloudIn->points.reserve (cloudIn->width * cloudIn->height);
00121 
00122     centerX = cloudIn->width>>1;
00123     centerY = cloudIn->height>>1;
00124 
00125     for (ypos = -centerY; ypos < centerY; ypos++)
00126       for (xpos = -centerX; xpos < centerX; xpos++)
00127       {
00128         z = 15.0 * (double (rand ()) / double (RAND_MAX+1.0))+20;
00129         y = double (ypos * oneOverFocalLength * z);
00130         x = double (xpos * oneOverFocalLength * z);
00131 
00132         cloudIn->points.push_back (PointXYZ (float (x), float (y), float (z)));
00133       }
00134 
00135     unsigned int searchIdx = rand()%(cloudIn->width * cloudIn->height);
00136     const PointXYZ& searchPoint = cloudIn->points[searchIdx];
00137 
00138     k_indices.clear();
00139     k_sqr_distances.clear();
00140 
00141     
00142     organizedNeighborSearch.setInputCloud (cloudIn);
00143     organizedNeighborSearch.nearestKSearch (searchPoint, int (K), k_indices, k_sqr_distances);
00144 
00145 
00146     double pointDist;
00147 
00148     k_indices_bruteforce.clear();
00149     k_sqr_distances_bruteforce.clear();
00150 
00151     std::priority_queue<prioPointQueueEntry, std::vector<prioPointQueueEntry, Eigen::aligned_allocator<prioPointQueueEntry> > > pointCandidates;
00152 
00153 
00154     
00155     for (i = 0; i < cloudIn->points.size (); i++)
00156     {
00157       pointDist = ((cloudIn->points[i].x - searchPoint.x) * (cloudIn->points[i].x - searchPoint.x) +
00158               (cloudIn->points[i].y - searchPoint.y) * (cloudIn->points[i].y - searchPoint.y) +
00159                    (cloudIn->points[i].z - searchPoint.z) * (cloudIn->points[i].z - searchPoint.z));
00160 
00161       prioPointQueueEntry pointEntry (cloudIn->points[i], pointDist, int (i));
00162 
00163       pointCandidates.push (pointEntry);
00164     }
00165 
00166     
00167     while (pointCandidates.size () > K)
00168       pointCandidates.pop ();
00169 
00170     
00171     while (pointCandidates.size ())
00172     {
00173       k_indices_bruteforce.push_back (pointCandidates.top ().pointIdx_);
00174       k_sqr_distances_bruteforce.push_back (float (pointCandidates.top ().pointDistance_));
00175 
00176       pointCandidates.pop ();
00177     }
00178 
00179 
00180     ASSERT_EQ ( k_indices.size() , k_indices_bruteforce.size() );
00181 
00182     
00183     for (i = 0; i < k_indices.size (); i++)
00184     {
00185       ASSERT_EQ ( k_indices[i] , k_indices_bruteforce.back() );
00186       EXPECT_NEAR (k_sqr_distances[i], k_sqr_distances_bruteforce.back(), 1e-4);
00187 
00188       k_indices_bruteforce.pop_back();
00189       k_sqr_distances_bruteforce.pop_back();
00190     }
00191 
00192   }
00193 
00194 }
00195 
00196 TEST (PCL, Organized_Neighbor_Pointcloud_Neighbours_Within_Radius_Search)
00197 {
00198 
00199   const unsigned int test_runs = 10;
00200   unsigned int test_id;
00201 
00202   size_t i,j;
00203 
00204   srand (int (time (NULL)));
00205 
00206         search::OrganizedNeighbor<PointXYZ> organizedNeighborSearch;
00207 
00208   std::vector<int> k_indices;
00209   std::vector<float> k_sqr_distances;
00210 
00211   std::vector<int> k_indices_bruteforce;
00212   std::vector<float> k_sqr_distances_bruteforce;
00213 
00214   
00215   const double oneOverFocalLength = 0.0018;
00216   double x,y,z;
00217 
00218   int xpos, ypos, centerX, centerY, idx;
00219 
00220   for (test_id = 0; test_id < test_runs; test_id++)
00221   {
00222     
00223     PointCloud<PointXYZ>::Ptr cloudIn (new PointCloud<PointXYZ> ());
00224 
00225     cloudIn->width = 640;
00226     cloudIn->height = 480;
00227     cloudIn->points.clear();
00228     cloudIn->points.resize (cloudIn->width * cloudIn->height);
00229 
00230     centerX = cloudIn->width>>1;
00231     centerY = cloudIn->height>>1;
00232 
00233     idx = 0;
00234     for (ypos = -centerY; ypos < centerY; ypos++)
00235       for (xpos = -centerX; xpos < centerX; xpos++)
00236       {
00237         z = 5.0 * ( (double (rand ()) / double (RAND_MAX)))+5;
00238         y = ypos*oneOverFocalLength*z;
00239         x = xpos*oneOverFocalLength*z;
00240 
00241         cloudIn->points[idx++]= PointXYZ (float (x), float (y), float (z));
00242       }
00243 
00244     unsigned int randomIdx = rand()%(cloudIn->width * cloudIn->height);
00245 
00246     const PointXYZ& searchPoint = cloudIn->points[randomIdx];
00247 
00248     double pointDist;
00249     double searchRadius = 1.0 * (double (rand ()) / double (RAND_MAX));
00250 
00251     int minX = cloudIn->width;
00252     int minY = cloudIn->height;
00253     int maxX = 0;
00254     int maxY = 0;
00255 
00256     
00257     vector<int> cloudSearchBruteforce;
00258     cloudSearchBruteforce.clear();
00259 
00260     for (i = 0; i < cloudIn->points.size (); i++)
00261     {
00262       pointDist = sqrt (
00263                         (cloudIn->points[i].x - searchPoint.x) * (cloudIn->points[i].x - searchPoint.x)
00264                       + (cloudIn->points[i].y - searchPoint.y) * (cloudIn->points[i].y - searchPoint.y)
00265                       + (cloudIn->points[i].z - searchPoint.z) * (cloudIn->points[i].z - searchPoint.z));
00266 
00267       if (pointDist <= searchRadius)
00268       {
00269         
00270         cloudSearchBruteforce.push_back (int (i));
00271 
00272         minX = std::min<int>(minX, int (i) % cloudIn->width);
00273         minY = std::min<int>(minY, int (i) / cloudIn->width);
00274         maxX = std::max<int>(maxX, int (i) % cloudIn->width);
00275         maxY = std::max<int>(maxY, int (i) / cloudIn->width);
00276       }
00277     }
00278 
00279                 std::vector<int> cloudNWRSearch;
00280                 std::vector<float> cloudNWRRadius;
00281 
00282     
00283     organizedNeighborSearch.setInputCloud (cloudIn);
00284     organizedNeighborSearch.radiusSearch (searchPoint, searchRadius, cloudNWRSearch, cloudNWRRadius);
00285 
00286     
00287     std::vector<int>::const_iterator current = cloudNWRSearch.begin();
00288     while (current != cloudNWRSearch.end())
00289     {
00290       pointDist = sqrt (
00291           (cloudIn->points[*current].x-searchPoint.x) * (cloudIn->points[*current].x-searchPoint.x) +
00292           (cloudIn->points[*current].y-searchPoint.y) * (cloudIn->points[*current].y-searchPoint.y) +
00293           (cloudIn->points[*current].z-searchPoint.z) * (cloudIn->points[*current].z-searchPoint.z)
00294       );
00295 
00296       ASSERT_EQ ( (pointDist<=searchRadius) , true);
00297 
00298       ++current;
00299     }
00300 
00301 
00302     
00303     current = cloudSearchBruteforce.begin();
00304     while (current != cloudSearchBruteforce.end())
00305     {
00306 
00307       pointDist = sqrt (
00308           (cloudIn->points[*current].x-searchPoint.x) * (cloudIn->points[*current].x-searchPoint.x) +
00309           (cloudIn->points[*current].y-searchPoint.y) * (cloudIn->points[*current].y-searchPoint.y) +
00310           (cloudIn->points[*current].z-searchPoint.z) * (cloudIn->points[*current].z-searchPoint.z)
00311       );
00312 
00313       ASSERT_EQ ( (pointDist<=searchRadius) , true);
00314 
00315       ++current;
00316     }
00317 
00318     for (i = 0; i < cloudSearchBruteforce.size (); i++) 
00319       for (j = 0; j < cloudNWRSearch.size (); j++) 
00320         if (cloudNWRSearch[i]== cloudSearchBruteforce[j])
00321           break;
00322 
00323     ASSERT_EQ (cloudNWRRadius.size() , cloudSearchBruteforce.size ());
00324 
00325     
00326     organizedNeighborSearch.radiusSearch (searchPoint, searchRadius, cloudNWRSearch, cloudNWRRadius, 5);
00327 
00328     ASSERT_EQ (cloudNWRRadius.size () <= 5, true);
00329   }
00330 }
00331 
00332 
00333 int
00334 main (int argc, char** argv)
00335 {
00336   testing::InitGoogleTest (&argc, argv);
00337   return (RUN_ALL_TESTS ());
00338 }
00339