test_distance_field.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2009, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00037 #include <gtest/gtest.h>
00038 
00039 #include <moveit/distance_field/voxel_grid.h>
00040 #include <moveit/distance_field/propagation_distance_field.h>
00041 #include <moveit/distance_field/distance_field_common.h>
00042 #include <console_bridge/console.h>
00043 #include <geometric_shapes/body_operations.h>
00044 #include <eigen_conversions/eigen_msg.h>
00045 #include <octomap/octomap.h>
00046 #include <boost/make_shared.hpp>
00047 
00048 using namespace distance_field;
00049 
00050 static const double width = 1.0;
00051 static const double height = 1.0;
00052 static const double depth = 1.0;
00053 static const double resolution = 0.1;
00054 static const double origin_x = 0.0;
00055 static const double origin_y = 0.0;
00056 static const double origin_z = 0.0;
00057 static const double max_dist = 0.3;
00058 
00059 static const int max_dist_in_voxels = max_dist/resolution+0.5;
00060 static const int max_dist_sq_in_voxels = max_dist_in_voxels*max_dist_in_voxels;
00061 
00062 static const Eigen::Vector3d point1(0.1,0.0,0.0);
00063 static const Eigen::Vector3d point2(0.0,0.1,0.2);
00064 static const Eigen::Vector3d point3(0.4,0.0,0.0);
00065 
00066 int dist_sq(int x, int y, int z)
00067 {
00068   return x*x + y*y +z*z;
00069 }
00070 
00071 void print( PropagationDistanceField& pdf, int numX, int numY, int numZ)
00072 {
00073   for (int z=0; z<numZ; z++) {
00074     for (int x=0; x<numX; x++) {
00075       for (int y=0; y<numY; y++) {
00076         std::cout << pdf.getCell(x,y,z).distance_square_ << " ";
00077       }
00078       std::cout << std::endl;
00079     }
00080     std::cout << std::endl;
00081   }
00082   for (int z=0; z<numZ; z++) {
00083     for (int x=0; x<numX; x++) {
00084       for (int y=0; y<numY; y++) {
00085         if(pdf.getCell(x,y,z).distance_square_ == 0) {
00086           //logInform("Obstacle cell %d %d %d", x, y, z);
00087         }
00088       }
00089     }
00090   }
00091 }
00092 
00093 void printNeg(PropagationDistanceField& pdf, int numX, int numY, int numZ)
00094 {
00095   for (int z=0; z<numZ; z++) {
00096     for (int x=0; x<numX; x++) {
00097       for (int y=0; y<numY; y++) {
00098         std::cout << pdf.getCell(x,y,z).negative_distance_square_ << " ";
00099       }
00100       std::cout << std::endl;
00101     }
00102     std::cout << std::endl;
00103   }
00104 }
00105 
00106 bool areDistanceFieldsDistancesEqual(const PropagationDistanceField& df1,
00107                                      const PropagationDistanceField& df2)
00108 {
00109   if(df1.getXNumCells() != df2.getXNumCells()) return false;
00110   if(df1.getYNumCells() != df2.getYNumCells()) return false;
00111   if(df1.getZNumCells() != df2.getZNumCells()) return false;
00112   for (int z=0; z<df1.getZNumCells(); z++) {
00113     for (int x=0; x<df1.getXNumCells(); x++) {
00114       for (int y=0; y<df1.getYNumCells(); y++) {
00115         if(df1.getCell(x,y,z).distance_square_ != df2.getCell(x,y,z).distance_square_) {
00116           printf("Cell %d %d %d distances not equal %d %d\n",x,y,z,
00117                  df1.getCell(x,y,z).distance_square_,df2.getCell(x,y,z).distance_square_);
00118           return false;
00119         }
00120         if(df1.getCell(x,y,z).negative_distance_square_ != df2.getCell(x,y,z).negative_distance_square_) {
00121           printf("Cell %d %d %d neg distances not equal %d %d\n",x,y,z,
00122                  df1.getCell(x,y,z).negative_distance_square_,df2.getCell(x,y,z).negative_distance_square_);
00123           return false;
00124         }
00125       }
00126     }
00127   }
00128   return true;
00129 }
00130 
00131 bool checkOctomapVersusDistanceField(const PropagationDistanceField& df,
00132                                      const octomap::OcTree& octree)
00133 {
00134   //just one way for now
00135   for (int z=0; z<df.getZNumCells(); z++) {
00136     for (int x=0; x<df.getXNumCells(); x++) {
00137       for (int y=0; y<df.getYNumCells(); y++) {
00138         if(df.getCell(x,y,z).distance_square_ == 0) {
00139           //making sure that octomap also shows it as occupied
00140           double qx, qy, qz;
00141           df.gridToWorld(x,y,z,
00142                          qx, qy, qz);
00143           octomap::point3d query(qx, qy, qz);
00144           octomap::OcTreeNode* result = octree.search(query);
00145           if(!result) {
00146             for(float boundary_x = query.x()-df.getResolution();
00147                 boundary_x <= query.x()+df.getResolution() && !result;
00148                 boundary_x += df.getResolution()) {
00149               for(float boundary_y = query.y()-df.getResolution();
00150                   boundary_y <= query.y()+df.getResolution() && !result;
00151                   boundary_y += df.getResolution()) {
00152                 for(float boundary_z = query.z()-df.getResolution();
00153                     boundary_z <= query.z()+df.getResolution();
00154                     boundary_z += df.getResolution()) {
00155                   octomap::point3d query_boundary(boundary_x, boundary_y, boundary_z);
00156                   result = octree.search(query_boundary);
00157                   if(result) {
00158                     break;
00159                   }
00160                 }
00161               }
00162             }
00163             if(!result) {
00164               std::cout << "No point at potential boundary query " << query.x() << " " << query.y() << " " << query.z() << std::endl;
00165               return false;
00166             }
00167           }
00168           if(!octree.isNodeOccupied(result)) {
00169             std::cout << "Disagreement at " << qx << " " << qy << " " << qz << std::endl;
00170             return false;
00171           }
00172         }
00173       }
00174     }
00175   }
00176   return true;
00177 }
00178 
00179 unsigned int countOccupiedCells(const PropagationDistanceField& df)
00180 {
00181   unsigned int count = 0;
00182   for (int z=0; z<df.getZNumCells(); z++) {
00183     for (int x=0; x<df.getXNumCells(); x++) {
00184       for (int y=0; y<df.getYNumCells(); y++) {
00185         if(df.getCell(x,y,z).distance_square_ == 0) {
00186           count++;
00187         }
00188       }
00189     }
00190   }
00191   return count;
00192 }
00193 
00194 unsigned int countLeafNodes(const octomap::OcTree& octree)
00195 {
00196   unsigned int count = 0;
00197   for(octomap::OcTree::leaf_iterator it = octree.begin_leafs(),
00198         end=octree.end_leafs(); it!= end; ++it)
00199   {
00200     if (octree.isNodeOccupied(*it))
00201     {
00202       std::cout << "Leaf node " << it.getX() << " " << it.getY() << " " << it.getZ() << std::endl;
00203       count++;
00204     }
00205   }
00206   return count;
00207 }
00208 
00209 //points should contain all occupied points
00210 void check_distance_field(const PropagationDistanceField & df,
00211                           const EigenSTL::vector_Vector3d& points,
00212                           int numX, int numY, int numZ,
00213                           bool do_negs)
00214 {
00215   std::vector<Eigen::Vector3i> points_ind(points.size());
00216   for(unsigned int i = 0; i < points.size(); i++) {
00217     Eigen::Vector3i loc;
00218     bool valid = df.worldToGrid(points[i].x(), points[i].y(), points[i].z(),
00219                                 loc.x(), loc.y(), loc.z() );
00220     points_ind[i] = loc;
00221   }
00222 
00223   for (int x=0; x<numX; x++) {
00224     for (int y=0; y<numY; y++) {
00225       for (int z=0; z<numZ; z++) {
00226         double dsq = df.getCell(x, y, z).distance_square_;
00227         double ndsq = df.getCell(x, y, z).negative_distance_square_;
00228         if(dsq == 0) {
00229           bool found = false;
00230           for(unsigned int i = 0; i < points_ind.size(); i++) {
00231             if(points_ind[i].x() == x && points_ind[i].y() == y && points_ind[i].z() == z) {
00232               found = true;
00233               break;
00234             }
00235           }
00236           if(do_negs) {
00237             ASSERT_GT(ndsq, 0) << "Obstacle point " << x << " " << y << " " << z << " has zero negative value";
00238           }
00239           ASSERT_TRUE(found) << "Obstacle point " << x << " " << y << " " << z << " not found";
00240         }
00241       }
00242     }
00243   }
00244 }
00245 
00246 
00247 TEST(TestPropagationDistanceField, TestAddRemovePoints)
00248 {
00249   PropagationDistanceField df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist);
00250 
00251   // Check size
00252   int numX = df.getXNumCells();
00253   int numY = df.getYNumCells();
00254   int numZ = df.getZNumCells();
00255 
00256   EXPECT_EQ( numX, (int)(width/resolution+0.5) );
00257   EXPECT_EQ( numY, (int)(height/resolution+0.5) );
00258   EXPECT_EQ( numZ, (int)(depth/resolution+0.5) );
00259 
00260   //getting a bad point
00261   double tgx, tgy, tgz;
00262   bool in_bounds;
00263   EXPECT_NEAR(df.getDistance(1000.0,1000.0,1000.0), max_dist, .0001);
00264   EXPECT_NEAR(df.getDistanceGradient(1000.0,1000.0,1000.0, tgx, tgy, tgz, in_bounds), max_dist, .0001);
00265   EXPECT_FALSE(in_bounds);
00266 
00267   // Add points to the grid
00268   EigenSTL::vector_Vector3d points;
00269   points.push_back(point1);
00270   points.push_back(point2);
00271   logInform("Adding %u points", points.size());
00272   df.addPointsToField(points);
00273   //print(df, numX, numY, numZ);
00274 
00275   // Update - iterative
00276   points.clear();
00277   points.push_back(point2);
00278   points.push_back(point3);
00279   EigenSTL::vector_Vector3d old_points;
00280   old_points.push_back(point1);
00281   df.updatePointsInField(old_points, points);
00282   //std::cout << "One removal, one addition" << std::endl;
00283   //print(df, numX, numY, numZ);
00284   //printNeg(df, numX, numY, numZ);
00285   check_distance_field(df, points, numX, numY, numZ, false);
00286 
00287   // Remove
00288   points.clear();
00289   points.push_back(point2);
00290   df.removePointsFromField(points);
00291   points.clear();
00292   points.push_back(point3);
00293   check_distance_field( df, points, numX, numY, numZ, false);
00294 
00295   //now testing gradient calls
00296   df.reset();
00297   points.clear();
00298   points.push_back(point1);
00299   df.addPointsToField(points);
00300   bool first = true;
00301   for (int z=1; z<df.getZNumCells()-1; z++) {
00302     for (int x=1; x<df.getXNumCells()-1; x++) {
00303       for (int y=1; y<df.getYNumCells()-1; y++) {
00304         double dist = df.getDistance(x,y,z);
00305         double wx, wy, wz;
00306         df.gridToWorld(x,y,z,wx,wy,wz);
00307         Eigen::Vector3d grad(0.0,0.0,0.0);
00308         bool grad_in_bounds;
00309         double dist_grad = df.getDistanceGradient(wx, wy, wz,
00310                                                   grad.x(), grad.y(), grad.z(), grad_in_bounds);
00311         ASSERT_TRUE(grad_in_bounds) << x << " " << y << " " << z;
00312         ASSERT_NEAR(dist, dist_grad, .0001);
00313         if(dist > 0 &&
00314            dist < max_dist) {
00315           double xscale = grad.x()/grad.norm();
00316           double yscale = grad.y()/grad.norm();
00317           double zscale = grad.z()/grad.norm();
00318 
00319           double comp_x = wx-xscale*dist;
00320           double comp_y = wy-yscale*dist;
00321           double comp_z = wz-zscale*dist;
00322           if(first) {
00323             first = false;
00324             std::cout << "Dist " << dist << std::endl;
00325             std::cout << "Cell " << x << " " << y << " " << z << " " << wx << " " << wy << " " << wz << std::endl;
00326             std::cout << "Scale " << xscale << " " << yscale << " " << zscale << std::endl;
00327             std::cout << "Grad " << grad.x() << " " << grad.y() << " " << grad.z() << " comp " << comp_x << " " << comp_y << " " << comp_z << std::endl;
00328           }
00329           ASSERT_NEAR(comp_x, point1.x(), resolution) << dist << x << " " << y << " " << z << " " << grad.x() << " " << grad.y() << " " << grad.z() << " " << xscale << " " << yscale << " " << zscale << std::endl;
00330           ASSERT_NEAR(comp_y, point1.y(), resolution) << x << " " << y << " " << z << " " << grad.x() << " " << grad.y() << " " << grad.z() << " " << xscale << " " << yscale << " " << zscale << std::endl;
00331           ASSERT_NEAR(comp_z, point1.z(), resolution) << x << " " << y << " " << z << " " << grad.x() << " " << grad.y() << " " << grad.z() << " " << xscale << " " << yscale << " " << zscale << std::endl;
00332         }
00333       }
00334     }
00335   }
00336   ASSERT_FALSE(first);
00337 }
00338 
00339 TEST(TestSignedPropagationDistanceField, TestSignedAddRemovePoints)
00340 {
00341 
00342   PropagationDistanceField df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist, true);
00343 
00344   // Check size
00345   int numX = df.getXNumCells();
00346   int numY = df.getYNumCells();
00347   int numZ = df.getZNumCells();
00348 
00349   EXPECT_EQ( numX, (int)(width/resolution+0.5) );
00350   EXPECT_EQ( numY, (int)(height/resolution+0.5) );
00351   EXPECT_EQ( numZ, (int)(depth/resolution+0.5) );
00352 
00353   // Error checking
00354   //print(df, numX, numY, numZ);
00355 
00356   // TODO - check initial values
00357   //EXPECT_EQ( df.getCell(0,0,0).distance_square_, max_dist_sq_in_voxels );
00358 
00359   // Add points to the grid
00360   double lwx, lwy, lwz;
00361   double hwx, hwy, hwz;
00362   df.gridToWorld(1,1,1,lwx,lwy,lwz);
00363   df.gridToWorld(8,8,8,hwx,hwy,hwz);
00364 
00365   EigenSTL::vector_Vector3d points;
00366   for(double x = lwx; x <= hwx; x+= .1) {
00367     for(double y = lwy; y <= hwy; y+= .1) {
00368       for(double z = lwz; z <= hwz; z+= .1) {
00369         points.push_back(Eigen::Vector3d(x,y,z));
00370       }
00371     }
00372   }
00373 
00374   df.reset();
00375   logInform("Adding %u points", points.size());
00376   df.addPointsToField(points);
00377   //print(df, numX, numY, numZ);
00378   //printNeg(df, numX, numY, numZ);
00379 
00380   double cx, cy, cz;
00381   df.gridToWorld(5,5,5,cx,cy,cz);
00382 
00383   Eigen::Vector3d center_point(cx,cy,cz);
00384 
00385   EigenSTL::vector_Vector3d rem_points;
00386   rem_points.push_back(center_point);
00387   df.removePointsFromField(rem_points);
00388   //std::cout << "Pos "<< std::endl;
00389   //print(df, numX, numY, numZ);
00390   //std::cout << "Neg "<< std::endl;
00391   //printNeg(df, numX, numY, numZ);
00392 
00393   //testing equality with initial add of points without the center point
00394   PropagationDistanceField test_df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist, true);
00395   EigenSTL::vector_Vector3d test_points;
00396   for(unsigned int i = 0; i < points.size(); i++) {
00397     if(points[i].x() != center_point.x() ||
00398        points[i].y() != center_point.y() ||
00399        points[i].z() != center_point.z())
00400     {
00401       test_points.push_back(points[i]);
00402     }
00403   }
00404   test_df.addPointsToField(test_points);
00405   ASSERT_TRUE(areDistanceFieldsDistancesEqual(df, test_df));
00406 
00407   PropagationDistanceField gradient_df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist, true);
00408 
00409   shapes::Sphere sphere(.25);
00410 
00411   geometry_msgs::Pose p;
00412   p.orientation.w = 1.0;
00413   p.position.x = .5;
00414   p.position.y = .5;
00415   p.position.z = .5;
00416 
00417   gradient_df.addShapeToField(&sphere, p);
00418   printNeg(gradient_df, numX, numY, numZ);
00419   EXPECT_GT(gradient_df.getCell(5,5,5).negative_distance_square_, 1);
00420   //all negative cells should have gradients that point towards cells with distance 1
00421   for (int z=1; z<df.getZNumCells()-1; z++) {
00422     for (int x=1; x<df.getXNumCells()-1; x++) {
00423       for (int y=1; y<df.getYNumCells()-1; y++) {
00424         if(gradient_df.getCell(x,y,z).negative_distance_square_ > 0) {
00425           double dist = gradient_df.getDistance(x,y,z);
00426           ASSERT_LT(dist, 0) << "Pos " << gradient_df.getCell(x,y,z).distance_square_ << " " << gradient_df.getCell(x,y,z).negative_distance_square_;
00427           double wx, wy, wz;
00428           df.gridToWorld(x,y,z,wx,wy,wz);
00429           Eigen::Vector3d grad(0.0,0.0,0.0);
00430           bool grad_in_bounds;
00431           double dist_grad = gradient_df.getDistanceGradient(wx, wy, wz,
00432                                                              grad.x(), grad.y(), grad.z(), grad_in_bounds);
00433           ASSERT_TRUE(grad_in_bounds) << x << " " << y << " " << z;
00434           ASSERT_NEAR(dist, dist_grad, .0001);
00435           double xscale = grad.x()/grad.norm();
00436           double yscale = grad.y()/grad.norm();
00437           double zscale = grad.z()/grad.norm();
00438 
00439           double comp_x = wx-xscale*dist;
00440           double comp_y = wy-yscale*dist;
00441           double comp_z = wz-zscale*dist;
00442 
00443           int cell_x, cell_y, cell_z;
00444           gradient_df.worldToGrid(comp_x, comp_y, comp_z,
00445                                   cell_x, cell_y, cell_z);
00446           ASSERT_GE(gradient_df.getCell(cell_x, cell_y, cell_z).distance_square_, 1) << dist << " " << x << " " << y << " " << z << " " << grad.x() << " " << grad.y() << " " << grad.z() << " " << xscale << " " << yscale << " " << zscale << " cell " << comp_x << " " << comp_y << " " << comp_z << std::endl;
00447         }
00448       }
00449     }
00450   }
00451 }
00452 
00453 
00454 TEST(TestSignedPropagationDistanceField, TestShape)
00455 {
00456 
00457   PropagationDistanceField df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist, true);
00458 
00459   int numX = df.getXNumCells();
00460   int numY = df.getYNumCells();
00461   int numZ = df.getZNumCells();
00462 
00463   shapes::Sphere sphere(.25);
00464 
00465   geometry_msgs::Pose p;
00466   p.orientation.w = 1.0;
00467   p.position.x = .5;
00468   p.position.y = .5;
00469   p.position.z = .5;
00470 
00471   geometry_msgs::Pose np;
00472   np.orientation.w = 1.0;
00473   np.position.x = .7;
00474   np.position.y = .7;
00475   np.position.z = .7;
00476 
00477   df.addShapeToField(&sphere, p);
00478 
00479   bodies::Body* body = bodies::createBodyFromShape(&sphere);
00480   Eigen::Affine3d pose_e;
00481   tf::poseMsgToEigen(p, pose_e);
00482   body->setPose(pose_e);
00483   EigenSTL::vector_Vector3d point_vec = distance_field::determineCollisionPoints(body, resolution);
00484   delete body;
00485   check_distance_field(df, point_vec,
00486                        numX, numY, numZ, true);
00487 
00488   // std::cout << "Shape pos "<< std::endl;
00489   // print(df, numX, numY, numZ);
00490   // std::cout << "Shape neg "<< std::endl;
00491   // printNeg(df, numX, numY, numZ);
00492 
00493   df.addShapeToField(&sphere, np);
00494 
00495   body = bodies::createBodyFromShape(&sphere);
00496   Eigen::Affine3d npose_e;
00497   tf::poseMsgToEigen(np, npose_e);
00498   body->setPose(npose_e);
00499 
00500   EigenSTL::vector_Vector3d point_vec_2 = distance_field::determineCollisionPoints(body, resolution);
00501   delete body;
00502   EigenSTL::vector_Vector3d point_vec_union = point_vec_2;
00503   point_vec_union.insert(point_vec_union.end(),
00504                          point_vec.begin(),
00505                          point_vec.end());
00506   check_distance_field(df, point_vec_union,
00507                        numX, numY, numZ, true);
00508 
00509   //should get rid of old pose
00510   df.moveShapeInField(&sphere, p, np);
00511 
00512   check_distance_field(df, point_vec_2,
00513                        numX, numY, numZ, true);
00514 
00515   //should be equivalent to just adding second shape
00516   PropagationDistanceField test_df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist, true);
00517   test_df.addShapeToField(&sphere, np);
00518   ASSERT_TRUE(areDistanceFieldsDistancesEqual(df, test_df));
00519 }
00520 
00521 static const double PERF_WIDTH = 3.0;
00522 static const double PERF_HEIGHT = 3.0;
00523 static const double PERF_DEPTH = 4.0;
00524 static const double PERF_RESOLUTION = 0.02;
00525 static const double PERF_ORIGIN_X = 0.0;
00526 static const double PERF_ORIGIN_Y = 0.0;
00527 static const double PERF_ORIGIN_Z = 0.0;
00528 static const double PERF_MAX_DIST = .25;
00529 static const unsigned int UNIFORM_DISTANCE = 10;
00530 
00531 TEST(TestSignedPropagationDistanceField, TestPerformance)
00532 {
00533   std::cout << "Creating distance field with " <<
00534     (PERF_WIDTH/PERF_RESOLUTION)*(PERF_HEIGHT/PERF_RESOLUTION)*(PERF_DEPTH/PERF_RESOLUTION)
00535             << " entries" << std::endl;
00536 
00537   ros::WallTime dt = ros::WallTime::now();
00538   PropagationDistanceField df( PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00539                                PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00540   std::cout << "Creating unsigned took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00541 
00542   dt = ros::WallTime::now();
00543   PropagationDistanceField sdf( PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00544                                 PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, true);
00545 
00546   std::cout << "Creating signed took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00547 
00548   shapes::Box big_table(2.0,2.0,.5);
00549 
00550   geometry_msgs::Pose p;
00551   p.orientation.w = 1.0;
00552   p.position.x = PERF_WIDTH/2.0;
00553   p.position.y = PERF_DEPTH/2.0;
00554   p.position.z = PERF_HEIGHT/2.0;
00555 
00556   geometry_msgs::Pose np;
00557   np.orientation.w = 1.0;
00558   np.position.x = p.position.x+.01;
00559   np.position.y = p.position.y;
00560   np.position.z = p.position.z;
00561 
00562   unsigned int big_num_points = ceil(2.0/PERF_RESOLUTION)*ceil(2.0/PERF_RESOLUTION)*ceil(.5/PERF_RESOLUTION);
00563 
00564   std::cout << "Adding " << big_num_points << " points" << std::endl;
00565 
00566   dt = ros::WallTime::now();
00567   df.addShapeToField(&big_table, p);
00568   std::cout << "Adding to unsigned took "
00569             << (ros::WallTime::now()-dt).toSec()
00570             << " avg " << (ros::WallTime::now()-dt).toSec()/(big_num_points*1.0)
00571             << std::endl;
00572 
00573   dt = ros::WallTime::now();
00574   df.addShapeToField(&big_table, p);
00575   std::cout << "Re-adding to unsigned took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00576 
00577   dt = ros::WallTime::now();
00578   sdf.addShapeToField(&big_table, p);
00579   std::cout << "Adding to signed took "
00580             << (ros::WallTime::now()-dt).toSec()
00581             << " avg " << (ros::WallTime::now()-dt).toSec()/(big_num_points*1.0)
00582             << std::endl;
00583 
00584   dt = ros::WallTime::now();
00585   df.moveShapeInField(&big_table, p, np);
00586   std::cout << "Moving in unsigned took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00587 
00588   dt = ros::WallTime::now();
00589   sdf.moveShapeInField(&big_table, p, np);
00590   std::cout << "Moving in signed took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00591 
00592   dt = ros::WallTime::now();
00593   df.removeShapeFromField(&big_table, np);
00594   std::cout << "Removing from unsigned took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00595 
00596   dt = ros::WallTime::now();
00597   sdf.removeShapeFromField(&big_table, np);
00598   std::cout << "Removing from signed took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00599 
00600   dt = ros::WallTime::now();
00601   df.reset();
00602 
00603   shapes::Box small_table(.25,.25,.05);
00604 
00605   unsigned int small_num_points = (13)*(13)*(3);
00606 
00607   std::cout << "Adding " << small_num_points << " points" << std::endl;
00608 
00609   dt = ros::WallTime::now();
00610   df.addShapeToField(&small_table, p);
00611   std::cout << "Adding to unsigned took "
00612             << (ros::WallTime::now()-dt).toSec()
00613             << " avg " << (ros::WallTime::now()-dt).toSec()/(small_num_points*1.0)
00614             << std::endl;
00615 
00616   dt = ros::WallTime::now();
00617   sdf.addShapeToField(&small_table, p);
00618   std::cout << "Adding to signed took "
00619             << (ros::WallTime::now()-dt).toSec()
00620             << " avg " << (ros::WallTime::now()-dt).toSec()/(small_num_points*1.0)
00621             << std::endl;
00622 
00623   dt = ros::WallTime::now();
00624   df.moveShapeInField(&small_table, p, np);
00625   std::cout << "Moving in unsigned took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00626 
00627   dt = ros::WallTime::now();
00628   sdf.moveShapeInField(&small_table, p, np);
00629   std::cout << "Moving in signed took " << (ros::WallTime::now()-dt).toSec() << std::endl;
00630 
00631   //uniformly spaced points - a worst case scenario
00632   PropagationDistanceField worstdfu(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00633                                    PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00634 
00635   PropagationDistanceField worstdfs(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00636                                    PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, true);
00637 
00638 
00639 
00640   EigenSTL::vector_Vector3d bad_vec;
00641   unsigned int count = 0;
00642   for(unsigned int z = UNIFORM_DISTANCE; z < worstdfu.getZNumCells()-UNIFORM_DISTANCE; z += UNIFORM_DISTANCE) {
00643     for(unsigned int x = UNIFORM_DISTANCE; x < worstdfu.getXNumCells()-UNIFORM_DISTANCE; x += UNIFORM_DISTANCE) {
00644       for(unsigned int y = UNIFORM_DISTANCE; y < worstdfu.getYNumCells()-UNIFORM_DISTANCE; y += UNIFORM_DISTANCE) {
00645         count++;
00646         Eigen::Vector3d loc;
00647         bool valid = worstdfu.gridToWorld(x,y,z,
00648                                           loc.x(), loc.y(), loc.z());
00649 
00650         if(!valid) {
00651           logWarn("Something wrong");
00652           continue;
00653         }
00654         bad_vec.push_back(loc);
00655       }
00656     }
00657   }
00658 
00659   dt = ros::WallTime::now();
00660   worstdfu.addPointsToField(bad_vec);
00661   ros::WallDuration wd = ros::WallTime::now()-dt;
00662   printf("Time for unsigned adding %u uniform points is %g average %g\n", (unsigned int)bad_vec.size(), wd.toSec(), wd.toSec()/(bad_vec.size()*1.0));
00663   dt = ros::WallTime::now();
00664   worstdfs.addPointsToField(bad_vec);
00665   wd = ros::WallTime::now()-dt;
00666   printf("Time for signed adding %u uniform points is %g average %g\n", (unsigned int)bad_vec.size(), wd.toSec(), wd.toSec()/(bad_vec.size()*1.0));
00667 
00668 }
00669 
00670 TEST(TestSignedPropagationDistanceField, TestOcTree)
00671 {
00672   PropagationDistanceField df(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00673                               PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00674 
00675   octomap::OcTree tree(.02);
00676 
00677   unsigned int count = 0;
00678   for(float x = 1.01; x < 1.5; x += .02) {
00679     for(float y = 1.01; y < 1.5; y += .02) {
00680       for(float z = 1.01; z < 1.5; z += .02, count++) {
00681         octomap::point3d point(x,y,z);
00682         tree.updateNode(point, true);
00683       }
00684     }
00685   }
00686 
00687   //more points at the border of the distance field
00688   for(float x = 2.51; x < 3.5; x += .02) {
00689     for(float y = 1.01; y < 3.5; y += .02) {
00690       for(float z = 1.01; z < 3.5; z += .02, count++) {
00691         octomap::point3d point(x,y,z);
00692         tree.updateNode(point, true);
00693       }
00694     }
00695   }
00696 
00697   std::cout << "OcTree nodes " << count << std::endl;
00698   df.addOcTreeToField(&tree);
00699 
00700   EXPECT_TRUE(checkOctomapVersusDistanceField(df, tree));
00701 
00702   //more cells
00703   for(float x = .01; x < .50; x += .02) {
00704     for(float y = .01; y < .50; y += .02) {
00705       for(float z = .01; z < .50; z += .02, count++) {
00706         octomap::point3d point(x,y,z);
00707         tree.updateNode(point, true);
00708       }
00709     }
00710   }
00711   df.addOcTreeToField(&tree);
00712   EXPECT_TRUE(checkOctomapVersusDistanceField(df, tree));
00713 
00714   PropagationDistanceField df_oct(tree,
00715                                  octomap::point3d(0.5,0.5,0.5),
00716                                  octomap::point3d(5.0,5.0,5.0),
00717                                  PERF_MAX_DIST,
00718                                  false);
00719 
00720   EXPECT_TRUE(checkOctomapVersusDistanceField(df_oct, tree));
00721 
00722   //now try different resolutions
00723   octomap::OcTree tree_lowres(.05);
00724   octomap::point3d point1(.5,.5,.5);
00725   octomap::point3d point2(.7,.5,.5);
00726   octomap::point3d point3(1.0,.5,.5);
00727   tree_lowres.updateNode(point1, true);
00728   tree_lowres.updateNode(point2, true);
00729   tree_lowres.updateNode(point3, true);
00730   ASSERT_EQ(countLeafNodes(tree_lowres), 3);
00731 
00732   PropagationDistanceField df_highres(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00733                                       PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00734 
00735   df_highres.addOcTreeToField(&tree_lowres);
00736   EXPECT_EQ(countOccupiedCells(df_highres), 3*(6*6*6));
00737   std::cout << "Occupied cells " << countOccupiedCells(df_highres) << std::endl;
00738 
00739   //testing adding shape that happens to be octree
00740   boost::shared_ptr<octomap::OcTree> tree_shape(new octomap::OcTree(.05));
00741   octomap::point3d tpoint1(1.0,.5,1.0);
00742   octomap::point3d tpoint2(1.7,.5,.5);
00743   octomap::point3d tpoint3(1.8,.5,.5);
00744   tree_shape->updateNode(tpoint1, true);
00745   tree_shape->updateNode(tpoint2, true);
00746   tree_shape->updateNode(tpoint3, true);
00747 
00748   boost::shared_ptr<shapes::OcTree> shape_oc(new shapes::OcTree(tree_shape));
00749 
00750   PropagationDistanceField df_test_shape_1(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00751                                            PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00752 
00753   PropagationDistanceField df_test_shape_2(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00754                                            PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00755 
00756   df_test_shape_1.addOcTreeToField(tree_shape.get());
00757   df_test_shape_2.addShapeToField(shape_oc.get(), geometry_msgs::Pose());
00758   EXPECT_TRUE(areDistanceFieldsDistancesEqual(df_test_shape_1, df_test_shape_2));
00759 }
00760 
00761 TEST(TestSignedPropagationDistanceField, TestReadWrite)
00762 {
00763 
00764   PropagationDistanceField small_df( width, height, depth, resolution, origin_x, origin_y, origin_z, max_dist);
00765 
00766   EigenSTL::vector_Vector3d points;
00767   points.push_back(point1);
00768   points.push_back(point2);
00769   points.push_back(point3);
00770   small_df.addPointsToField(points);
00771 
00772   std::ofstream sf("test_small.df", std::ios::out);
00773 
00774   small_df.writeToStream(sf);
00775   //must close to make sure that the buffer is written
00776   sf.close();
00777 
00778   std::ifstream si("test_small.df", std::ios::in | std::ios::binary);
00779   PropagationDistanceField small_df2(si, PERF_MAX_DIST, false);
00780   ASSERT_TRUE(areDistanceFieldsDistancesEqual(small_df, small_df2));
00781 
00782   PropagationDistanceField df(PERF_WIDTH, PERF_HEIGHT, PERF_DEPTH, PERF_RESOLUTION,
00783                               PERF_ORIGIN_X, PERF_ORIGIN_Y, PERF_ORIGIN_Z, PERF_MAX_DIST, false);
00784 
00785   shapes::Sphere sphere(.5);
00786 
00787   geometry_msgs::Pose p;
00788   p.orientation.w = 1.0;
00789   p.position.x = .5;
00790   p.position.y = .5;
00791   p.position.z = .5;
00792 
00793   df.addShapeToField(&sphere, p);
00794 
00795   std::ofstream f("test_big.df", std::ios::out);
00796 
00797   df.writeToStream(f);
00798   f.close();
00799 
00800   std::ifstream i("test_big.df", std::ios::in);
00801   PropagationDistanceField df2(i, PERF_MAX_DIST, false);
00802   EXPECT_TRUE(areDistanceFieldsDistancesEqual(df, df2));
00803 
00804   //we shouldn't segfault if we start with an old ifstream
00805   PropagationDistanceField dfx(i, PERF_MAX_DIST, false);
00806 
00807   std::ifstream i2("test_big.df", std::ios::in);
00808   ros::WallTime wt = ros::WallTime::now();
00809   PropagationDistanceField df3(i2, PERF_MAX_DIST+.02, false);
00810   std::cout << "Reconstruction for big file took " << (ros::WallTime::now()-wt).toSec() << std::endl;
00811   EXPECT_FALSE(areDistanceFieldsDistancesEqual(df, df3));
00812 }
00813 
00814 int main(int argc, char **argv){
00815   testing::InitGoogleTest(&argc, argv);
00816 
00817   return RUN_ALL_TESTS();
00818 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Mon Oct 6 2014 02:24:47