Go to the documentation of this file.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 #include <carrot_planner/carrot_planner.h>
00038 #include <pluginlib/class_list_macros.h>
00039
00040
00041 PLUGINLIB_EXPORT_CLASS( carrot_planner::CarrotPlanner, nav_core::BaseGlobalPlanner)
00042
00043 namespace carrot_planner {
00044
00045 CarrotPlanner::CarrotPlanner()
00046 : costmap_ros_(NULL), initialized_(false){}
00047
00048 CarrotPlanner::CarrotPlanner(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00049 : costmap_ros_(NULL), initialized_(false){
00050 initialize(name, costmap_ros);
00051 }
00052
00053 void CarrotPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros){
00054 if(!initialized_){
00055 costmap_ros_ = costmap_ros;
00056 ros::NodeHandle private_nh("~/" + name);
00057 private_nh.param("step_size", step_size_, costmap_ros_->getResolution());
00058 private_nh.param("min_dist_from_robot", min_dist_from_robot_, 0.10);
00059 costmap_ros_->getCostmapCopy(costmap_);
00060 world_model_ = new base_local_planner::CostmapModel(costmap_);
00061
00062 inscribed_radius_ = costmap_ros_->getInscribedRadius();
00063 circumscribed_radius_ = costmap_ros_->getCircumscribedRadius();
00064 footprint_spec_ = costmap_ros_->getRobotFootprint();
00065
00066 initialized_ = true;
00067 }
00068 else
00069 ROS_WARN("This planner has already been initialized... doing nothing");
00070 }
00071
00072
00073
00074
00075
00076
00077 double CarrotPlanner::footprintCost(double x_i, double y_i, double theta_i){
00078 if(!initialized_){
00079 ROS_ERROR("The planner has not been initialized, please call initialize() to use the planner");
00080 return -1.0;
00081 }
00082
00083 if(footprint_spec_.size() < 3)
00084 return -1.0;
00085
00086
00087 double cos_th = cos(theta_i);
00088 double sin_th = sin(theta_i);
00089 std::vector<geometry_msgs::Point> oriented_footprint;
00090 for(unsigned int i = 0; i < footprint_spec_.size(); ++i){
00091 geometry_msgs::Point new_pt;
00092 new_pt.x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
00093 new_pt.y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
00094 oriented_footprint.push_back(new_pt);
00095 }
00096
00097 geometry_msgs::Point robot_position;
00098 robot_position.x = x_i;
00099 robot_position.y = y_i;
00100
00101
00102 double footprint_cost = world_model_->footprintCost(robot_position, oriented_footprint, inscribed_radius_, circumscribed_radius_);
00103 return footprint_cost;
00104 }
00105
00106
00107 bool CarrotPlanner::makePlan(const geometry_msgs::PoseStamped& start,
00108 const geometry_msgs::PoseStamped& goal, std::vector<geometry_msgs::PoseStamped>& plan){
00109
00110 if(!initialized_){
00111 ROS_ERROR("The planner has not been initialized, please call initialize() to use the planner");
00112 return false;
00113 }
00114
00115 ROS_DEBUG("Got a start: %.2f, %.2f, and a goal: %.2f, %.2f", start.pose.position.x, start.pose.position.y, goal.pose.position.x, goal.pose.position.y);
00116
00117 plan.clear();
00118 costmap_ros_->getCostmapCopy(costmap_);
00119
00120 if(goal.header.frame_id != costmap_ros_->getGlobalFrameID()){
00121 ROS_ERROR("This planner as configured will only accept goals in the %s frame, but a goal was sent in the %s frame.",
00122 costmap_ros_->getGlobalFrameID().c_str(), goal.header.frame_id.c_str());
00123 return false;
00124 }
00125
00126 tf::Stamped<tf::Pose> goal_tf;
00127 tf::Stamped<tf::Pose> start_tf;
00128
00129 poseStampedMsgToTF(goal,goal_tf);
00130 poseStampedMsgToTF(start,start_tf);
00131
00132 double useless_pitch, useless_roll, goal_yaw, start_yaw;
00133 start_tf.getBasis().getEulerYPR(start_yaw, useless_pitch, useless_roll);
00134 goal_tf.getBasis().getEulerYPR(goal_yaw, useless_pitch, useless_roll);
00135
00136
00137 double goal_x = goal.pose.position.x;
00138 double goal_y = goal.pose.position.y;
00139 double start_x = start.pose.position.x;
00140 double start_y = start.pose.position.y;
00141
00142 double diff_x = goal_x - start_x;
00143 double diff_y = goal_y - start_y;
00144 double diff_yaw = angles::normalize_angle(goal_yaw-start_yaw);
00145
00146 double target_x = goal_x;
00147 double target_y = goal_y;
00148 double target_yaw = goal_yaw;
00149
00150 bool done = false;
00151 double scale = 1.0;
00152 double dScale = 0.01;
00153
00154 while(!done)
00155 {
00156 if(scale < 0)
00157 {
00158 target_x = start_x;
00159 target_y = start_y;
00160 target_yaw = start_yaw;
00161 ROS_WARN("The carrot planner could not find a valid plan for this goal");
00162 break;
00163 }
00164 target_x = start_x + scale * diff_x;
00165 target_y = start_y + scale * diff_y;
00166 target_yaw = angles::normalize_angle(start_yaw + scale * diff_yaw);
00167
00168 double footprint_cost = footprintCost(target_x, target_y, target_yaw);
00169 if(footprint_cost >= 0)
00170 {
00171 done = true;
00172 }
00173 scale -=dScale;
00174 }
00175
00176 plan.push_back(start);
00177 geometry_msgs::PoseStamped new_goal = goal;
00178 tf::Quaternion goal_quat = tf::createQuaternionFromYaw(target_yaw);
00179
00180 new_goal.pose.position.x = target_x;
00181 new_goal.pose.position.y = target_y;
00182
00183 new_goal.pose.orientation.x = goal_quat.x();
00184 new_goal.pose.orientation.y = goal_quat.y();
00185 new_goal.pose.orientation.z = goal_quat.z();
00186 new_goal.pose.orientation.w = goal_quat.w();
00187
00188 plan.push_back(new_goal);
00189 return (done);
00190 }
00191
00192 };