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_ros.h>
00039 
00040 
00041 #include <pluginlib/class_list_macros.h>
00042 
00043 
00044 #include <nav_core/base_local_planner.h>
00045 
00046 
00047 
00048 
00049 PLUGINLIB_DECLARE_CLASS(eband_local_planner, EBandPlannerROS, eband_local_planner::EBandPlannerROS, nav_core::BaseLocalPlanner)
00050 
00051 
00052 namespace eband_local_planner{
00053 
00054 EBandPlannerROS::EBandPlannerROS() : costmap_ros_(NULL), tf_(NULL), initialized_(false) {}
00055 
00056 
00057 EBandPlannerROS::EBandPlannerROS(std::string name, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros)
00058  : costmap_ros_(NULL), tf_(NULL), initialized_(false)
00059 {
00060         
00061         initialize(name, tf, costmap_ros);
00062 }
00063 
00064 
00065 EBandPlannerROS::~EBandPlannerROS() {}
00066 
00067 
00068 void EBandPlannerROS::initialize(std::string name, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros)
00069 {
00070         
00071         if(!initialized_)
00072         {
00073                 
00074                 costmap_ros_ = costmap_ros;
00075                 tf_ = tf;
00076 
00077 
00078                 
00079                 ros::NodeHandle pn("~/" + name);
00080 
00081                 
00082                 
00083                 pn.param("yaw_goal_tolerance", yaw_goal_tolerance_, 0.05);
00084                 pn.param("xy_goal_tolerance", xy_goal_tolerance_, 0.1);
00085 
00086                 
00087                 pn.param("rot_stopped_vel", rot_stopped_vel_, 1e-2);
00088                 pn.param("trans_stopped_vel", trans_stopped_vel_, 1e-2);
00089 
00090                 
00091                 g_plan_pub_ = pn.advertise<nav_msgs::Path>("global_plan", 1);
00092                 l_plan_pub_ = pn.advertise<nav_msgs::Path>("local_plan", 1);
00093 
00094 
00095                 
00096                 ros::NodeHandle gn;
00097                 odom_sub_ = gn.subscribe<nav_msgs::Odometry>("odom", 1, boost::bind(&EBandPlannerROS::odomCallback, this, _1));
00098 
00099 
00100                 
00101                 
00102                 eband_ = boost::shared_ptr<EBandPlanner>(new EBandPlanner(name, costmap_ros_));
00103 
00104                 
00105                 eband_trj_ctrl_ = boost::shared_ptr<EBandTrajectoryCtrl>(new EBandTrajectoryCtrl(name, costmap_ros_));
00106 
00107                 
00108                 eband_visual_ = boost::shared_ptr<EBandVisualization>(new EBandVisualization);
00109 
00110                 
00111                 eband_->setVisualization(eband_visual_);
00112 
00113                 
00114                 eband_trj_ctrl_->setVisualization(eband_visual_);
00115 
00116                 
00117                 eband_visual_->initialize(pn, costmap_ros);
00118 
00119 
00120                 
00121                 initialized_ = true;
00122 
00123 
00124                 
00125                 ROS_DEBUG("Elastic Band plugin initialized.");
00126         }
00127         else
00128         {
00129                 ROS_WARN("This planner has already been initialized, doing nothing.");
00130         }
00131 }
00132 
00133 
00134 
00135 bool EBandPlannerROS::setPlan(const std::vector<geometry_msgs::PoseStamped>& orig_global_plan)
00136 {
00137     
00138         
00139         if(!initialized_)
00140         {
00141                 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00142                 return false;
00143         }
00144 
00145     
00146     global_plan_.clear();
00147     global_plan_ = orig_global_plan;
00148         
00149         
00150         
00151         std::vector<int> start_end_counts (2, (int) global_plan_.size()); 
00152         if(!eband_local_planner::transformGlobalPlan(*tf_, global_plan_, *costmap_ros_, costmap_ros_->getGlobalFrameID(), transformed_plan_, start_end_counts))
00153         {
00154                 
00155                 ROS_WARN("Could not transform the global plan to the frame of the controller");
00156                 return false;
00157         }
00158 
00159     
00160         if(transformed_plan_.empty())
00161         {
00162                 
00163                 ROS_WARN("Transformed plan is empty. Aborting local planner!");
00164                 return false;
00165         }
00166 
00167 
00168         
00169         if(!eband_->setPlan(transformed_plan_))
00170         {
00171                 ROS_ERROR("Setting plan to Elastic Band method failed!");
00172                 return false;
00173         }
00174         ROS_INFO("Global plan set to elastic band for optimization");
00175 
00176         
00177         plan_start_end_counter_ = start_end_counts;
00178 
00179         
00180         eband_->optimizeBand();
00181 
00182 
00183         
00184         std::vector<eband_local_planner::Bubble> current_band;
00185         if(eband_->getBand(current_band))
00186                 eband_visual_->publishBand("bubbles", current_band);
00187 
00188 
00189     return true;
00190 }
00191 
00192 
00193 bool EBandPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel)
00194 {       
00195         
00196         if(!initialized_)
00197         {
00198                 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00199                 return false;
00200         }
00201 
00202         
00203         
00204         tf::Stamped<tf::Pose> global_pose;
00205         geometry_msgs::PoseStamped global_pose_msg;
00206         std::vector<geometry_msgs::PoseStamped> tmp_plan;
00207 
00208         
00209         ROS_DEBUG("Reading current robot Position from costmap and appending it to elastic band.");
00210         if(!costmap_ros_->getRobotPose(global_pose))
00211         {
00212                 ROS_WARN("Could not retrieve up to date robot pose from costmap for local planning.");
00213                 return false;
00214         }
00215 
00216         
00217         tf::poseStampedTFToMsg(global_pose, global_pose_msg);
00218         tmp_plan.assign(1, global_pose_msg);
00219         eband_local_planner::AddAtPosition add_frames_at = add_front;
00220 
00221         
00222         if(!eband_->addFrames(tmp_plan, add_frames_at))
00223         {
00224                 ROS_WARN("Could not connect robot pose to existing elastic band.");
00225                 return false;
00226         }
00227 
00228 
00229         
00230         ROS_DEBUG("Checking for new path frames in moving window");
00231         std::vector<int> plan_start_end_counter = plan_start_end_counter_;
00232         std::vector<geometry_msgs::PoseStamped> append_transformed_plan;
00233         
00234         if(!eband_local_planner::transformGlobalPlan(*tf_, global_plan_, *costmap_ros_, costmap_ros_->getGlobalFrameID(), transformed_plan_, plan_start_end_counter))
00235         {
00236                 
00237                 ROS_WARN("Could not transform the global plan to the frame of the controller");
00238                 return false;
00239         }
00240 
00241     
00242         if(transformed_plan_.empty())
00243         {
00244                 
00245                 ROS_WARN("Transformed plan is empty. Aborting local planner!");
00246                 return false;
00247         }
00248         
00249         ROS_DEBUG("Retrieved start-end-counts are: (%d, %d)", plan_start_end_counter.at(0), plan_start_end_counter.at(1));
00250         ROS_DEBUG("Current start-end-counts are: (%d, %d)", plan_start_end_counter_.at(0), plan_start_end_counter_.at(1));
00251 
00252         
00253         append_transformed_plan.clear();
00254         
00255         if(plan_start_end_counter_.at(1) > plan_start_end_counter.at(1)) 
00256         {
00257                 
00258                 if(plan_start_end_counter_.at(1) > plan_start_end_counter.at(0)) 
00259                 {
00260                         
00261                         append_transformed_plan = transformed_plan_;
00262                 }
00263                 else
00264                 {
00265                         
00266                         int discarded_frames = plan_start_end_counter.at(0) - plan_start_end_counter_.at(1);
00267                         ROS_ASSERT(transformed_plan_.begin() + discarded_frames + 1 >= transformed_plan_.begin());
00268                         ROS_ASSERT(transformed_plan_.begin() + discarded_frames + 1 < transformed_plan_.end());
00269                         append_transformed_plan.assign(transformed_plan_.begin() + discarded_frames + 1, transformed_plan_.end());
00270                 }
00271 
00272                 
00273                 ROS_DEBUG("Adding %d new frames to current band", (int) append_transformed_plan.size());
00274                 add_frames_at = add_back;
00275                 if(eband_->addFrames(append_transformed_plan, add_back))
00276                 {
00277                         
00278                         ROS_DEBUG("Sucessfully added frames to band");
00279                         plan_start_end_counter_ = plan_start_end_counter;
00280                 }
00281                 else
00282                         ROS_DEBUG("Failed to add frames to existing band");
00283         }
00284         else
00285                 ROS_DEBUG("Nothing to add");
00286 
00287 
00288         
00289         ROS_DEBUG("Calling optimization method for elastic band");
00290         std::vector<eband_local_planner::Bubble> current_band;
00291         if(!eband_->optimizeBand())
00292         {
00293                 ROS_DEBUG("Optimization failed - Band invalid - No controls availlable");
00294                 
00295                 if(eband_->getBand(current_band))
00296                         eband_visual_->publishBand("bubbles", current_band);
00297                 return false;
00298         }
00299 
00300 
00301         
00302         eband_->getBand(current_band);
00303         
00304         if(!eband_trj_ctrl_->setBand(current_band))
00305         {
00306                 ROS_DEBUG("Failed to to set current band to Trajectory Controller");
00307                 return false;
00308         }
00309 
00310         
00311         if(!eband_trj_ctrl_->setOdometry(base_odom_))
00312         {
00313                 ROS_DEBUG("Failed to to set current odometry to Trajectory Controller");
00314                 return false;
00315         }
00316 
00317         
00318         geometry_msgs::Twist cmd_twist;
00319         if(!eband_trj_ctrl_->getTwist(cmd_twist))
00320         {
00321                 ROS_DEBUG("Failed to calculate Twist from band in Trajectory Controller");
00322                 return false;
00323         }
00324 
00325 
00326         
00327         ROS_DEBUG("Retrieving velocity command: (%f, %f, %f)", cmd_twist.linear.x, cmd_twist.linear.y, cmd_twist.angular.z);
00328         cmd_vel = cmd_twist;
00329 
00330 
00331         
00332         std::vector<geometry_msgs::PoseStamped> refined_plan;
00333         if(eband_->getPlan(refined_plan))
00334                 
00335                 base_local_planner::publishPlan(refined_plan, g_plan_pub_, 0.0, 1.0, 0.0, 0.0);
00336         
00337 
00338         
00339         if(eband_->getBand(current_band))
00340                 eband_visual_->publishBand("bubbles", current_band);
00341         
00342 
00343         return true;
00344 }
00345 
00346 
00347 bool EBandPlannerROS::isGoalReached()
00348 {
00349         
00350         if(!initialized_)
00351         {
00352                 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00353                 return false;
00354         }
00355 
00356         
00357         nav_msgs::Odometry base_odom;
00358         {
00359                 
00360                 boost::mutex::scoped_lock lock(odom_mutex_);
00361                 base_odom = base_odom_;
00362         }
00363 
00364         
00365         return base_local_planner::isGoalReached(*tf_, global_plan_, *costmap_ros_, costmap_ros_->getGlobalFrameID(), base_odom, 
00366                                 rot_stopped_vel_, trans_stopped_vel_, xy_goal_tolerance_, yaw_goal_tolerance_);
00367 }
00368 
00369 
00370 void EBandPlannerROS::odomCallback(const nav_msgs::Odometry::ConstPtr& msg)
00371 {
00372         
00373     boost::mutex::scoped_lock lock(odom_mutex_);
00374 
00375         
00376         base_odom_.twist.twist.linear.x = msg->twist.twist.linear.x;
00377         base_odom_.twist.twist.linear.y = msg->twist.twist.linear.y;
00378         base_odom_.twist.twist.angular.z = msg->twist.twist.angular.z;
00379 }
00380 
00381 
00382 }
00383 
00384