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
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
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
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
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
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
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
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
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
00274
00275
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
00283
00284
00285 check_distance_field(df, points, numX, numY, numZ, false);
00286
00287
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
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
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
00354
00355
00356
00357
00358
00359
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
00378
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
00389
00390
00391
00392
00393
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
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
00489
00490
00491
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
00510 df.moveShapeInField(&sphere, p, np);
00511
00512 check_distance_field(df, point_vec_2,
00513 numX, numY, numZ, true);
00514
00515
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
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
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
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
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
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
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
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 }