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