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
00031 #include <sbpl_arm_planner/sbpl_collision_space.h>
00032
00033 #define SMALL_NUM 0.00000001 // to avoid division overflow
00034
00035 namespace sbpl_arm_planner {
00036
00037 SBPLCollisionSpace::SBPLCollisionSpace(SBPLArmModel* arm, OccupancyGrid* grid)
00038 {
00039 arm_ = arm;
00040 grid_ = grid;
00041 fOut_ = stdout;
00042 object_attached_ = false;
00043
00044
00045 inc_.resize(arm_->num_joints_,0.0348);
00046 inc_[5] = 0.1392;
00047 inc_[6] = M_PI;
00048
00049
00050
00051
00052 }
00053
00054 void SBPLCollisionSpace::setDebugFile(FILE* file_ptr)
00055 {
00056 fOut_ = file_ptr;
00057 }
00058
00059 bool SBPLCollisionSpace::checkCollision(const std::vector<double> &angles, bool verbose, bool check_mesh, unsigned char &dist)
00060 {
00061 unsigned char dist_temp=100;
00062 std::vector<std::vector<int> > jnts;
00063 KDL::Frame f_out;
00064 dist = 100;
00065
00066
00067 if(!getJointPosesInGrid(angles, jnts, f_out, false))
00068 return false;
00069
00070
00071 for(size_t i = 0; i < jnts.size(); ++i)
00072 {
00073 if(!grid_->isInBounds(jnts[i][0],jnts[i][1],jnts[i][2]))
00074 {
00075 if(verbose)
00076 SBPL_DEBUG("End of link %d is out of bounds. (%d %d %d)", int(i), jnts[i][0],jnts[i][1],jnts[i][2]);
00077 return false;
00078 }
00079 }
00080
00081
00082 for(int i = 0; i < int(jnts.size()-1); i++)
00083 {
00084 dist_temp = isValidLineSegment(jnts[i], jnts[i+1], arm_->getLinkRadiusCells(i));
00085
00086
00087 if(dist_temp <= arm_->getLinkRadiusCells(i))
00088 {
00089 if(verbose)
00090 SBPL_DEBUG("Link %d: {%d %d %d} -> {%d %d %d} with radius %0.2f is in collision.",i,jnts[i][0],jnts[i][1],jnts[i][2],jnts[i+1][0],jnts[i+1][1],jnts[i+1][2], arm_->getLinkRadius(i));
00091 dist = dist_temp;
00092 return false;
00093 }
00094
00095 if(dist_temp < dist)
00096 dist = dist_temp;
00097 }
00098
00099
00100 if(!isValidAttachedObject(angles, dist_temp, jnts[0],jnts[1]))
00101 {
00102 dist = dist_temp;
00103 return false;
00104 }
00105
00106 if(dist_temp < dist)
00107 dist = dist_temp;
00108
00109 return true;
00110 }
00111
00112 bool SBPLCollisionSpace::checkLinkForCollision(const std::vector<double> &angles, int link_num, bool verbose, unsigned char &dist)
00113 {
00114 unsigned char dist_temp = 0;
00115 std::vector<std::vector<int> > jnts;
00116 KDL::Frame f_out;
00117
00118 if(link_num >= arm_->num_links_)
00119 {
00120 SBPL_WARN("[checkLinkInCollision] %d is not a valid link index. There are %d links.", link_num, arm_->num_links_);
00121 return false;
00122 }
00123
00124
00125 if(!getJointPosesInGrid(angles, jnts, f_out, false))
00126 return false;
00127
00128
00129 if(!grid_->isInBounds(jnts[link_num][0],jnts[link_num][1],jnts[link_num][2]))
00130 {
00131 if(verbose)
00132 SBPL_DEBUG("End of link %d is out of bounds. (%d %d %d)", link_num, jnts[link_num][0],jnts[link_num][1],jnts[link_num][2]);
00133 return false;
00134 }
00135
00136
00137 dist = isValidLineSegment(jnts[link_num], jnts[link_num+1], arm_->getLinkRadiusCells(link_num));
00138
00139
00140 if(dist <= arm_->getLinkRadiusCells(link_num))
00141 {
00142 if(verbose)
00143 SBPL_DEBUG("Link %d: {%d %d %d} -> {%d %d %d} with radius %0.2f is in collision.",link_num,jnts[link_num][0],jnts[link_num][1],jnts[link_num][2],jnts[link_num+1][0],jnts[link_num+1][1],jnts[link_num+1][2],arm_->getLinkRadius(link_num));
00144 return false;
00145 }
00146
00147
00148 if(!isValidAttachedObject(angles, dist_temp, jnts[0], jnts[1]))
00149 {
00150 if(verbose)
00151 SBPL_DEBUG("Attached object is in collision.");
00152 dist = dist_temp;
00153 return false;
00154 }
00155
00156 if(dist_temp < dist)
00157 {
00158 if(verbose)
00159 SBPL_DEBUG("Attached object is the closest thing to the nearest obstacle with dist=%d", int(dist_temp));
00160 dist = dist_temp;
00161 }
00162
00163 return true;
00164 }
00165
00166 bool SBPLCollisionSpace::checkPathForCollision(const std::vector<double> &start, const std::vector<double> &end, bool verbose, unsigned char &dist)
00167 {
00168 int inc_cc = 10;
00169 unsigned char dist_temp = 0;
00170 std::vector<double> start_norm(start);
00171 std::vector<double> end_norm(end);
00172 std::vector<std::vector<double> > path;
00173 dist = 100;
00174
00175 for(size_t i=0; i < start.size(); i++)
00176 {
00177 start_norm[i] = angles::normalize_angle(start[i]);
00178 end_norm[i] = angles::normalize_angle(end[i]);
00179 }
00180
00181 if(start[2] > 0.85)
00182 start_norm[2] = start[2] + (2*-M_PI);
00183
00184 if(end[2] > 0.85)
00185 end_norm[2] = end[2] + (2*-M_PI);
00186
00187 getInterpolatedPath(start_norm, end_norm, inc_, path);
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 if(int(path.size()) > inc_cc)
00203 {
00204 for(int i = 0; i < inc_cc; i++)
00205 {
00206 for(size_t j = i; j < path.size(); j=j+inc_cc)
00207 {
00208 if(!checkCollision(path[j], verbose, false, dist_temp))
00209 {
00210 dist = dist_temp;
00211 return false;
00212 }
00213
00214 if(dist_temp < dist)
00215 dist = dist_temp;
00216 }
00217 }
00218 }
00219 else
00220 {
00221 for(size_t i = 0; i < path.size(); i++)
00222 {
00223 if(!checkCollision(path[i], verbose, false, dist_temp))
00224 {
00225 dist = dist_temp;
00226 return false;
00227 }
00228
00229 if(dist_temp < dist)
00230 dist = dist_temp;
00231 }
00232 }
00233
00234 return true;
00235 }
00236
00237 bool SBPLCollisionSpace::checkLinkPathForCollision(const std::vector<double> &start, const std::vector<double> &end, int link_num, bool verbose, unsigned char &dist)
00238 {
00239 int inc_cc = 10;
00240 unsigned char dist_temp = 0;
00241 std::vector<double> start_norm(start);
00242 std::vector<double> end_norm(end);
00243 std::vector<std::vector<double> > path;
00244 dist = 100;
00245
00246 for(size_t i=0; i < start.size(); i++)
00247 {
00248 start_norm[i] = angles::normalize_angle(start[i]);
00249 end_norm[i] = angles::normalize_angle(end[i]);
00250 }
00251
00252
00253 if(start[2] > 0.85)
00254 start_norm[2] = start[2] + (2*-M_PI);
00255
00256 if(end[2] > 0.85)
00257 end_norm[2] = end[2] + (2*-M_PI);
00258
00259 getInterpolatedPath(start_norm, end_norm, inc_, path);
00260
00261
00262 if(int(path.size()) > inc_cc)
00263 {
00264 for(int i = 0; i < inc_cc; i++)
00265 {
00266 for(size_t j = i; j < path.size(); j=j+inc_cc)
00267 {
00268 if(!checkLinkForCollision(path[j], link_num, verbose, dist_temp))
00269 {
00270 dist = dist_temp;
00271 return false;
00272 }
00273
00274 if(dist_temp < dist)
00275 dist = dist_temp;
00276 }
00277 }
00278 }
00279 else
00280 {
00281 for(size_t i = 0; i < path.size(); i++)
00282 {
00283 if(!checkLinkForCollision(path[i], link_num, verbose, dist_temp))
00284 {
00285 dist = dist_temp;
00286 return false;
00287 }
00288
00289 if(dist_temp < dist)
00290 dist = dist_temp;
00291 }
00292 }
00293
00294 return true;
00295 }
00296
00297 bool SBPLCollisionSpace::getJointPosesInGrid(std::vector<double> angles, std::vector<std::vector<int> > &jnts, KDL::Frame &f_out, bool verbose)
00298 {
00299 std::vector<std::vector<double> > jnts_m;
00300
00301 if(!arm_->getJointPositions(angles, jnts_m, f_out))
00302 return false;
00303
00304
00305 KDL::Vector tip_f_ref, tip_f_wrist(0.16,0,0);
00306 tip_f_ref = f_out.M * tip_f_wrist + f_out.p;
00307 jnts_m[3][0] = tip_f_ref.x();
00308 jnts_m[3][1] = tip_f_ref.y();
00309 jnts_m[3][2] = tip_f_ref.z();
00310
00311 jnts.resize(jnts_m.size());
00312 for(int i = 0; i < int(jnts.size()); ++i)
00313 {
00314 jnts[i].resize(3);
00315 grid_->worldToGrid(jnts_m[i][0],jnts_m[i][1],jnts_m[i][2],jnts[i][0],jnts[i][1],jnts[i][2]);
00316 }
00317
00318 return true;
00319 }
00320
00321 unsigned char SBPLCollisionSpace::isValidLineSegment(const std::vector<int> a, const std::vector<int> b, const short unsigned int radius)
00322 {
00323 bresenham3d_param_t params;
00324 int nXYZ[3], retvalue = 1;
00325 unsigned char cell_val, min_dist = 255;
00326 CELL3V tempcell;
00327 vector<CELL3V>* pTestedCells=NULL;
00328
00329
00330 get_bresenham3d_parameters(a[0], a[1], a[2], b[0], b[1], b[2], ¶ms);
00331 do {
00332 get_current_point3d(¶ms, &(nXYZ[0]), &(nXYZ[1]), &(nXYZ[2]));
00333
00334 if(!grid_->isInBounds(nXYZ[0],nXYZ[1],nXYZ[2]))
00335 return 0;
00336
00337 cell_val = grid_->getCell(nXYZ[0],nXYZ[1],nXYZ[2]);
00338 if(cell_val <= radius)
00339 {
00340 if(pTestedCells == NULL)
00341 return cell_val;
00342 else
00343 retvalue = 0;
00344 }
00345
00346 if(cell_val < min_dist)
00347 min_dist = cell_val;
00348
00349
00350 if(pTestedCells)
00351 {
00352 if(cell_val <= radius)
00353 tempcell.bIsObstacle = true;
00354 else
00355 tempcell.bIsObstacle = false;
00356 tempcell.x = nXYZ[0];
00357 tempcell.y = nXYZ[1];
00358 tempcell.z = nXYZ[2];
00359 pTestedCells->push_back(tempcell);
00360 }
00361 } while (get_next_point3d(¶ms));
00362
00363 if(retvalue)
00364 return min_dist;
00365 else
00366 return 0;
00367 }
00368
00369 double SBPLCollisionSpace::distanceBetween3DLineSegments(std::vector<int> l1a, std::vector<int> l1b,std::vector<int> l2a, std::vector<int> l2b)
00370 {
00371
00372
00373
00374
00375
00376
00377
00378 double u[3];
00379 double v[3];
00380 double w[3];
00381 double dP[3];
00382
00383 u[0] = l1b[0] - l1a[0];
00384 u[1] = l1b[1] - l1a[1];
00385 u[2] = l1b[2] - l1a[2];
00386
00387 v[0] = l2b[0] - l2a[0];
00388 v[1] = l2b[1] - l2a[1];
00389 v[2] = l2b[2] - l2a[2];
00390
00391 w[0] = l1a[0] - l2a[0];
00392 w[1] = l1a[1] - l2a[1];
00393 w[2] = l1a[2] - l2a[2];
00394
00395 double a = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
00396 double b = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
00397 double c = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
00398 double d = u[0] * w[0] + u[1] * w[1] + u[2] * w[2];
00399 double e = v[0] * w[0] + v[1] * w[1] + v[2] * w[2];
00400 double D = a*c - b*b;
00401 double sc, sN, sD = D;
00402 double tc, tN, tD = D;
00403
00404
00405 if (D < SMALL_NUM) {
00406 sN = 0.0;
00407 sD = 1.0;
00408 tN = e;
00409 tD = c;
00410 }
00411 else {
00412 sN = (b*e - c*d);
00413 tN = (a*e - b*d);
00414 if (sN < 0.0) {
00415 sN = 0.0;
00416 tN = e;
00417 tD = c;
00418 }
00419 else if (sN > sD) {
00420 sN = sD;
00421 tN = e + b;
00422 tD = c;
00423 }
00424 }
00425
00426 if (tN < 0.0) {
00427 tN = 0.0;
00428
00429 if (-d < 0.0)
00430 sN = 0.0;
00431 else if (-d > a)
00432 sN = sD;
00433 else {
00434 sN = -d;
00435 sD = a;
00436 }
00437 }
00438 else if (tN > tD) {
00439 tN = tD;
00440
00441 if ((-d + b) < 0.0)
00442 sN = 0;
00443 else if ((-d + b) > a)
00444 sN = sD;
00445 else {
00446 sN = (-d + b);
00447 sD = a;
00448 }
00449 }
00450
00451
00452 sc = (fabs(sN) < SMALL_NUM ? 0.0 : sN / sD);
00453 tc = (fabs(tN) < SMALL_NUM ? 0.0 : tN / tD);
00454
00455
00456
00457
00458 dP[0] = w[0] + (sc * u[0]) - (tc * v[0]);
00459 dP[1] = w[1] + (sc * u[1]) - (tc * v[1]);
00460 dP[2] = w[2] + (sc * u[2]) - (tc * v[2]);
00461
00462 return sqrt(dP[0]*dP[0] + dP[1]*dP[1] + dP[2]*dP[2]);
00463 }
00464
00465 void SBPLCollisionSpace::addArmCuboidsToGrid()
00466 {
00467 std::vector<std::vector<double> > cuboids = arm_->getCollisionCuboids();
00468
00469 SBPL_DEBUG("[SBPLCollisionSpace] received %d cuboids\n",int(cuboids.size()));
00470
00471 for(unsigned int i = 0; i < cuboids.size(); i++)
00472 {
00473 if(cuboids[i].size() == 6)
00474 grid_->addCollisionCuboid(cuboids[i][0],cuboids[i][1],cuboids[i][2],cuboids[i][3],cuboids[i][4],cuboids[i][5]);
00475 else
00476 SBPL_DEBUG("[addArmCuboidsToGrid] Self-collision cuboid #%d has an incomplete description.\n", i);
00477 }
00478 }
00479
00480 bool SBPLCollisionSpace::getCollisionCylinders(const std::vector<double> &angles, std::vector<std::vector<double> > &cylinders)
00481 {
00482 int num_arm_spheres = 0;
00483 KDL::Frame f_out;
00484 std::vector<double> xyzr(4,0);
00485 std::vector<std::vector<int> > points, jnts;
00486 std::vector<std::vector<double> > object;
00487
00488
00489 if(!getJointPosesInGrid(angles, jnts, f_out, false))
00490 return false;
00491
00492 for(int i = 0; i < int(jnts.size()-1); ++i)
00493 {
00494 points.clear();
00495 getLineSegment(jnts[i], jnts[i+1], points);
00496
00497
00498 for(int j = 0; j < int(points.size()); ++j)
00499 {
00500 grid_->gridToWorld(points[j][0],points[j][1],points[j][2],xyzr[0],xyzr[1],xyzr[2]);
00501 xyzr[3]=double(arm_->getLinkRadiusCells(i))*arm_->resolution_;
00502 cylinders.push_back(xyzr);
00503 }
00504 }
00505
00506 num_arm_spheres = cylinders.size();
00507
00508 if(object_attached_)
00509 {
00510 getAttachedObject(angles, object);
00511 for(size_t i = 0; i < object.size(); ++i)
00512 {
00513 xyzr[0] = object[i][0];
00514 xyzr[1] = object[i][1];
00515 xyzr[2] = object[i][2];
00516 xyzr[3]=double(attached_object_radius_)*grid_->getResolution();
00517 cylinders.push_back(xyzr);
00518 }
00519 }
00520
00521 ROS_DEBUG("[getCollisionCylinders] {Collision Spheres} arm: %d object: %d ", int(num_arm_spheres), int(object.size()));
00522
00523 return true;
00524 }
00525
00526 void SBPLCollisionSpace::getLineSegment(const std::vector<int> a,const std::vector<int> b,std::vector<std::vector<int> > &points){
00527 bresenham3d_param_t params;
00528 std::vector<int> nXYZ(3,0);
00529
00530
00531 get_bresenham3d_parameters(a[0], a[1], a[2], b[0], b[1], b[2], ¶ms);
00532 do {
00533 get_current_point3d(¶ms, &(nXYZ[0]), &(nXYZ[1]), &(nXYZ[2]));
00534
00535 points.push_back(nXYZ);
00536
00537 } while (get_next_point3d(¶ms));
00538 }
00539
00540 void SBPLCollisionSpace::getInterpolatedPath(const std::vector<double> &start, const std::vector<double> &end, double inc, std::vector<std::vector<double> > &path)
00541 {
00542 bool changed = true;
00543 std::vector<double> next(start);
00544
00545
00546 if(start.size() != end.size())
00547 {
00548 SBPL_WARN("[getInterpolatedPath] The start and end configurations have different sizes.\n");
00549 return;
00550 }
00551
00552 while(changed)
00553 {
00554 changed = false;
00555
00556 for (int i = 0; i < int(start.size()); i++)
00557 {
00558 if (fabs(next[i] - end[i]) > inc)
00559 {
00560 changed = true;
00561
00562 if(end[i] > next[i])
00563 next[i] += inc;
00564 else
00565 next[i] += -inc;
00566 }
00567 }
00568
00569 if (changed)
00570 path.push_back(next);
00571 }
00572 }
00573
00574 void SBPLCollisionSpace::getInterpolatedPath(const std::vector<double> &start, const std::vector<double> &end, std::vector<double> &inc, std::vector<std::vector<double> > &path)
00575 {
00576 bool changed = true;
00577 std::vector<double> next(start);
00578
00579
00580 if(start.size() != end.size())
00581 {
00582 SBPL_WARN("[getInterpolatedPath] The start and end configurations have different sizes.\n");
00583 return;
00584 }
00585
00586 while(changed)
00587 {
00588 changed = false;
00589
00590 for (int i = 0; i < int(start.size()); i++)
00591 {
00592 if (fabs(next[i] - end[i]) > inc[i])
00593 {
00594 changed = true;
00595
00596 if(end[i] > next[i])
00597 next[i] += inc[i];
00598 else
00599 next[i] += -inc[i];
00600 }
00601 }
00602
00603 if (changed)
00604 path.push_back(next);
00605 }
00606 }
00607
00608 void SBPLCollisionSpace::removeAttachedObject()
00609 {
00610 object_attached_ = false;
00611 object_points_.clear();
00612 SBPL_INFO("[removeAttachedObject] Removed attached object.");
00613 }
00614
00615 void SBPLCollisionSpace::attachSphereToGripper(std::string frame, geometry_msgs::Pose pose, double radius)
00616 {
00617 object_attached_ = true;
00618 attached_object_frame_num_ = 12;
00619
00620 SBPL_INFO("[addSphereToGripper] Pose of Sphere: %0.3f %0.3f %0.3f radius: %0.3f", pose.position.x,pose.position.y,pose.position.z, radius);
00621 attached_object_radius_ = radius / grid_->getResolution();
00622
00623 object_points_.resize(1);
00624 tf::PoseMsgToKDL(pose, object_points_[0]);
00625
00626 SBPL_DEBUG("[addSphereToGripper] Added collision sphere. xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[0].p.x(), object_points_[0].p.y(), object_points_[0].p.z(), radius, attached_object_radius_);
00627
00628 arm_->printArmDescription(stdout);
00629 }
00630
00631 void SBPLCollisionSpace::attachCylinderToGripper(std::string frame, geometry_msgs::Pose pose, double radius, double length)
00632 {
00633 object_attached_ = true;
00634 attached_object_frame_num_ = 12;
00635
00636 SBPL_DEBUG("[addCylinderToGripper] Cylinder: %0.3f %0.3f %0.3f radius: %0.3f length: %0.3f", pose.position.x,pose.position.y,pose.position.z, radius, length);
00637
00638 attached_object_radius_ = radius / grid_->getResolution();
00639
00640 if(attached_object_radius_ < 1)
00641 attached_object_radius_ = 1;
00642
00643 object_points_.resize(2);
00644 tf::PoseMsgToKDL(pose, object_points_[0]);
00645 tf::PoseMsgToKDL(pose, object_points_[1]);
00646
00647
00648 object_points_[0].p.data[2] -= length/2.0;
00649 object_points_[1].p.data[2] += length/2.0;
00650
00651 SBPL_DEBUG("[addCylinderToGripper] Added cylinder. Bottom: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[0].p.x(), object_points_[0].p.y(), object_points_[0].p.z(), radius, attached_object_radius_);
00652 SBPL_DEBUG("[addCylinderToGripper] Added cylinder. Top: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[1].p.x(), object_points_[1].p.y(), object_points_[1].p.z(), radius, attached_object_radius_);
00653
00654 arm_->printArmDescription(stdout);
00655 }
00656
00657 void SBPLCollisionSpace::attachMeshToGripper(const std::string frame, const geometry_msgs::Pose pose, const std::vector<int32_t> &triangles, const std::vector<geometry_msgs::Point> &vertices)
00658 {
00659 bodies::BoundingCylinder cyl;
00660 getBoundingCylinderOfMesh(triangles, vertices, cyl);
00661 ROS_INFO("HERE");
00662 attachMeshToGripper(frame, pose, cyl);
00663 }
00664
00665 void SBPLCollisionSpace::attachMeshToGripper(const std::string frame, const geometry_msgs::Pose pose, const bodies::BoundingCylinder &cyl)
00666 {
00667 KDL::Frame cyl_pose;
00668
00669 object_attached_ = true;
00670 attached_object_frame_num_ = 12;
00671
00672 SBPL_INFO("[addMeshToGripper] Mesh: %0.3f %0.3f %0.3f radius: %0.3f length: %0.3f", pose.position.x,pose.position.y,pose.position.z, cyl.radius, cyl.length);
00673
00674 attached_object_radius_ = cyl.radius / grid_->getResolution();
00675
00676 if(attached_object_radius_ < 1)
00677 attached_object_radius_ = 1;
00678
00679
00680 object_points_.resize(2);
00681 ROS_INFO("Object Pose- Position: %0.3f %0.3f %0.3f Orientation: %0.3f %0.3f %0.3f %0.3f",pose.position.x,pose.position.y,pose.position.z, pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
00682
00683 tf::PoseMsgToKDL(pose, object_points_[0]);
00684 tf::PoseMsgToKDL(pose, object_points_[1]);
00685
00686
00687
00688
00689
00690 SBPL_INFO("BEFORE TRANSFORMATION");
00691 SBPL_INFO("[addMeshToGripper] Added bounding cylinder. Bottom: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[0].p.x(), object_points_[0].p.y(), object_points_[0].p.z(), cyl.radius, attached_object_radius_);
00692 SBPL_INFO("[addMeshToGripper] Added bounding cylinder. Top: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[1].p.x(), object_points_[1].p.y(), object_points_[1].p.z(), cyl.radius, attached_object_radius_);
00693
00694 tf::TransformTFToKDL(cyl.pose, cyl_pose);
00695
00696
00697
00698 object_points_[0].p.data[2] -= cyl.length/2.0;
00699 object_points_[1].p.data[2] += cyl.length/2.0;
00700
00701 SBPL_INFO("AFTER TRANSFORMATION");
00702 SBPL_INFO("[addMeshToGripper] Added bounding cylinder. Bottom: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[0].p.x(), object_points_[0].p.y(), object_points_[0].p.z(), cyl.radius, attached_object_radius_);
00703 SBPL_INFO("[addMeshToGripper] Added bounding cylinder. Top: xyz: %0.3f %0.3f %0.3f radius: %0.3fm (%d cells)", object_points_[1].p.x(), object_points_[1].p.y(), object_points_[1].p.z(), cyl.radius, attached_object_radius_);
00704
00705 arm_->printArmDescription(stdout);
00706 }
00707
00708 bool SBPLCollisionSpace::isValidAttachedObject(const std::vector<double> &angles, unsigned char &dist, std::vector<int> j1, std::vector<int> j2)
00709 {
00710 unsigned char dist_temp = 0;
00711 KDL::Frame f_base_obj;
00712 KDL::Vector p_base,p1,p2;
00713
00714 std::vector<int> q1(3,0), q2(3,0);
00715 dist = 100;
00716
00717 if(!object_attached_)
00718 return true;
00719
00720 if(!arm_->computeFK(angles, attached_object_frame_num_,&f_base_obj))
00721 return false;
00722
00723
00724
00725
00726 for(size_t i = 0; i < object_points_.size(); i++)
00727 {
00728
00729
00730 p_base = f_base_obj * object_points_[i].p;
00731
00732 if(!isValidPoint(p_base.data[0],p_base.data[1],p_base.data[2],attached_object_radius_,dist))
00733 {
00734
00735 return false;
00736 }
00737 }
00738
00739
00740 for(size_t i = 0; i < (object_points_.size()-1); i++)
00741 {
00742 p1 = f_base_obj * object_points_[i].p;
00743 p2 = f_base_obj * object_points_[i+1].p;
00744
00745 grid_->worldToGrid(p1.data[0],p1.data[1],p1.data[2],q1[0],q1[1],q1[2]);
00746 grid_->worldToGrid(p2.data[0],p2.data[1],p2.data[2],q2[0],q2[1],q2[2]);
00747
00748
00749
00750
00751 dist_temp = isValidLineSegment(q1, q2, attached_object_radius_);
00752
00753 if(dist_temp <= attached_object_radius_)
00754 {
00755 dist = dist_temp;
00756
00757 return false;
00758 }
00759
00760 if(dist_temp < dist)
00761 dist = dist_temp;
00762 }
00763
00764
00765 if (distanceBetween3DLineSegments(q1,q2,j1,j2) < 6)
00766 return false;
00767
00768 return true;
00769 }
00770
00771 bool SBPLCollisionSpace::isValidAttachedObject(const std::vector<double> &angles, unsigned char &dist)
00772 {
00773 unsigned char dist_temp = 0;
00774 KDL::Frame f_base_obj;
00775 KDL::Vector p_base,p1,p2;
00776
00777 std::vector<int> q1(3,0), q2(3,0);
00778
00779 if(!object_attached_)
00780 return true;
00781
00782 if(!arm_->computeFK(angles, attached_object_frame_num_,&f_base_obj))
00783 return false;
00784
00785
00786
00787
00788 for(size_t i = 0; i < object_points_.size(); i++)
00789 {
00790
00791
00792 p_base = f_base_obj * object_points_[i].p;
00793
00794 if(!isValidPoint(p_base.data[0],p_base.data[1],p_base.data[2],attached_object_radius_,dist))
00795 {
00796
00797 return false;
00798 }
00799 }
00800
00801
00802 for(size_t i = 0; i < (object_points_.size()-1); i++)
00803 {
00804 p1 = f_base_obj * object_points_[i].p;
00805 p2 = f_base_obj * object_points_[i+1].p;
00806
00807 grid_->worldToGrid(p1.data[0],p1.data[1],p1.data[2],q1[0],q1[1],q1[2]);
00808 grid_->worldToGrid(p2.data[0],p2.data[1],p2.data[2],q2[0],q2[1],q2[2]);
00809
00810
00811
00812
00813 dist_temp = isValidLineSegment(q1, q2, attached_object_radius_);
00814
00815 if(dist_temp <= attached_object_radius_)
00816 {
00817 dist = dist_temp;
00818
00819 return false;
00820 }
00821
00822 if(dist_temp < dist)
00823 dist = dist_temp;
00824 }
00825
00826 return true;
00827 }
00828
00829 bool SBPLCollisionSpace::isValidPoint(double &x, double &y, double &z, short unsigned int &radius, unsigned char &dist)
00830 {
00831 int xyz_c[3]={0};
00832
00833 grid_->worldToGrid(x,y,z,xyz_c[0], xyz_c[1], xyz_c[2]);
00834
00835 SBPL_DEBUG("world: %0.3f %0.3f %0.3f grid: %d %d %d dist: %u radius: %u",x, y, z, xyz_c[0], xyz_c[1], xyz_c[2], grid_->getCell(xyz_c[0],xyz_c[1],xyz_c[2]), radius);
00836
00837 if((dist = grid_->getCell(xyz_c[0],xyz_c[1],xyz_c[2])) <= radius)
00838 return false;
00839
00840 return true;
00841 }
00842
00843 bool SBPLCollisionSpace::getAttachedObject(const std::vector<double> &angles, std::vector<std::vector<double> > &xyz)
00844 {
00845 KDL::Frame f_base_obj;
00846 KDL::Vector p_base,p1,p2;
00847 std::vector<double> point(6,0);
00848 std::vector<int> q1(3,0), q2(3,0);
00849 std::vector<std::vector<int> > cells;
00850
00851 if(!object_attached_)
00852 return false;
00853
00854 if(!arm_->computeFK(angles, attached_object_frame_num_, &f_base_obj))
00855 return false;
00856
00857 xyz.resize(object_points_.size(), std::vector<double>(6,0));
00858 for(size_t i = 0; i < object_points_.size(); i++)
00859 {
00860 p_base = f_base_obj * object_points_[i].p;
00861 xyz[i][0] = p_base.data[0];
00862 xyz[i][1] = p_base.data[1];
00863 xyz[i][2] = p_base.data[2];
00864 }
00865
00866
00867
00868 for(size_t i = 0; i < (object_points_.size()-1); i++)
00869 {
00870 p1 = f_base_obj * object_points_[i].p;
00871 p2 = f_base_obj * object_points_[i+1].p;
00872
00873 grid_->worldToGrid(p1.data[0],p1.data[1],p1.data[2],q1[0],q1[1],q1[2]);
00874 grid_->worldToGrid(p2.data[0],p2.data[1],p2.data[2],q2[0],q2[1],q2[2]);
00875
00876 getLineSegment(q1, q2, cells);
00877
00878 for(size_t j = 0; j < cells.size();j++)
00879 {
00880 grid_->gridToWorld(cells[j][0],cells[j][1],cells[j][2],point[0],point[1],point[2]);
00881 xyz.push_back(point);
00882 }
00883 }
00884
00885 return true;
00886 }
00887
00888 double SBPLCollisionSpace::getAttachedObjectRadius()
00889 {
00890 return attached_object_radius_*grid_->getResolution();
00891 }
00892
00893 bool SBPLCollisionSpace::getBoundingCylinderOfMesh(std::string mesh_file, shapes::Shape *mesh, bodies::BoundingCylinder &cyl)
00894 {
00895 bool retval = false;
00896 mesh = NULL;
00897
00898 if (!mesh_file.empty())
00899 {
00900 resource_retriever::Retriever retriever;
00901 resource_retriever::MemoryResource res;
00902 bool ok = true;
00903
00904 try
00905 {
00906 res = retriever.get(mesh_file);
00907 }
00908 catch (resource_retriever::Exception& e)
00909 {
00910 ROS_ERROR("%s", e.what());
00911 ok = false;
00912 }
00913
00914 if (ok)
00915 {
00916 if (res.size == 0)
00917 ROS_WARN("Retrieved empty mesh for resource '%s'", mesh_file.c_str());
00918 else
00919 {
00920 mesh = shapes::createMeshFromBinaryStlData(reinterpret_cast<char*>(res.data.get()), res.size);
00921 if (mesh == NULL)
00922 ROS_ERROR("Failed to load mesh '%s'", mesh_file.c_str());
00923 else
00924 retval = true;
00925 }
00926 }
00927 }
00928 else
00929 ROS_WARN("Empty mesh filename");
00930
00931 if(retval)
00932 {
00933 const bodies::Body *body=new bodies::ConvexMesh(mesh);
00934 body->computeBoundingCylinder(cyl);
00935 ROS_INFO("Bounding cylinder has radius: %0.3f length: %0.3f", cyl.radius, cyl.length);
00936 }
00937
00938 return retval;
00939 }
00940
00941 void SBPLCollisionSpace::getBoundingCylinderOfMesh(const std::vector<int32_t> &triangles, const std::vector<geometry_msgs::Point> &vertices, bodies::BoundingCylinder &cyl)
00942 {
00943 shapes::Shape *mesh = NULL;
00944
00945 shapes::Mesh *dest = new shapes::Mesh(vertices.size(), triangles.size()/3);
00946 for (size_t i = 0 ; i < vertices.size(); ++i)
00947 {
00948 dest->vertices[3*i] = vertices[i].x;
00949 dest->vertices[3*i+1] = vertices[i].y;
00950 dest->vertices[3*i+2] = vertices[i].z;
00951 }
00952
00953 for (unsigned int i = 0 ; i < triangles.size(); ++i)
00954 dest->triangles[i] = triangles[i];
00955
00956 mesh = dest;
00957
00958 const bodies::Body *body=new bodies::ConvexMesh(mesh);
00959 body->computeBoundingCylinder(cyl);
00960 ROS_INFO("Bounding cylinder has radius: %0.3f length: %0.3f", cyl.radius, cyl.length);
00961 }
00962
00963 void SBPLCollisionSpace::processCollisionObjectMsg(const mapping_msgs::CollisionObject &object)
00964 {
00965 if(object.operation.operation == mapping_msgs::CollisionObjectOperation::ADD)
00966 {
00967 object_map_[object.id] = object;
00968 addCollisionObject(object);
00969 }
00970 else if(object.operation.operation == mapping_msgs::CollisionObjectOperation::REMOVE)
00971 {
00972 if(object.id.compare("all") == 0)
00973 removeAllCollisionObjects();
00974 else
00975 removeCollisionObject(object);
00976 }
00977 else if(object.operation.operation == mapping_msgs::CollisionObjectOperation::DETACH_AND_ADD_AS_OBJECT)
00978 {
00979 object_map_[object.id] = object;
00980 addCollisionObject(object);
00981 }
00982 else if(object.operation.operation == mapping_msgs::CollisionObjectOperation::ATTACH_AND_REMOVE_AS_OBJECT)
00983 {
00984
00985 removeCollisionObject(object);
00986 }
00987 else
00988 ROS_WARN("*** Operation isn't supported. ***\n\n");
00989 }
00990
00991 void SBPLCollisionSpace::addCollisionObject(const mapping_msgs::CollisionObject &object)
00992 {
00993 geometry_msgs::Pose pose;
00994
00995 for(size_t i = 0; i < object.shapes.size(); ++i)
00996 {
00997 if(object.shapes[i].type == geometric_shapes_msgs::Shape::BOX)
00998 {
00999 transformPose(object.header.frame_id, grid_->getReferenceFrame(), object.poses[i], pose);
01000 grid_->getVoxelsInBox(pose, object.shapes[i].dimensions, object_voxel_map_[object.id]);
01001
01002 ROS_DEBUG("[%s] TransformPose from %s to %s.", object.id.c_str(), object.header.frame_id.c_str(), grid_->getReferenceFrame().c_str());
01003 ROS_DEBUG("[%s] %s: xyz: %0.3f %0.3f %0.3f quat: %0.3f %0.3f %0.3f %0.3f", object.id.c_str(), object.header.frame_id.c_str(), object.poses[i].position.x, object.poses[i].position.y, object.poses[i].position.z, object.poses[i].orientation.x, object.poses[i].orientation.y, object.poses[i].orientation.z,object.poses[i].orientation.w);
01004 ROS_DEBUG("[%s] %s: xyz: %0.3f %0.3f %0.3f quat: %0.3f %0.3f %0.3f %0.3f", object.id.c_str(), grid_->getReferenceFrame().c_str(), pose.position.x, pose.position.y, pose.position.z, pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);
01005 ROS_DEBUG("[%s] occupies %d voxels.",object.id.c_str(), int(object_voxel_map_[object.id].size()));
01006 }
01007 else
01008 ROS_WARN("[addCollisionObject] Collision objects of type %d are not yet supported.", object.shapes[i].type);
01009 }
01010
01011
01012 bool new_object = true;
01013 for(size_t i = 0; i < known_objects_.size(); ++i)
01014 {
01015 if(known_objects_[i].compare(object.id) == 0)
01016 new_object = false;
01017 }
01018 if(new_object)
01019 known_objects_.push_back(object.id);
01020
01021 grid_->addPointsToField(object_voxel_map_[object.id]);
01022 ROS_DEBUG("[addCollisionObject] Just added %s to the distance field.", object.id.c_str());
01023 }
01024
01025 void SBPLCollisionSpace::removeCollisionObject(const mapping_msgs::CollisionObject &object)
01026 {
01027 for(size_t i = 0; i < known_objects_.size(); ++i)
01028 {
01029 if(known_objects_[i].compare(object.id) == 0)
01030 {
01031 known_objects_.erase(known_objects_.begin() + i);
01032 ROS_DEBUG("[removeCollisionObject] Removing %s from list of known objects.", object.id.c_str());
01033 }
01034 }
01035 }
01036
01037 void SBPLCollisionSpace::removeAllCollisionObjects()
01038 {
01039 known_objects_.clear();
01040 }
01041
01042 void SBPLCollisionSpace::putCollisionObjectsInGrid()
01043 {
01044 ROS_DEBUG("[putCollisionObjectsInGrid] Should we reset first?");
01045
01046 for(size_t i = 0; i < known_objects_.size(); ++i)
01047 {
01048 grid_->addPointsToField(object_voxel_map_[known_objects_[i]]);
01049 ROS_DEBUG("[putCollisionObjectsInGrid] Added %s to grid with %d voxels.",known_objects_[i].c_str(), int(object_voxel_map_[known_objects_[i]].size()));
01050 }
01051 }
01052
01053 void SBPLCollisionSpace::getCollisionObjectVoxelPoses(std::vector<geometry_msgs::Pose> &points)
01054 {
01055 geometry_msgs::Pose pose;
01056
01057 pose.orientation.x = 0;
01058 pose.orientation.y = 0;
01059 pose.orientation.z = 0;
01060 pose.orientation.w = 1;
01061
01062 for(size_t i = 0; i < known_objects_.size(); ++i)
01063 {
01064 for(size_t j = 0; j < object_voxel_map_[known_objects_[i]].size(); ++j)
01065 {
01066 pose.position.x = object_voxel_map_[known_objects_[i]][j].x();
01067 pose.position.y = object_voxel_map_[known_objects_[i]][j].y();
01068 pose.position.z = object_voxel_map_[known_objects_[i]][j].z();
01069 points.push_back(pose);
01070 }
01071 }
01072 }
01073
01074 void SBPLCollisionSpace::transformPose(const std::string ¤t_frame, const std::string &desired_frame, const geometry_msgs::Pose &pose_in, geometry_msgs::Pose &pose_out)
01075 {
01076 geometry_msgs::PoseStamped stpose_in, stpose_out;
01077 stpose_in.header.frame_id = current_frame;
01078 stpose_in.header.stamp = ros::Time();
01079 stpose_in.pose = pose_in;
01080 tf_.transformPose(desired_frame, stpose_in, stpose_out);
01081 pose_out = stpose_out.pose;
01082 }
01083
01084 }