00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <eband_local_planner/eband_local_planner.h>
00039
00040
00041 namespace eband_local_planner{
00042
00043
00044 EBandPlanner::EBandPlanner() : costmap_ros_(NULL), initialized_(false) {}
00045
00046
00047 EBandPlanner::EBandPlanner(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00048 : costmap_ros_(NULL), initialized_(false)
00049 {
00050
00051 initialize(name, costmap_ros);
00052 }
00053
00054
00055 EBandPlanner::~EBandPlanner()
00056 {
00057 delete world_model_;
00058 }
00059
00060
00061 void EBandPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00062 {
00063
00064 if(!initialized_)
00065 {
00066
00067 costmap_ros_ = costmap_ros;
00068
00069
00070 costmap_ros_->getCostmapCopy(costmap_);
00071
00072
00073 world_model_ = new base_local_planner::CostmapModel(costmap_);
00074
00075
00076 footprint_spec_ = costmap_ros_->getRobotFootprint();
00077
00078
00079
00080 ros::NodeHandle pn("~/" + name);
00081
00082
00083
00084 pn.param("eband_min_relative_bubble_overlap_", min_bubble_overlap_, 0.7);
00085
00086
00087 pn.param("eband_tiny_bubble_distance", tiny_bubble_distance_, 0.01);
00088 pn.param("eband_tiny_bubble_expansion", tiny_bubble_expansion_, 0.01);
00089
00090
00091 pn.param("eband_internal_force_gain", internal_force_gain_, 1.0);
00092 pn.param("eband_external_force_gain", external_force_gain_, 2.0);
00093 pn.param("num_iterations_eband_optimization", num_optim_iterations_, 3);
00094
00095
00096 pn.param("eband_equilibrium_approx_max_recursion_depth", max_recursion_depth_approx_equi_, 4);
00097 pn.param("eband_equilibrium_relative_overshoot", equilibrium_relative_overshoot_, 0.75);
00098 pn.param("eband_significant_force_lower_bound", significant_force_, 0.15);
00099
00100
00101
00102 elastic_band_.clear();
00103
00104
00105 initialized_ = true;
00106
00107
00108 visualization_ = false;
00109 }
00110 else
00111 {
00112 ROS_WARN("This planner has already been initialized, doing nothing.");
00113 }
00114 }
00115
00116 void EBandPlanner::setVisualization(boost::shared_ptr<EBandVisualization> eband_visual)
00117 {
00118 eband_visual_ = eband_visual;
00119
00120 visualization_ = true;
00121 }
00122
00123
00124 bool EBandPlanner::setPlan(const std::vector<geometry_msgs::PoseStamped>& global_plan)
00125 {
00126
00127 if(!initialized_)
00128 {
00129 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00130 return false;
00131 }
00132
00133
00134
00135 if(global_plan.size() < 2)
00136 {
00137 ROS_ERROR("Attempt to pass empty path to optimization. Valid path needs to have at least 2 Frames. This one has %d.", ((int) global_plan.size()) );
00138 return false;
00139 }
00140
00141 global_plan_ = global_plan;
00142
00143
00144
00145 costmap_ros_->getCostmapCopy(costmap_);
00146
00147
00148 if(global_plan.front().header.frame_id != costmap_ros_->getGlobalFrameID())
00149 {
00150 ROS_ERROR("Elastic Band expects plan for optimization in the %s frame, the plan was sent in the %s frame.",
00151 costmap_ros_->getGlobalFrameID().c_str(), global_plan.front().header.frame_id.c_str());
00152 return false;
00153 }
00154
00155
00156
00157 ROS_DEBUG("Converting Plan to Band");
00158 if(!convertPlanToBand(global_plan_, elastic_band_))
00159 {
00160 ROS_WARN("Conversion from plan to elastic band failed. Plan probably not collision free. Plan not set for optimization");
00161
00162 return false;
00163 }
00164
00165
00166
00167 ROS_DEBUG("Refining Band");
00168 if(!refineBand(elastic_band_))
00169 {
00170 ROS_WARN("Band is broken. Could not close gaps in converted path. Path not set. Global replanning needed");
00171 return false;
00172 }
00173
00174
00175 ROS_DEBUG("Refinement done - Band set.");
00176 return true;
00177 }
00178
00179
00180 bool EBandPlanner::getPlan(std::vector<geometry_msgs::PoseStamped>& global_plan)
00181 {
00182
00183 if(!initialized_)
00184 {
00185 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00186 return false;
00187 }
00188
00189
00190 if(elastic_band_.empty())
00191 {
00192 ROS_WARN("Band is empty. There was no path successfully set so far.");
00193 return false;
00194 }
00195
00196
00197 if(!convertBandToPlan(global_plan, elastic_band_))
00198 {
00199 ROS_WARN("Conversion from Elastic Band to path failed.");
00200 return false;
00201 }
00202
00203 return true;
00204 }
00205
00206
00207 bool EBandPlanner::getBand(std::vector<Bubble>& elastic_band)
00208 {
00209
00210 if(!initialized_)
00211 {
00212 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00213 return false;
00214 }
00215
00216 elastic_band = elastic_band_;
00217
00218
00219 if(elastic_band_.empty())
00220 {
00221 ROS_WARN("Band is empty.");
00222 return false;
00223 }
00224
00225 return true;
00226 }
00227
00228
00229 bool EBandPlanner::addFrames(const std::vector<geometry_msgs::PoseStamped>& plan_to_add, const AddAtPosition& add_frames_at)
00230 {
00231
00232 if(!initialized_)
00233 {
00234 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00235 return false;
00236 }
00237
00238
00239 if(elastic_band_.size() < 1)
00240 {
00241 ROS_WARN("Attempt to connect path to empty band. path not connected. Use SetPath instead");
00242 return false;
00243 }
00244
00245
00246 if(plan_to_add.empty())
00247 {
00248 ROS_WARN("Attempt to connect empty path to band. Nothing to do here.");
00249 return false;
00250 }
00251
00252
00253
00254 costmap_ros_->getCostmapCopy(costmap_);
00255
00256
00257 if(plan_to_add.at(0).header.frame_id != costmap_ros_->getGlobalFrameID())
00258 {
00259 ROS_ERROR("Elastic Band expects robot pose for optimization in the %s frame, the pose was sent in the %s frame.",
00260 costmap_ros_->getGlobalFrameID().c_str(), plan_to_add.at(0).header.frame_id.c_str());
00261 return false;
00262 }
00263
00264
00265
00266 std::vector<Bubble> band_to_add;
00267 if(!convertPlanToBand(plan_to_add, band_to_add))
00268 {
00269 ROS_DEBUG("Conversion from plan to elastic band failed. Plan not appended");
00270
00271 return false;
00272 }
00273
00274
00275
00276 ROS_DEBUG("Checking for connections between current band and new bubbles");
00277 bool connected = false;
00278 int bubble_connect = -1;
00279 if(add_frames_at == add_front)
00280 {
00281
00282
00283 for(int i = ((int) elastic_band_.size() - 1); i >= 0; i--)
00284 {
00285
00286 if(checkOverlap(band_to_add.back(), elastic_band_.at(i)))
00287 {
00288 bubble_connect = i;
00289 connected = true;
00290 break;
00291 }
00292 }
00293 }
00294 else
00295 {
00296
00297
00298 for(int i = 0; i < ((int) elastic_band_.size() - 1); i++)
00299 {
00300
00301 if(checkOverlap(band_to_add.front(), elastic_band_.at(i)))
00302 {
00303 bubble_connect = i;
00304 connected = true;
00305 break;
00306 }
00307 }
00308 }
00309
00310
00311 std::vector<Bubble> tmp_band;
00312 std::vector<Bubble>::iterator tmp_iter1, tmp_iter2;
00313
00314 tmp_band.assign(band_to_add.begin(), band_to_add.end());
00315
00316 if(connected)
00317 {
00318 ROS_DEBUG("Connections found - composing new band by connecting new frames to bubble %d", bubble_connect);
00319 if(add_frames_at == add_front)
00320 {
00321
00322 tmp_iter1 = elastic_band_.begin() + bubble_connect;
00323 ROS_ASSERT( (tmp_iter1 >= elastic_band_.begin()) && (tmp_iter1 < elastic_band_.end()) );
00324 tmp_band.insert(tmp_band.end(), tmp_iter1, elastic_band_.end());
00325 }
00326 else
00327 {
00328
00329 tmp_iter1 = elastic_band_.begin() + bubble_connect + 1;
00330 ROS_ASSERT( (tmp_iter1 > elastic_band_.begin()) && (tmp_iter1 <= elastic_band_.end()) );
00331 tmp_band.insert(tmp_band.begin(), elastic_band_.begin(), tmp_iter1);
00332 }
00333
00334
00335 elastic_band_ = tmp_band;
00336 return true;
00337 }
00338
00339
00340 ROS_DEBUG("No direct connection found - Composing tmp band and trying to fill gap");
00341 if(add_frames_at == add_front)
00342 {
00343
00344 tmp_band.insert(tmp_band.end(), elastic_band_.begin(), elastic_band_.end());
00345
00346 tmp_iter1 = tmp_band.begin() + ((int) band_to_add.size()) - 1;
00347 tmp_iter2 = tmp_iter1 + 1;
00348 }
00349 else
00350 {
00351
00352 tmp_band.insert(tmp_band.begin(), elastic_band_.begin(), elastic_band_.end());
00353
00354 tmp_iter1 = tmp_band.begin() + ((int) elastic_band_.size()) - 1;
00355 tmp_iter2 = tmp_iter1 + 1;
00356 }
00357
00358
00359 ROS_ASSERT( tmp_iter1 >= tmp_band.begin() );
00360 ROS_ASSERT( tmp_iter2 < tmp_band.end() );
00361 ROS_ASSERT( tmp_iter1 < tmp_iter2 );
00362 if(!fillGap(tmp_band, tmp_iter1, tmp_iter2))
00363 {
00364
00365 ROS_DEBUG("Could not connect robot pose to band - Failed to fill gap.");
00366 return false;
00367 }
00368
00369
00370 elastic_band_ = tmp_band;
00371
00372 return true;
00373 }
00374
00375
00376 bool EBandPlanner::optimizeBand()
00377 {
00378
00379 if(!initialized_)
00380 {
00381 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00382 return false;
00383 }
00384
00385
00386 if(elastic_band_.empty())
00387 {
00388 ROS_ERROR("Band is empty. Probably Band has not been set yet");
00389 return false;
00390 }
00391
00392
00393 ROS_DEBUG("Starting optimization of band");
00394 if(!optimizeBand(elastic_band_))
00395 {
00396 ROS_DEBUG("Aborting Optimization. Changes discarded.");
00397 return false;
00398 }
00399
00400 ROS_DEBUG("Elastic Band - Optimization successfull!");
00401 return true;
00402 }
00403
00404
00405 bool EBandPlanner::optimizeBand(std::vector<Bubble>& band)
00406 {
00407
00408 if(!initialized_)
00409 {
00410 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00411 return false;
00412 }
00413
00414
00415 costmap_ros_->getCostmapCopy(costmap_);
00416
00417
00418 if(band.front().center.header.frame_id != costmap_ros_->getGlobalFrameID())
00419 {
00420 ROS_ERROR("Elastic Band expects plan for optimization in the %s frame, the plan was sent in the %s frame.",
00421 costmap_ros_->getGlobalFrameID().c_str(), band.front().center.header.frame_id.c_str());
00422 return false;
00423 }
00424
00425 double distance;
00426 for(int i = 0; i < ((int) band.size()); i++)
00427 {
00428
00429 if(!calcObstacleKinematicDistance(band.at(i).center.pose, distance))
00430 {
00431 ROS_DEBUG("Optimization (Elastic Band) - Calculation of Distance failed. Frame %d of %d Probably outside map coordinates.",
00432 i, ((int) band.size()) );
00433 return false;
00434 }
00435
00436 if(distance == 0.0)
00437 {
00438
00439 ROS_DEBUG("Optimization (Elastic Band) - Calculation of Distance failed. Frame %d of %d in collision. Plan invalid. Trying to refine band.",
00440 i, ((int) band.size()) );
00441
00442 return false;
00443 }
00444
00445 band.at(i).expansion = distance;
00446 }
00447
00448
00449 if(!refineBand(band))
00450 {
00451 ROS_DEBUG("Elastic Band is broken. Could not close gaps in band. Global replanning needed.");
00452 return false;
00453 }
00454
00455
00456 std::vector<Bubble> tmp_band = band;
00457
00458
00459 for(int i = 0; i < num_optim_iterations_; i++)
00460 {
00461 ROS_DEBUG("Inside optimization: Cycle no %d", i);
00462
00463
00464 if(!modifyBandArtificialForce(tmp_band))
00465 {
00466 ROS_DEBUG("Optimization failed while trying to modify Band.");
00467
00468 return false;
00469 }
00470
00471
00472 if(!refineBand(tmp_band))
00473 {
00474 ROS_DEBUG("Optimization failed while trying to refine modified band");
00475
00476 return false;
00477 }
00478 }
00479
00480
00481 band = tmp_band;
00482 return true;
00483 }
00484
00485
00486
00487
00488 bool EBandPlanner::refineBand(std::vector<Bubble>& band)
00489 {
00490
00491 if(!initialized_)
00492 {
00493 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00494 return false;
00495 }
00496
00497
00498 if(band.size() < 2)
00499 {
00500 ROS_WARN("Attempt to convert empty band to plan. Valid band needs to have at least 2 Frames. This one has %d.", ((int) band.size()) );
00501 return false;
00502 }
00503
00504
00505 bool success;
00506 std::vector<Bubble> tmp_band;
00507 std::vector<Bubble>::iterator start_iter, end_iter;
00508
00509
00510 tmp_band = band;
00511 start_iter = tmp_band.begin();
00512 end_iter = (tmp_band.end() - 1);
00513
00514 success = removeAndFill(tmp_band, start_iter, end_iter);
00515
00516 if(!success)
00517 ROS_DEBUG("Band is broken. Could not close gaps.");
00518 else
00519 {
00520 #ifdef DEBUG_EBAND_
00521 ROS_DEBUG("Recursive filling and removing DONE");
00522 #endif
00523 band = tmp_band;
00524 }
00525
00526 return success;
00527 }
00528
00529
00530 bool EBandPlanner::removeAndFill(std::vector<Bubble>& band, std::vector<Bubble>::iterator& start_iter,std::vector<Bubble>::iterator& end_iter)
00531 {
00532
00533 bool overlap;
00534 std::vector<Bubble>::iterator tmp_iter;
00535 int mid_int, diff_int;
00536
00537 #ifdef DEBUG_EBAND_
00538 int debug_dist_start, debug_dist_iters;
00539 debug_dist_start = std::distance(band.begin(), start_iter);
00540 debug_dist_iters = std::distance(start_iter, end_iter);
00541 ROS_DEBUG("Refining Recursive - Check if Bubbles %d and %d overlapp. Total size of band %d.", debug_dist_start, (debug_dist_start + debug_dist_iters), ((int) band.size()) );
00542 #endif
00543
00544
00545 ROS_ASSERT( start_iter >= band.begin() );
00546 ROS_ASSERT( end_iter < band.end() );
00547 ROS_ASSERT( start_iter < end_iter );
00548
00549
00550 overlap = checkOverlap(*start_iter, *end_iter);
00551
00552 if(overlap)
00553 {
00554
00555 #ifdef DEBUG_EBAND_
00556 ROS_DEBUG("Refining Recursive - Bubbles overlapp, check for redundancies");
00557 #endif
00558
00559
00560 if((start_iter + 1) < end_iter)
00561 {
00562 #ifdef DEBUG_EBAND_
00563 ROS_DEBUG("Refining Recursive - Bubbles overlapp, removing Bubbles %d to %d.", (debug_dist_start + 1), (debug_dist_start + debug_dist_iters -1));
00564 #endif
00565
00566
00567 tmp_iter = band.erase((start_iter+1), end_iter);
00568
00569
00570 end_iter = tmp_iter;
00571 }
00572
00573 #ifdef DEBUG_EBAND_
00574 ROS_DEBUG("Refining Recursive - Bubbles overlapp - DONE");
00575 #endif
00576
00577
00578 return true;
00579 }
00580
00581
00582
00583 if((start_iter + 1) < end_iter)
00584 {
00585 #ifdef DEBUG_EBAND_
00586 ROS_DEBUG("Refining Recursive - Bubbles do not overlapp, go one recursion deeper");
00587 #endif
00588
00589
00590
00591 mid_int = std::distance(start_iter, end_iter);
00592 mid_int = mid_int/2;
00593
00594
00595 tmp_iter = start_iter + mid_int;
00596
00597 diff_int = (int) std::distance(tmp_iter, end_iter);
00598
00599
00600 ROS_ASSERT( start_iter >= band.begin() );
00601 ROS_ASSERT( end_iter < band.end() );
00602 ROS_ASSERT( start_iter < end_iter );
00603
00604
00605
00606 if(!removeAndFill(band, start_iter, tmp_iter))
00607 {
00608
00609 return false;
00610 }
00611
00612
00613
00614 end_iter = tmp_iter + diff_int;
00615
00616
00617 ROS_ASSERT( start_iter >= band.begin() );
00618 ROS_ASSERT( end_iter < band.end() );
00619 ROS_ASSERT( (start_iter < tmp_iter) && (tmp_iter < end_iter) );
00620
00621
00622
00623
00624 diff_int = (int) std::distance(start_iter, tmp_iter);
00625 if(!removeAndFill(band, tmp_iter, end_iter))
00626 {
00627
00628 return false;
00629 }
00630
00631
00632 start_iter = tmp_iter - diff_int;
00633
00634
00635 ROS_ASSERT( start_iter >= band.begin() );
00636 ROS_ASSERT( end_iter < band.end() );
00637 ROS_ASSERT( (start_iter < tmp_iter) && (tmp_iter < end_iter) );
00638
00639
00640
00641
00642
00643
00644 if(checkOverlap(*(tmp_iter-1), *(tmp_iter+1)))
00645 {
00646 #ifdef DEBUG_EBAND_
00647 ROS_DEBUG("Refining Recursive - Removing middle bubble");
00648 #endif
00649
00650
00651 diff_int = (int) std::distance((tmp_iter + 1), end_iter);
00652
00653
00654 tmp_iter = band.erase(tmp_iter);
00655 end_iter = tmp_iter + diff_int;
00656 }
00657
00658
00659 ROS_ASSERT( start_iter >= band.begin() );
00660 ROS_ASSERT( end_iter < band.end() );
00661 ROS_ASSERT( start_iter < end_iter );
00662
00663 #ifdef DEBUG_EBAND_
00664 ROS_DEBUG("Refining Recursive - Bubbles do not overlapp, go one recursion deeper DONE");
00665 #endif
00666
00667
00668 return true;
00669 }
00670
00671
00672 #ifdef DEBUG_EBAND_
00673 ROS_DEBUG("Refining Recursive - Gap detected, fill recursive");
00674 #endif
00675
00676
00677 if(!fillGap(band, start_iter, end_iter))
00678 {
00679
00680 ROS_DEBUG("Failed to fill gap between bubble %d and %d.", (int) distance(band.begin(), start_iter), (int) distance(band.begin(), end_iter) );
00681 return false;
00682 }
00683
00684 #ifdef DEBUG_EBAND_
00685 ROS_DEBUG("Refining Recursive - Gap detected, fill recursive DONE");
00686 #endif
00687
00688
00689 return true;
00690 }
00691
00692
00693 bool EBandPlanner::fillGap(std::vector<Bubble>& band, std::vector<Bubble>::iterator& start_iter,std::vector<Bubble>::iterator& end_iter)
00694 {
00695
00696
00697
00698
00699 double distance = 0.0;
00700 Bubble interpolated_bubble;
00701 geometry_msgs::PoseStamped interpolated_center;
00702 std::vector<Bubble>::iterator tmp_iter;
00703 int diff_int, start_num, end_num;
00704
00705
00706 ROS_ASSERT( start_iter >= band.begin() );
00707 ROS_ASSERT( end_iter < band.end() );
00708 ROS_ASSERT( start_iter < end_iter );
00709
00710
00711 #ifdef DEBUG_EBAND_
00712 ROS_DEBUG("Fill recursive - interpolate");
00713 #endif
00714
00715
00716 if(!interpolateBubbles(start_iter->center, end_iter->center, interpolated_center))
00717 {
00718
00719 start_num = std::distance(band.begin(), start_iter);
00720 end_num = std::distance(band.begin(), end_iter);
00721 ROS_DEBUG("Interpolation failed while trying to fill gap between bubble %d and %d.", start_num, end_num);
00722 return false;
00723 }
00724
00725
00726 #ifdef DEBUG_EBAND_
00727 ROS_DEBUG("Fill recursive - calc expansion of interpolated bubble");
00728 #endif
00729
00730
00731 if(!calcObstacleKinematicDistance(interpolated_center.pose, distance))
00732 {
00733
00734 start_num = std::distance(band.begin(), start_iter);
00735 end_num = std::distance(band.begin(), end_iter);
00736 ROS_DEBUG("Calculation of Distance failed for interpolated bubble - failed to fill gap between bubble %d and %d.", start_num, end_num);
00737 return false;
00738 }
00739
00740 if(distance <= tiny_bubble_expansion_)
00741 {
00742
00743 start_num = std::distance(band.begin(), start_iter);
00744 end_num = std::distance(band.begin(), end_iter);
00745 ROS_DEBUG("Interpolated Bubble in Collision - failed to fill gap between bubble %d and %d.", start_num, end_num);
00746
00747 return false;
00748 }
00749
00750
00751 #ifdef DEBUG_EBAND_
00752 ROS_DEBUG("Fill recursive - inserting interpolated bubble at (%f, %f), with expansion %f", interpolated_center.pose.position.x, interpolated_center.pose.position.y, distance);
00753 #endif
00754
00755
00756 interpolated_bubble.center = interpolated_center;
00757 interpolated_bubble.expansion = distance;
00758
00759 tmp_iter = band.insert(end_iter, interpolated_bubble);
00760
00761 start_iter = tmp_iter - 1;
00762 end_iter = tmp_iter + 1;
00763
00764
00765 ROS_ASSERT( start_iter >= band.begin() );
00766 ROS_ASSERT( end_iter < band.end() );
00767 ROS_ASSERT( (start_iter < tmp_iter) && (tmp_iter < end_iter) );
00768
00769
00770 #ifdef DEBUG_EBAND_
00771 ROS_DEBUG("Fill recursive - check overlap interpolated bubble and first bubble");
00772 #endif
00773
00774
00775 if(!checkOverlap(*start_iter, *tmp_iter))
00776 {
00777
00778 #ifdef DEBUG_EBAND
00779 ROS_DEBUG("Fill recursive - gap btw. interpolated and first bubble - fill recursive");
00780 #endif
00781
00782
00783 if(!fillGap(band, start_iter, tmp_iter))
00784 {
00785
00786 return false;
00787 }
00788
00789 end_iter = tmp_iter + 1;
00790 }
00791
00792
00793 ROS_ASSERT( start_iter >= band.begin() );
00794 ROS_ASSERT( end_iter < band.end() );
00795 ROS_ASSERT( (start_iter < tmp_iter) && (tmp_iter < end_iter) );
00796
00797
00798 #ifdef DEBUG_EBAND_
00799 ROS_DEBUG("Fill recursive - check overlap interpolated bubble and second bubble");
00800 #endif
00801
00802 if(!checkOverlap(*tmp_iter, *end_iter))
00803 {
00804
00805 #ifdef DEBUG_EBAND_
00806 ROS_DEBUG("Fill recursive - gap btw. interpolated and second bubble - fill recursive");
00807 #endif
00808
00809
00810 diff_int = (int) std::distance(start_iter, tmp_iter);
00811
00812
00813 if(!fillGap(band, tmp_iter, end_iter))
00814 {
00815
00816 return false;
00817 }
00818
00819 start_iter = tmp_iter - diff_int;
00820 }
00821
00822
00823 ROS_ASSERT( start_iter >= band.begin() );
00824 ROS_ASSERT( end_iter < band.end() );
00825 ROS_ASSERT( (start_iter < tmp_iter) && (tmp_iter < end_iter) );
00826
00827
00828 #ifdef DEBUG_EBAND_
00829 ROS_DEBUG("Fill recursive - gap closed");
00830 #endif
00831
00832
00833 return true;
00834 }
00835
00836
00837
00838
00839 bool EBandPlanner::modifyBandArtificialForce(std::vector<Bubble>& band)
00840 {
00841 if(band.empty())
00842 {
00843 ROS_ERROR("Trying to modify an empty band.");
00844 return false;
00845 }
00846
00847 if(band.size() <= 2)
00848 {
00849
00850 return true;
00851 }
00852
00853 std::vector<geometry_msgs::WrenchStamped> internal_forces, external_forces, forces;
00854 geometry_msgs::WrenchStamped wrench;
00855
00856 #ifdef DEBUG_EBAND_
00857
00858 if(visualization_)
00859 eband_visual_->publishBand("bubbles", band);
00860 #endif
00861
00862
00863 wrench.header.stamp = ros::Time::now();
00864 wrench.header.frame_id = band[0].center.header.frame_id;
00865 wrench.wrench.force.x = 0.0;
00866 wrench.wrench.force.y = 0.0;
00867 wrench.wrench.force.z = 0.0;
00868 wrench.wrench.torque.x = 0.0;
00869 wrench.wrench.torque.y = 0.0;
00870 wrench.wrench.torque.z = 0.0;
00871 internal_forces.assign(band.size(), wrench);
00872 external_forces = internal_forces;
00873 forces = internal_forces;
00874
00875
00876
00877
00878
00879
00880
00881
00882 int i = 1;
00883 bool forward = true;
00884 while( (i>0) && (i < ((int) band.size() - 1)) )
00885 {
00886 ROS_DEBUG("Modifying bubble %d.", i);
00887
00888
00889 #ifdef DEBUG_EBAND_
00890 ROS_DEBUG("Calculating internal force for bubble %d.", i);
00891 #endif
00892
00893 if(!calcInternalForces(i, band, band.at(i), internal_forces.at(i)))
00894 {
00895
00896 ROS_DEBUG("Calculation of internal forces failed");
00897 return false;
00898 }
00899
00900 #ifdef DEBUG_EBAND_
00901 if(visualization_)
00902
00903 eband_visual_->publishForce("internal_forces", i, eband_visual_->blue, internal_forces[i], band[i]);
00904
00905 ROS_DEBUG("Calculating external force for bubble %d.", i);
00906 #endif
00907
00908
00909
00910 if(!calcExternalForces(i, band.at(i), external_forces.at(i)))
00911 {
00912
00913 ROS_DEBUG("Calculation of external forces failed");
00914 return false;
00915 }
00916
00917 #ifdef DEBUG_EBAND_
00918 if(visualization_)
00919
00920 eband_visual_->publishForce("external_forces", i, eband_visual_->red, external_forces[i], band[i]);
00921
00922 ROS_DEBUG("Superposing internal and external forces");
00923 #endif
00924
00925
00926
00927 forces.at(i).wrench.force.x = internal_forces.at(i).wrench.force.x + external_forces.at(i).wrench.force.x;
00928 forces.at(i).wrench.force.y = internal_forces.at(i).wrench.force.y + external_forces.at(i).wrench.force.y;
00929 forces.at(i).wrench.force.z = internal_forces.at(i).wrench.force.z + external_forces.at(i).wrench.force.z;
00930
00931 forces.at(i).wrench.torque.x = internal_forces.at(i).wrench.torque.x + external_forces.at(i).wrench.torque.x;
00932 forces.at(i).wrench.torque.y = internal_forces.at(i).wrench.torque.y + external_forces.at(i).wrench.torque.y;
00933 forces.at(i).wrench.torque.z = internal_forces.at(i).wrench.torque.z + external_forces.at(i).wrench.torque.z;
00934
00935 #ifdef DEBUG_EBAND_
00936 ROS_DEBUG("Superpose forces: (x, y, theta) = (%f, %f, %f)", forces.at(i).wrench.force.x, forces.at(i).wrench.force.y, forces.at(i).wrench.torque.z);
00937 ROS_DEBUG("Supressing tangential forces");
00938 #endif
00939
00940 if(!suppressTangentialForces(i, band, forces.at(i)))
00941 {
00942
00943 ROS_DEBUG("Supression of tangential forces failed");
00944 return false;
00945 }
00946
00947 #ifdef DEBUG_EBAND_
00948 if(visualization_)
00949
00950 eband_visual_->publishForce("resulting_forces", i, eband_visual_->green, forces[i], band[i]);
00951 #endif
00952
00953
00954 ROS_DEBUG("Applying forces to modify band");
00955 if(!applyForces(i, band, forces))
00956 {
00957
00958 ROS_DEBUG("Band is invalid - Stopping Modification");
00959 return false;
00960 }
00961
00962 #ifdef DEBUG_EBAND_
00963 if(visualization_)
00964 {
00965
00966 eband_visual_->publishBand("bubbles", band);
00967 ros::Duration(0.01).sleep();
00968 }
00969 #endif
00970
00971
00972
00973 if(forward)
00974 {
00975 i++;
00976 if(i == ((int) band.size() - 1))
00977 {
00978
00979 forward = false;
00980 i--;
00981 ROS_DEBUG("Optimization Elastic Band - Forward cycle done, starting backward cycle");
00982 }
00983 }
00984 else
00985 {
00986 i--;
00987 }
00988 }
00989
00990 return true;
00991 }
00992
00993
00994 bool EBandPlanner::applyForces(int bubble_num, std::vector<Bubble>& band, std::vector<geometry_msgs::WrenchStamped> forces)
00995 {
00996
00997 if(band.size() <= 2)
00998 {
00999
01000 return true;
01001 }
01002
01003 geometry_msgs::Pose2D bubble_pose2D, new_bubble_pose2D;
01004 geometry_msgs::Pose bubble_pose, new_bubble_pose;
01005 geometry_msgs::Twist bubble_jump;
01006 Bubble new_bubble = band.at(bubble_num);
01007 double distance;
01008
01009
01010
01011 bubble_pose = band.at(bubble_num).center.pose;
01012 PoseToPose2D(bubble_pose, bubble_pose2D);
01013
01014
01015 bubble_jump.linear.x = band.at(bubble_num).expansion*forces.at(bubble_num).wrench.force.x;
01016 bubble_jump.linear.y = band.at(bubble_num).expansion*forces.at(bubble_num).wrench.force.y;
01017 bubble_jump.linear.z = 0.0;
01018 bubble_jump.angular.x = 0.0;
01019 bubble_jump.angular.y = 0.0;
01020 bubble_jump.angular.z = band.at(bubble_num).expansion/costmap_ros_->getCircumscribedRadius() * forces.at(bubble_num).wrench.torque.z;
01021 bubble_jump.angular.z = angles::normalize_angle(bubble_jump.angular.z);
01022
01023
01024 new_bubble_pose2D.x = bubble_pose2D.x + bubble_jump.linear.x;
01025 new_bubble_pose2D.y = bubble_pose2D.y + bubble_jump.linear.y;
01026 new_bubble_pose2D.theta = bubble_pose2D.theta + bubble_jump.angular.z;
01027 new_bubble_pose2D.theta = angles::normalize_angle(new_bubble_pose2D.theta);
01028
01029
01030 Pose2DToPose(new_bubble_pose, new_bubble_pose2D);
01031 new_bubble.center.pose = new_bubble_pose;
01032
01033 #ifdef DEBUG_EBAND_
01034 ROS_DEBUG("Try moving bubble %d at (%f, %f, %f) by (%f, %f, %f).", bubble_num, bubble_pose2D.x, bubble_pose2D.y, bubble_pose2D.theta,
01035 bubble_jump.linear.x, bubble_jump.linear.y, bubble_jump.angular.z);
01036 #endif
01037
01038
01039
01040
01041
01042 if(!calcObstacleKinematicDistance(new_bubble_pose, distance))
01043 {
01044 ROS_DEBUG("Calculation of Distance failed. Frame %d of %d Probably outside map. Discarding Changes", bubble_num, ((int) band.size()) );
01045
01046 #ifdef DEBUG_EBAND_
01047 if(visualization_)
01048 eband_visual_->publishBubble("bubble_hypo", bubble_num, eband_visual_->red, new_bubble);
01049 #endif
01050
01051
01052 return true;
01053 }
01054
01055 if(distance <= tiny_bubble_expansion_)
01056 {
01057
01058 ROS_DEBUG("Calculation of Distance failed. Frame %d of %d in collision. Plan invalid. Discarding Changes", bubble_num, ((int) band.size()) );
01059
01060 #ifdef DEBUG_EBAND_
01061 if(visualization_)
01062 eband_visual_->publishBubble("bubble_hypo", bubble_num, eband_visual_->red, new_bubble);
01063 #endif
01064
01065
01066 return true;
01067 }
01068
01069
01070 new_bubble.expansion = distance;
01071
01072
01073
01074
01075 geometry_msgs::WrenchStamped new_bubble_force = forces.at(bubble_num);
01076
01077
01078 if(!getForcesAt(bubble_num, band, new_bubble, new_bubble_force))
01079 {
01080
01081 ROS_DEBUG("Cannot calculate forces on bubble %d at new position - discarding changes", bubble_num);
01082 return true;
01083 }
01084
01085 #ifdef DEBUG_EBAND_
01086 ROS_DEBUG("Check for zero-crossings in force on bubble %d", bubble_num);
01087 #endif
01088
01089
01090 double checksum_zero, abs_new_force, abs_old_force;
01091
01092
01093 checksum_zero = (new_bubble_force.wrench.force.x * forces.at(bubble_num).wrench.force.x) +
01094 (new_bubble_force.wrench.force.y * forces.at(bubble_num).wrench.force.y) +
01095 (new_bubble_force.wrench.torque.z * forces.at(bubble_num).wrench.torque.z);
01096
01097
01098 if(checksum_zero < 0.0)
01099 {
01100 ROS_DEBUG("Detected zero-crossings in force on bubble %d. Checking total change in force.", bubble_num);
01101
01102 abs_new_force = sqrt( (new_bubble_force.wrench.force.x * new_bubble_force.wrench.force.x) +
01103 (new_bubble_force.wrench.force.y * new_bubble_force.wrench.force.y) +
01104 (new_bubble_force.wrench.torque.z * new_bubble_force.wrench.torque.z) );
01105 abs_old_force = sqrt( (forces.at(bubble_num).wrench.force.x * forces.at(bubble_num).wrench.force.x) +
01106 (forces.at(bubble_num).wrench.force.x * forces.at(bubble_num).wrench.force.x) +
01107 (forces.at(bubble_num).wrench.torque.z * forces.at(bubble_num).wrench.torque.z) );
01108
01109
01110 if( (abs_new_force > equilibrium_relative_overshoot_ * abs_old_force) && (abs_new_force > significant_force_) )
01111 {
01112 ROS_DEBUG("Detected significante change in force (%f to %f) on bubble %d. Entering Recursive Approximation.", abs_old_force, abs_new_force, bubble_num);
01113
01114 int curr_recursion_depth = 0;
01115 geometry_msgs::Twist new_step_width;
01116 Bubble curr_bubble = band.at(bubble_num);
01117 geometry_msgs::WrenchStamped curr_bubble_force = forces.at(bubble_num);
01118
01119
01120 new_step_width.linear.x = 0.5*bubble_jump.linear.x;
01121 new_step_width.linear.y = 0.5*bubble_jump.linear.y;
01122 new_step_width.linear.z = 0.5*bubble_jump.linear.z;
01123 new_step_width.angular.x = 0.5*bubble_jump.angular.x;
01124 new_step_width.angular.y = 0.5*bubble_jump.angular.y;
01125 new_step_width.angular.z = 0.5*bubble_jump.angular.z;
01126
01127
01128 if(moveApproximateEquilibrium(bubble_num, band, curr_bubble, curr_bubble_force, new_step_width, curr_recursion_depth))
01129 {
01130
01131 new_bubble = curr_bubble;
01132
01133 #ifdef DEBUG_EBAND_
01134 geometry_msgs::Pose2D curr_bubble_pose2D;
01135 PoseToPose2D(curr_bubble.center.pose, curr_bubble_pose2D);
01136 ROS_DEBUG("Instead - Try moving bubble %d at (%f, %f, %f) by (%f, %f, %f) to (%f, %f, %f).",
01137 bubble_num, bubble_pose2D.x, bubble_pose2D.y, bubble_pose2D.theta,
01138 new_step_width.linear.x, new_step_width.linear.y, new_step_width.angular.z,
01139 curr_bubble_pose2D.x, curr_bubble_pose2D.y, curr_bubble_pose2D.theta);
01140 #endif
01141 }
01142 }
01143 }
01144
01145
01146
01147
01148
01149
01150 std::vector<Bubble> tmp_band = band;
01151 std::vector<Bubble>::iterator start_iter, end_iter;
01152 tmp_band.at(bubble_num) = new_bubble;
01153 start_iter = tmp_band.begin();
01154
01155
01156 start_iter = start_iter + bubble_num - 1;
01157 end_iter = start_iter + 1;
01158
01159
01160 if(!checkOverlap(*start_iter, *end_iter))
01161 {
01162 if(!fillGap(tmp_band, start_iter, end_iter))
01163 {
01164 ROS_DEBUG("Bubble at new position cannot be connected to neighbour. Discarding changes.");
01165
01166 return true;
01167 }
01168 }
01169
01170
01171
01172 tmp_band = band;
01173 tmp_band.at(bubble_num) = new_bubble;
01174 start_iter = tmp_band.begin();
01175
01176
01177 start_iter = start_iter + bubble_num;
01178 end_iter = start_iter + 1;
01179
01180
01181 if(!checkOverlap(*start_iter, *end_iter))
01182 {
01183 if(!fillGap(tmp_band, start_iter, end_iter))
01184 {
01185 ROS_DEBUG("Bubble at new position cannot be connected to neighbour. Discarding changes.");
01186
01187 return true;
01188 }
01189 }
01190
01191
01192
01193
01194 #ifdef DEBUG_EBAND_
01195 ROS_DEBUG("Frame %d of %d: Check successful - bubble and band valid. Applying Changes", bubble_num, ((int) band.size()) );
01196 #endif
01197
01198 band.at(bubble_num) = new_bubble;
01199
01200 return true;
01201 }
01202
01203
01204 bool EBandPlanner::moveApproximateEquilibrium(const int& bubble_num, const std::vector<Bubble>& band, Bubble& curr_bubble,
01205 const geometry_msgs::WrenchStamped& curr_bubble_force, geometry_msgs::Twist& curr_step_width, const int& curr_recursion_depth)
01206 {
01207
01208 double distance;
01209 Bubble new_bubble = curr_bubble;
01210 geometry_msgs::Pose2D new_bubble_pose2D, curr_bubble_pose2D;
01211 geometry_msgs::WrenchStamped new_bubble_force = curr_bubble_force;
01212
01213
01214 PoseToPose2D(curr_bubble.center.pose, curr_bubble_pose2D);
01215 PoseToPose2D(new_bubble.center.pose, new_bubble_pose2D);
01216
01217
01218 new_bubble_pose2D.x = curr_bubble_pose2D.x + curr_step_width.linear.x;
01219 new_bubble_pose2D.y = curr_bubble_pose2D.y + curr_step_width.linear.y;
01220 new_bubble_pose2D.theta = curr_bubble_pose2D.theta + curr_step_width.angular.z;
01221 new_bubble_pose2D.theta = angles::normalize_angle(new_bubble_pose2D.theta);
01222
01223
01224 Pose2DToPose(new_bubble.center.pose, new_bubble_pose2D);
01225
01226
01227
01228
01229
01230 if(!calcObstacleKinematicDistance(new_bubble.center.pose, distance))
01231 return false;
01232
01233
01234 if(distance == 0.0)
01235 return false;
01236
01237
01238
01239 new_bubble.expansion = distance;
01240
01241
01242 if(!getForcesAt(bubble_num, band, new_bubble, new_bubble_force))
01243 return false;
01244
01245
01246 curr_bubble = new_bubble;
01247
01248
01249 if(curr_recursion_depth >= max_recursion_depth_approx_equi_)
01250
01251 return true;
01252
01253
01254
01255
01256 #ifdef DEBUG_EBAND_
01257 ROS_DEBUG("Check for zero-crossings in force on bubble %d - Recursion %d", bubble_num, curr_recursion_depth);
01258 #endif
01259
01260 double checksum_zero, abs_new_force, abs_old_force;
01261 int new_recursion_depth;
01262 geometry_msgs::Twist new_step_width;
01263
01264
01265 checksum_zero = (new_bubble_force.wrench.force.x * curr_bubble_force.wrench.force.x) +
01266 (new_bubble_force.wrench.force.y * curr_bubble_force.wrench.force.y) +
01267 (new_bubble_force.wrench.torque.z * curr_bubble_force.wrench.torque.z);
01268
01269 if(checksum_zero < 0.0)
01270 {
01271 #ifdef DEBUG_EBAND_
01272 ROS_DEBUG("Detected zero-crossings in force on bubble %d - Recursion %d. Checking total change in force.", bubble_num, curr_recursion_depth);
01273 #endif
01274
01275
01276 abs_new_force = sqrt( (new_bubble_force.wrench.force.x * new_bubble_force.wrench.force.x) +
01277 (new_bubble_force.wrench.force.y * new_bubble_force.wrench.force.y) +
01278 (new_bubble_force.wrench.torque.z * new_bubble_force.wrench.torque.z) );
01279 abs_old_force = sqrt( (curr_bubble_force.wrench.force.x * curr_bubble_force.wrench.force.x) +
01280 (curr_bubble_force.wrench.force.x * curr_bubble_force.wrench.force.x) +
01281 (curr_bubble_force.wrench.torque.z * curr_bubble_force.wrench.torque.z) );
01282
01283 if( (abs_new_force > equilibrium_relative_overshoot_ * abs_old_force) && (abs_new_force > significant_force_) )
01284 {
01285 #ifdef DEBUG_EBAND_
01286 ROS_DEBUG("Detected significant change in force (%f to %f) on bubble %d - Recursion %d. Going one Recursion deeper.", abs_old_force, abs_new_force, bubble_num, curr_recursion_depth);
01287 #endif
01288
01289
01290 new_recursion_depth = curr_recursion_depth + 1;
01291
01292 new_step_width.linear.x = -0.5*curr_step_width.linear.x;
01293 new_step_width.linear.y = -0.5*curr_step_width.linear.y;
01294 new_step_width.linear.z = -0.5*curr_step_width.linear.z;
01295 new_step_width.angular.x = -0.5*curr_step_width.angular.x;
01296 new_step_width.angular.y = -0.5*curr_step_width.angular.y;
01297 new_step_width.angular.z = -0.5*curr_step_width.angular.z;
01298
01299
01300 if(moveApproximateEquilibrium(bubble_num, band, new_bubble, new_bubble_force, new_step_width, new_recursion_depth))
01301
01302 curr_bubble = new_bubble;
01303
01304
01305 }
01306
01307
01308 }
01309 else
01310 {
01311 #ifdef DEBUG_EBAND_
01312 ROS_DEBUG("No zero-crossings in force on bubble %d - Recursion %d. Continue walk in same direction. Going one recursion deeper.", bubble_num, curr_recursion_depth);
01313 #endif
01314
01315
01316 new_recursion_depth = curr_recursion_depth + 1;
01317
01318 new_step_width.linear.x = 0.5*curr_step_width.linear.x;
01319 new_step_width.linear.y = 0.5*curr_step_width.linear.y;
01320 new_step_width.linear.z = 0.5*curr_step_width.linear.z;
01321 new_step_width.angular.x = 0.5*curr_step_width.angular.x;
01322 new_step_width.angular.y = 0.5*curr_step_width.angular.y;
01323 new_step_width.angular.z = 0.5*curr_step_width.angular.z;
01324
01325
01326 if(moveApproximateEquilibrium(bubble_num, band, new_bubble, new_bubble_force, new_step_width, new_recursion_depth))
01327
01328 curr_bubble = new_bubble;
01329
01330
01331 }
01332
01333
01334 return true;
01335 }
01336
01337
01338 bool EBandPlanner::getForcesAt(int bubble_num, std::vector<Bubble> band, Bubble curr_bubble, geometry_msgs::WrenchStamped& forces)
01339 {
01340 geometry_msgs::WrenchStamped internal_force, external_force;
01341
01342 if(!calcInternalForces(bubble_num, band, curr_bubble, internal_force))
01343 {
01344
01345 ROS_DEBUG("Calculation of internal forces failed");
01346 return false;
01347 }
01348
01349 if(!calcExternalForces(bubble_num, curr_bubble, external_force))
01350 {
01351
01352 ROS_DEBUG("Calculation of external forces failed");
01353 return false;
01354 }
01355
01356
01357 forces.wrench.force.x = internal_force.wrench.force.x + external_force.wrench.force.x;
01358 forces.wrench.force.y = internal_force.wrench.force.y + external_force.wrench.force.y;
01359 forces.wrench.force.z = internal_force.wrench.force.z + external_force.wrench.force.z;
01360
01361 forces.wrench.torque.x = internal_force.wrench.torque.x + external_force.wrench.torque.x;
01362 forces.wrench.torque.y = internal_force.wrench.torque.y + external_force.wrench.torque.y;
01363 forces.wrench.torque.z = internal_force.wrench.torque.z + external_force.wrench.torque.z;
01364
01365 if(!suppressTangentialForces(bubble_num, band, forces))
01366 {
01367
01368 ROS_DEBUG("Supression of tangential forces failed");
01369 return false;
01370 }
01371
01372 return true;
01373 }
01374
01375
01376 bool EBandPlanner::calcInternalForces(int bubble_num, std::vector<Bubble> band, Bubble curr_bubble, geometry_msgs::WrenchStamped& forces)
01377 {
01378
01379 if(!initialized_)
01380 {
01381 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01382 return false;
01383 }
01384
01385
01386 if(band.size() <= 2)
01387 {
01388
01389 return true;
01390 }
01391
01392
01393 double distance1, distance2;
01394 geometry_msgs::Twist difference1, difference2;
01395 geometry_msgs::Wrench wrench;
01396
01397
01398 ROS_ASSERT( bubble_num > 0 );
01399 ROS_ASSERT( bubble_num < ((int) band.size() - 1) );
01400
01401
01402
01403 if(!calcBubbleDistance(curr_bubble.center.pose, band[bubble_num-1].center.pose, distance1))
01404 {
01405 ROS_ERROR("Failed to calculate Distance between two bubbles. Aborting calculation of internal forces!");
01406 return false;
01407 }
01408
01409 if(!calcBubbleDistance(curr_bubble.center.pose, band[bubble_num+1].center.pose, distance2))
01410 {
01411 ROS_ERROR("Failed to calculate Distance between two bubbles. Aborting calculation of internal forces!");
01412 return false;
01413 }
01414
01415
01416 if(!calcBubbleDifference(curr_bubble.center.pose, band[bubble_num-1].center.pose, difference1))
01417 {
01418 ROS_ERROR("Failed to calculate Difference between two bubbles. Aborting calculation of internal forces!");
01419 return false;
01420 }
01421
01422 if(!calcBubbleDifference(curr_bubble.center.pose, band[bubble_num+1].center.pose, difference2))
01423 {
01424 ROS_ERROR("Failed to calculate Difference between two bubbles. Aborting calculation of internal forces!");
01425 return false;
01426 }
01427
01428
01429
01430 if(distance1 <= tiny_bubble_distance_)
01431 distance1 = 1000000.0;
01432 if(distance2 <= tiny_bubble_distance_)
01433 distance2 = 1000000.0;
01434
01435
01436 wrench.force.x = internal_force_gain_*(difference1.linear.x/distance1 + difference2.linear.x/distance2);
01437 wrench.force.y = internal_force_gain_*(difference1.linear.y/distance1 + difference2.linear.y/distance2);
01438 wrench.force.z = internal_force_gain_*(difference1.linear.z/distance1 + difference2.linear.z/distance2);
01439 wrench.torque.x = internal_force_gain_*(difference1.angular.x/distance1 + difference2.angular.x/distance2);
01440 wrench.torque.y = internal_force_gain_*(difference1.angular.y/distance1 + difference2.angular.y/distance2);
01441 wrench.torque.z = internal_force_gain_*(difference1.angular.z/distance1 + difference2.angular.z/distance2);
01442
01443 #ifdef DEBUG_EBAND_
01444 ROS_DEBUG("Calculating internal forces: (x, y, theta) = (%f, %f, %f)", wrench.force.x, wrench.force.y, wrench.torque.z);
01445 #endif
01446
01447
01448 forces.wrench = wrench;
01449
01450 return true;
01451 }
01452
01453
01454 bool EBandPlanner::calcExternalForces(int bubble_num, Bubble curr_bubble, geometry_msgs::WrenchStamped& forces)
01455 {
01456
01457 if(!initialized_)
01458 {
01459 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01460 return false;
01461 }
01462
01463
01464 double distance1, distance2;
01465 geometry_msgs::Pose edge;
01466 geometry_msgs::Pose2D edge_pose2D;
01467 geometry_msgs::Wrench wrench;
01468
01469
01470
01471 edge = curr_bubble.center.pose;
01472 edge.position.x = edge.position.x + curr_bubble.expansion;
01473
01474 if(!calcObstacleKinematicDistance(edge, distance1))
01475 {
01476 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01477
01478 return true;
01479 }
01480
01481 edge.position.x = edge.position.x - 2.0*curr_bubble.expansion;
01482
01483 if(!calcObstacleKinematicDistance(edge, distance2))
01484 {
01485 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01486
01487 return true;
01488 }
01489
01490
01491 if(curr_bubble.expansion <= tiny_bubble_expansion_)
01492 {
01493
01494 wrench.force.x = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
01495
01496 ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
01497 }
01498 else
01499 wrench.force.x = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
01500
01501
01502
01503
01504 edge = curr_bubble.center.pose;
01505 edge.position.y = edge.position.y + curr_bubble.expansion;
01506
01507 if(!calcObstacleKinematicDistance(edge, distance1))
01508 {
01509 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01510
01511 return true;
01512 }
01513
01514 edge.position.y = edge.position.y - 2.0*curr_bubble.expansion;
01515
01516 if(!calcObstacleKinematicDistance(edge, distance2))
01517 {
01518 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01519
01520 return true;
01521 }
01522
01523
01524 if(curr_bubble.expansion <= tiny_bubble_expansion_)
01525 {
01526
01527 wrench.force.y = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
01528
01529 ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
01530 }
01531 else
01532 wrench.force.y = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
01533
01534
01535
01536
01537 wrench.force.z = 0.0;
01538
01539
01540
01541 wrench.torque.x = 0.0;
01542 wrench.torque.y = 0.0;
01543
01544
01545
01546 PoseToPose2D(curr_bubble.center.pose, edge_pose2D);
01547 edge_pose2D.theta = edge_pose2D.theta + (curr_bubble.expansion/costmap_ros_->getCircumscribedRadius());
01548 edge_pose2D.theta = angles::normalize_angle(edge_pose2D.theta);
01549 PoseToPose2D(edge, edge_pose2D);
01550
01551 if(!calcObstacleKinematicDistance(edge, distance1))
01552 {
01553 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01554
01555 return true;
01556 }
01557
01558 edge_pose2D.theta = edge_pose2D.theta - 2.0*(curr_bubble.expansion/costmap_ros_->getCircumscribedRadius());
01559 edge_pose2D.theta = angles::normalize_angle(edge_pose2D.theta);
01560 PoseToPose2D(edge, edge_pose2D);
01561
01562 if(!calcObstacleKinematicDistance(edge, distance2))
01563 {
01564 ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
01565
01566 return true;
01567 }
01568
01569
01570 if(curr_bubble.expansion <= tiny_bubble_expansion_)
01571 {
01572
01573 wrench.torque.z = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
01574
01575 ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
01576 }
01577 else
01578 wrench.torque.z = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
01579
01580
01581
01582 #ifdef DEBUG_EBAND_
01583 ROS_DEBUG("Calculating external forces: (x, y, theta) = (%f, %f, %f)", wrench.force.x, wrench.force.y, wrench.torque.z);
01584 #endif
01585
01586
01587 forces.wrench = wrench;
01588
01589 return true;
01590 }
01591
01592
01593 bool EBandPlanner::suppressTangentialForces(int bubble_num, std::vector<Bubble> band, geometry_msgs::WrenchStamped& forces)
01594 {
01595
01596 if(band.size() <= 2)
01597 {
01598
01599 return true;
01600 }
01601
01602 double scalar_fd, scalar_dd;
01603 geometry_msgs::Twist difference;
01604
01605
01606 ROS_ASSERT( bubble_num > 0 );
01607 ROS_ASSERT( bubble_num < ((int) band.size() - 1) );
01608
01609
01610
01611 if(!calcBubbleDifference(band[bubble_num+1].center.pose, band[bubble_num-1].center.pose, difference))
01612 return false;
01613
01614
01615
01616 scalar_fd = forces.wrench.force.x*difference.linear.x + forces.wrench.force.y*difference.linear.y +
01617 forces.wrench.force.z*difference.linear.z + forces.wrench.torque.x*difference.angular.x +
01618 forces.wrench.torque.y*difference.angular.y + forces.wrench.torque.z*difference.angular.z;
01619
01620
01621 scalar_dd = difference.linear.x*difference.linear.x + difference.linear.y*difference.linear.y + difference.linear.z*difference.linear.z +
01622 difference.angular.x*difference.angular.x + difference.angular.y*difference.angular.y + difference.angular.z*difference.angular.z;
01623
01624
01625 if(scalar_dd <= tiny_bubble_distance_)
01626 {
01627
01628 ROS_DEBUG("Calculating tangential forces for redundant bubbles. Bubble should have been removed. Local Planner probably ill configured");
01629 }
01630
01631
01632 forces.wrench.force.x = forces.wrench.force.x - scalar_fd/scalar_dd * difference.linear.x;
01633 forces.wrench.force.y = forces.wrench.force.y - scalar_fd/scalar_dd * difference.linear.y;
01634 forces.wrench.force.z = forces.wrench.force.z - scalar_fd/scalar_dd * difference.linear.z;
01635 forces.wrench.torque.x = forces.wrench.torque.x - scalar_fd/scalar_dd * difference.angular.x;
01636 forces.wrench.torque.y = forces.wrench.torque.y - scalar_fd/scalar_dd * difference.angular.y;
01637 forces.wrench.torque.z = forces.wrench.torque.z - scalar_fd/scalar_dd * difference.angular.z;
01638
01639 #ifdef DEBUG_EBAND_
01640 ROS_DEBUG("Supressing tangential forces: (x, y, theta) = (%f, %f, %f)",
01641 forces.wrench.force.x, forces.wrench.force.y, forces.wrench.torque.z);
01642 #endif
01643
01644 return true;
01645 }
01646
01647
01648
01649
01650 bool EBandPlanner::interpolateBubbles(geometry_msgs::PoseStamped start_center, geometry_msgs::PoseStamped end_center, geometry_msgs::PoseStamped& interpolated_center)
01651 {
01652
01653 if(!initialized_)
01654 {
01655 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01656 return false;
01657 }
01658
01659
01660 geometry_msgs::Pose2D start_pose2D, end_pose2D, interpolated_pose2D;
01661 double delta_theta;
01662
01663
01664 interpolated_center.header = start_center.header;
01665
01666
01667
01668
01669
01670
01671 PoseToPose2D(start_center.pose, start_pose2D);
01672 PoseToPose2D(end_center.pose, end_pose2D);
01673
01674 delta_theta = end_pose2D.theta - start_pose2D.theta;
01675 delta_theta = angles::normalize_angle(delta_theta) / 2.0;
01676 interpolated_pose2D.theta = start_pose2D.theta + delta_theta;
01677 interpolated_pose2D.theta = angles::normalize_angle(interpolated_pose2D.theta);
01678
01679 interpolated_pose2D.x = 0.0;
01680 interpolated_pose2D.y = 0.0;
01681 Pose2DToPose(interpolated_center.pose, interpolated_pose2D);
01682
01683
01684 interpolated_center.pose.position.x = (end_center.pose.position.x + start_center.pose.position.x)/2.0;
01685 interpolated_center.pose.position.y = (end_center.pose.position.y + start_center.pose.position.y)/2.0;
01686 interpolated_center.pose.position.z = (end_center.pose.position.z + start_center.pose.position.z)/2.0;
01687
01688
01689
01690 return true;
01691 }
01692
01693
01694 bool EBandPlanner::checkOverlap(Bubble bubble1, Bubble bubble2)
01695 {
01696
01697 if(!initialized_)
01698 {
01699 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01700 return false;
01701 }
01702
01703
01704 double distance = 0.0;
01705 if(!calcBubbleDistance(bubble1.center.pose, bubble2.center.pose, distance))
01706 {
01707 ROS_ERROR("failed to calculate Distance between two bubbles. Aborting check for overlap!");
01708 return false;
01709 }
01710
01711
01712 if(distance >= min_bubble_overlap_ * (bubble1.expansion + bubble2.expansion))
01713 return false;
01714
01715
01716
01717
01718 return true;
01719 }
01720
01721
01722 bool EBandPlanner::calcBubbleDistance(geometry_msgs::Pose start_center_pose, geometry_msgs::Pose end_center_pose, double& distance)
01723 {
01724
01725 if(!initialized_)
01726 {
01727 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01728 return false;
01729 }
01730
01731 geometry_msgs::Pose2D start_pose2D, end_pose2D, diff_pose2D;
01732
01733
01734
01735
01736 PoseToPose2D(start_center_pose, start_pose2D);
01737 PoseToPose2D(end_center_pose, end_pose2D);
01738
01739
01740 diff_pose2D.theta = end_pose2D.theta - start_pose2D.theta;
01741 diff_pose2D.theta = angles::normalize_angle(diff_pose2D.theta);
01742
01743 diff_pose2D.x = end_pose2D.x - start_pose2D.x;
01744 diff_pose2D.y = end_pose2D.y - start_pose2D.y;
01745
01746
01747 double angle_to_pseudo_vel = diff_pose2D.theta * costmap_ros_->getCircumscribedRadius();
01748 distance = sqrt( (diff_pose2D.x * diff_pose2D.x) + (diff_pose2D.y * diff_pose2D.y) + (angle_to_pseudo_vel * angle_to_pseudo_vel) );
01749
01750
01751
01752 return true;
01753 }
01754
01755
01756 bool EBandPlanner::calcBubbleDifference(geometry_msgs::Pose start_center_pose, geometry_msgs::Pose end_center_pose, geometry_msgs::Twist& difference)
01757 {
01758
01759 if(!initialized_)
01760 {
01761 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01762 return false;
01763 }
01764
01765 geometry_msgs::Pose2D start_pose2D, end_pose2D, diff_pose2D;
01766
01767
01768
01769
01770 PoseToPose2D(start_center_pose, start_pose2D);
01771 PoseToPose2D(end_center_pose, end_pose2D);
01772
01773
01774 diff_pose2D.theta = end_pose2D.theta - start_pose2D.theta;
01775 diff_pose2D.theta = angles::normalize_angle(diff_pose2D.theta);
01776
01777 diff_pose2D.x = end_pose2D.x - start_pose2D.x;
01778 diff_pose2D.y = end_pose2D.y - start_pose2D.y;
01779
01780 difference.linear.x = diff_pose2D.x;
01781 difference.linear.y = diff_pose2D.y;
01782 difference.linear.z = 0.0;
01783
01784 difference.angular.x = 0.0;
01785 difference.angular.y = 0.0;
01786 difference.angular.z = diff_pose2D.theta*costmap_ros_->getCircumscribedRadius();
01787
01788
01789
01790 return true;
01791 }
01792
01793
01794 bool EBandPlanner::calcObstacleKinematicDistance(geometry_msgs::Pose center_pose, double& distance)
01795 {
01796
01797
01798
01799 if(!initialized_)
01800 {
01801 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01802 return false;
01803 }
01804
01805 unsigned int cell_x, cell_y;
01806 unsigned char disc_cost;
01807 double cont_cost;
01808
01809
01810
01811
01812 if(!costmap_.worldToMap(center_pose.position.x, center_pose.position.y, cell_x, cell_y))
01813 {
01814
01815 distance = 0.001;
01816 return true;
01817 }
01818
01819
01820 disc_cost = costmap_.getCost(cell_x, cell_y);
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839 if(disc_cost >= 253)
01840 {
01841 distance = 0.0;
01842 return true;
01843 }
01844 else
01845 {
01846 if(disc_cost <= 1)
01847 {
01848
01849
01850 cont_cost = 1.0 / 253.0;
01851 }
01852 else
01853 {
01854 cont_cost = ((double) disc_cost)/253.0;
01855 }
01856
01857 distance = -(log(cont_cost)/10.0);
01858
01859 }
01860
01861 return true;
01862 }
01863
01864
01865
01866
01867 bool EBandPlanner::convertPlanToBand(std::vector<geometry_msgs::PoseStamped> plan, std::vector<Bubble>& band)
01868 {
01869
01870 if(!initialized_)
01871 {
01872 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01873 return false;
01874 }
01875
01876
01877 double distance = 0.0;
01878 std::vector<Bubble> tmp_band;
01879
01880 ROS_DEBUG("Copying plan to band - Conversion started: %d frames to convert.", ((int) plan.size()) );
01881
01882
01883 tmp_band = band;
01884
01885
01886 tmp_band.resize(plan.size());
01887 for(int i = 0; i < ((int) plan.size()); i++)
01888 {
01889 #ifdef DEBUG_EBAND_
01890 ROS_DEBUG("Checking Frame %d of %d", i, ((int) plan.size()) );
01891 #endif
01892
01893
01894 tmp_band[i].center = plan[i];
01895
01896
01897 if(!calcObstacleKinematicDistance(tmp_band[i].center.pose, distance))
01898 {
01899
01900 ROS_INFO("Calculation of Distance between bubble and nearest obstacle failed. Frame %d of %d outside map", i, ((int) plan.size()) );
01901 return false;
01902 }
01903
01904 if(distance <= 0.0)
01905 {
01906
01907 ROS_INFO("Calculation of Distance between bubble and nearest obstacle failed. Frame %d of %d in collision. Plan invalid", i, ((int) plan.size()) );
01908
01909 return false;
01910 }
01911
01912
01913
01914 tmp_band[i].expansion = distance;
01915 }
01916
01917
01918 band = tmp_band;
01919
01920 ROS_DEBUG("Successfully converted plan to band");
01921 return true;
01922 }
01923
01924
01925 bool EBandPlanner::convertBandToPlan(std::vector<geometry_msgs::PoseStamped>& plan, std::vector<Bubble> band)
01926 {
01927
01928 if(!initialized_)
01929 {
01930 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
01931 return false;
01932 }
01933
01934
01935 std::vector<geometry_msgs::PoseStamped> tmp_plan;
01936
01937
01938 tmp_plan.resize(band.size());
01939 for(int i = 0; i < ((int) band.size()); i++)
01940 {
01941
01942 tmp_plan[i] = band[i].center;
01943 }
01944
01945
01946 plan = tmp_plan;
01947
01948 return true;
01949 }
01950
01951
01952 }