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