sbpl_cart_planner.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2008, Willow Garage, Inc.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the Willow Garage nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Mike Phillips, Sachin Chitta
00036 *********************************************************************/
00037 
00038 #include <sbpl_cart_planner/sbpl_cart_planner.h>
00039 #include <cart_pushing_msgs/RobotCartPath.h>
00040 #include <pluginlib/class_list_macros.h>
00041 #include <nav_msgs/Path.h>
00042 #include <sbpl_cart_planner/SBPLCartPlannerStats.h>
00043 
00044 using namespace std;
00045 using namespace ros;
00046 
00047 // TODO - uncomment code that forces environment to be empty!!!!
00048 
00049 PLUGINLIB_REGISTER_CLASS(SBPLCartPlanner, SBPLCartPlanner, nav_core::BaseGlobalPlanner);
00050 
00051 class LatticeSCQ : public StateChangeQuery{
00052   public:
00053     LatticeSCQ(EnvironmentNAVXYTHETACARTLAT* env, std::vector<nav2dcell_t> const & changedcellsV)
00054       : env_(env), changedcellsV_(changedcellsV) {
00055     }
00056 
00057     // lazy init, because we do not always end up calling this method
00058     virtual std::vector<int> const * getPredecessors() const{
00059       if(predsOfChangedCells_.empty() && !changedcellsV_.empty())
00060         env_->GetPredsofChangedEdges(&changedcellsV_, &predsOfChangedCells_);
00061       return &predsOfChangedCells_;
00062     }
00063 
00064     // lazy init, because we do not always end up calling this method
00065     virtual std::vector<int> const * getSuccessors() const{
00066       if(succsOfChangedCells_.empty() && !changedcellsV_.empty())
00067         env_->GetSuccsofChangedEdges(&changedcellsV_, &succsOfChangedCells_);
00068       return &succsOfChangedCells_;
00069     }
00070 
00071     EnvironmentNAVXYTHETACARTLAT * env_;
00072     std::vector<nav2dcell_t> const & changedcellsV_;
00073     mutable std::vector<int> predsOfChangedCells_;
00074     mutable std::vector<int> succsOfChangedCells_;
00075 };
00076 
00077 double SBPLCartPlanner::sign(double x)
00078 {
00079   return x < 0.0 ? -1.0 : 1.0;
00080 }
00081 
00082 SBPLCartPlanner::SBPLCartPlanner()
00083   : initialized_(false), costmap_ros_(NULL){
00084 }
00085 
00086 SBPLCartPlanner::SBPLCartPlanner(std::string name, costmap_2d::Costmap2DROS* costmap_ros) 
00087   : initialized_(false), costmap_ros_(NULL){
00088   initialize(name, costmap_ros);
00089   if(!initialized_)
00090     ROS_ERROR("Could not initialize global planner");
00091 }
00092 
00093     
00094 void SBPLCartPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros){
00095   if(!initialized_){
00096     num_sbpl_markers_ = 0;
00097     ros::NodeHandle private_nh("~/"+name);
00098     ros::NodeHandle nh(name);
00099     
00100     ROS_INFO("Name is %s", name.c_str());
00101 
00102     private_nh.param("planner_type", planner_type_, string("ARAPlanner"));
00103     private_nh.param("allocated_time", allocated_time_, 10.0);
00104     private_nh.param("initial_epsilon",initial_epsilon_,3.0);
00105     private_nh.param("environment_type", environment_type_, string("XYThetaLattice"));
00106     private_nh.param("forward_search", forward_search_, bool(false));
00107     private_nh.param("primitive_filename",primitive_filename_,string(""));
00108     private_nh.param("force_scratch_limit",force_scratch_limit_,500);
00109 
00110     double nominalvel_mpersecs, timetoturn45degsinplace_secs;
00111     private_nh.param("nominalvel_mpersecs", nominalvel_mpersecs, 0.4);
00112     private_nh.param("timetoturn45degsinplace_secs", timetoturn45degsinplace_secs, 0.6);
00113 
00114     private_nh.param<int>("visualizer_skip_poses",visualizer_skip_poses_,5);
00115 
00116     int lethal_obstacle;
00117     private_nh.param("lethal_obstacle",lethal_obstacle,20);
00118     lethal_obstacle_ = (unsigned char) lethal_obstacle;
00119     inscribed_inflated_obstacle_ = lethal_obstacle_-1;
00120     sbpl_cost_multiplier_ = (unsigned char) (costmap_2d::INSCRIBED_INFLATED_OBSTACLE/inscribed_inflated_obstacle_ + 1); 
00121 
00122     ROS_DEBUG("SBPL: lethal: %uz, inscribed inflated: %uz, multiplier: %uz",lethal_obstacle,inscribed_inflated_obstacle_,sbpl_cost_multiplier_);
00123     costmap_ros_ = costmap_ros;
00124     costmap_ros_->clearRobotFootprint();
00125 
00126 
00127     costmap_ros_->getCostmapCopy(cost_map_);
00128 
00129     std::vector<geometry_msgs::Point> footprint = costmap_ros_->getRobotFootprint();
00130     robot_footprint_ = footprint;
00131     if ("XYThetaLattice" == environment_type_){
00132       ROS_INFO("Using a 3D costmap for theta lattice\n");
00133       env_ = new EnvironmentNAVXYTHETACARTLAT();
00134     }
00135     else
00136     {
00137       ROS_FATAL("XYThetaLattice is currently the only supported environment!\n");
00138       return;
00139     }
00140 
00141     if(!env_->SetEnvParameter("cost_inscribed_thresh",inscribed_inflated_obstacle_))
00142     {
00143       ROS_FATAL("Failed to set cost_inscribed_thresh parameter");
00144       return;
00145     }
00146     //    env_->SetEnvParameter("cost_possibly_circumscribed_thresh", cost_map_.getCircumscribedCost());
00147     int obst_cost_thresh = costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE);
00148     vector<sbpl_2Dpt_t> perimeterptsV, cart_perimeterptsV;
00149     private_nh.param("cart_pivot_offset/x", cart_offset_.x, 0.35);
00150     private_nh.param("cart_pivot_offset/y", cart_offset_.y, 0.0);
00151     ROS_INFO("Cart pivot point offset (in base_footprint): %f %f",cart_offset_.x,cart_offset_.y);
00152 
00153     ros::NodeHandle cart_pushing_nh("cart_pushing");
00154     double cart_length, cart_width;
00155     double fp_x_offset, fp_y_offset;
00156     cart_pushing_nh.param("length", cart_length, 0.0);
00157     cart_pushing_nh.param("width", cart_width, 0.0);
00158     cart_pushing_nh.param("footprint_x_offset", fp_x_offset, 0.0);
00159     cart_pushing_nh.param("footprint_y_offset", fp_y_offset, 0.0);
00160 
00161     ROS_DEBUG("Length: %f %f, Footprint offset: %f %f",cart_length,cart_width,fp_x_offset,fp_y_offset);
00162     XmlRpc::XmlRpcValue init_position;
00163     geometry_msgs::Pose cart_init_pose;
00164     cart_pushing_nh.getParam("cart_init_pose/position", init_position);
00165     if(!(init_position.getType() == XmlRpc::XmlRpcValue::TypeArray && init_position.size() == 3)){
00166       ROS_FATAL("The init pose must be specified as a 3-Vector");
00167       return;
00168     }
00169     for(int i = 0; i < init_position.size(); ++i)
00170       if(!init_position[i].getType() == XmlRpc::XmlRpcValue::TypeDouble)//make sure that the value we're looking at a double
00171         ROS_FATAL("Values in the footprint specification must be numbers");
00172     cart_init_pose.position.x = (double) init_position[0];
00173     cart_init_pose.position.y = (double) init_position[1];
00174     cart_init_pose.position.z = (double) init_position[2];
00175 
00176     ROS_DEBUG("Init pose: %f %f %f",cart_init_pose.position.x,cart_init_pose.position.y,cart_init_pose.position.z);
00177 
00178     cart_cp_offset_.x = cart_init_pose.position.x - cart_offset_.x;
00179     cart_cp_offset_.y = cart_init_pose.position.y - cart_offset_.y;
00180     ROS_INFO("Cart control point offset (from pivot point): %f %f",cart_cp_offset_.x,cart_cp_offset_.y);
00181 
00182     
00183     double padding;
00184     std::string padding_param;
00185     if(!private_nh.searchParam("footprint_padding", padding_param))
00186       padding = 0.01;
00187     else
00188       private_nh.param(padding_param, padding, 0.01);
00189     
00190 
00191     std::vector<geometry_msgs::Point> cart_footprint;
00192     cart_footprint.resize(4);
00193     cart_footprint[0].x = -cart_length/2.0-padding;
00194     cart_footprint[0].y = -cart_width/2.0-padding;
00195     cart_footprint[0].z = 0.0;
00196 
00197     cart_footprint[1].x = -cart_length/2.0-padding;
00198     cart_footprint[1].y = cart_width/2.0+padding;
00199     cart_footprint[1].z = 0.0;
00200 
00201     cart_footprint[2].x = cart_length/2.0+padding;
00202     cart_footprint[2].y = cart_width/2.0+padding;
00203     cart_footprint[2].z = 0.0;
00204 
00205     cart_footprint[3].x = cart_length/2.0+padding;
00206     cart_footprint[3].y = -cart_width/2.0-padding;
00207     cart_footprint[3].z = 0.0;
00208 
00209     for(unsigned int i=0; i < cart_footprint.size(); i++)
00210       cart_footprint[i].x += (cart_init_pose.position.x + cart_length/2.0 - fp_x_offset -cart_offset_.x);
00211 
00212 
00213     //    std::vector<geometry_msgs::Point> cart_footprint = loadRobotFootprint(private_nh);
00214     cart_footprint_ = cart_footprint;
00215     cart_perimeterptsV.reserve(cart_footprint.size());
00216     ROS_INFO("Cart footprint");
00217     for (size_t ii(0); ii < cart_footprint.size(); ++ii) {
00218       sbpl_2Dpt_t pt;
00219       pt.x = cart_footprint[ii].x;
00220       pt.y = cart_footprint[ii].y;
00221       cart_perimeterptsV.push_back(pt);
00222       ROS_INFO("%d: %f %f",(int)ii,pt.x,pt.y);
00223     }
00224     perimeterptsV.reserve(footprint.size());
00225     for (size_t ii(0); ii < footprint.size(); ++ii) {
00226       sbpl_2Dpt_t pt;
00227       pt.x = footprint[ii].x;
00228       pt.y = footprint[ii].y;
00229       perimeterptsV.push_back(pt);
00230     }
00231 
00232     bool ret;
00233     try{
00234      ret = env_->InitializeEnv(costmap_ros_->getSizeInCellsX(), // width
00235                           costmap_ros_->getSizeInCellsY(), // height
00236                           0, // mapdata
00237                           0, 0, 0, 0, // start (x, y, theta, t)
00238                           0, 0, 0, 0, // goal (x, y, theta)
00239                           0, 0, 0, 0,//goal tolerance
00240                           perimeterptsV,
00241                           cart_offset_,
00242                           cart_perimeterptsV,
00243                           costmap_ros_->getResolution(), nominalvel_mpersecs,
00244                           timetoturn45degsinplace_secs, obst_cost_thresh,
00245                           primitive_filename_.c_str());
00246     }
00247     catch(SBPL_Exception e){
00248       ROS_ERROR("SBPL encountered a fatal exception");
00249       ret = false;
00250     }
00251     if(!ret){
00252       ROS_FATAL("SBPL initialization failed!");
00253     }
00254 
00255     for (ssize_t ix(0); ix < costmap_ros_->getSizeInCellsX(); ++ix)
00256       for (ssize_t iy(0); iy < costmap_ros_->getSizeInCellsY(); ++iy)
00257         env_->UpdateCost(ix, iy, costMapCostToSBPLCost(cost_map_.getCost(ix,iy)));
00258     
00259     if ("ARAPlanner" == planner_type_){
00260       planner_ = new ARAPlanner(env_, forward_search_);
00261     }
00262     else if ("ADPlanner" == planner_type_){
00263       planner_ = new ADPlanner(env_, forward_search_);
00264     }
00265     else{
00266       initialized_ = false;
00267       ROS_FATAL("ARAPlanner and ADPlanner are currently the only supported planners!\n");
00268       return;
00269     }
00270 
00271     ROS_INFO("[sbpl_cart_planner] Initialized successfully");
00272     plan_pub_ = private_nh.advertise<nav_msgs::Path>("plan", 1);
00273     sbpl_plan_pub_ = private_nh.advertise<visualization_msgs::MarkerArray>("sbpl_plan_array", 1);
00274     sbpl_plan_footprint_pub_ = private_nh.advertise<visualization_msgs::MarkerArray>("sbpl_plan_footprint_array", 1);
00275     sbpl_robot_cart_plan_pub_ = private_nh.advertise<cart_pushing_msgs::RobotCartPath>("sbpl_robot_cart_plan", 1);
00276     stats_publisher_ = private_nh.advertise<sbpl_cart_planner::SBPLCartPlannerStats>("sbpl_cart_planner_stats", 1);
00277     
00278     if(!env_->initialized_)
00279       initialized_ = false;
00280     else
00281       initialized_ = true;
00282   }
00283 
00284 }
00285 
00286 unsigned char SBPLCartPlanner::costMapCostToSBPLCost(unsigned char newcost)
00287 {
00288   if(newcost == costmap_2d::LETHAL_OBSTACLE)
00289     return lethal_obstacle_;
00290   else if(newcost == costmap_2d::INSCRIBED_INFLATED_OBSTACLE)
00291     return inscribed_inflated_obstacle_;
00292   else if(newcost == 0 || newcost == costmap_2d::NO_INFORMATION)
00293     return 0;
00294   else
00295     return (unsigned char) (newcost/sbpl_cost_multiplier_ + 0.5);
00296 
00297 }
00298 
00299 std::vector<geometry_msgs::Point> SBPLCartPlanner::loadRobotFootprint(ros::NodeHandle node)
00300 {
00301   std::vector<geometry_msgs::Point> footprint;
00302   geometry_msgs::Point pt;
00303   double padding;
00304   
00305   std::string padding_param, footprint_param;
00306   if(!node.searchParam("footprint_padding", padding_param))
00307     padding = 0.01;
00308   else
00309     node.param(padding_param, padding, 0.01);
00310   
00311   //grab the footprint from the parameter server if possible
00312   XmlRpc::XmlRpcValue footprint_list;
00313   if(node.searchParam("cart_footprint", footprint_param)){
00314     ROS_INFO("Footprint param: %s", footprint_param.c_str());
00315     node.getParam(footprint_param, footprint_list);
00316     //make sure we have a list of lists
00317     if(!(footprint_list.getType() == XmlRpc::XmlRpcValue::TypeArray && footprint_list.size() > 2)){
00318       ROS_FATAL("The footprint must be specified as list of lists on the parameter server with at least 3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
00319       throw std::runtime_error("The footprint must be specified as list of lists on the parameter server with at least 3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
00320     }
00321     for(int i = 0; i < footprint_list.size(); ++i){
00322       //make sure we have a list of lists of size 2
00323       XmlRpc::XmlRpcValue point = footprint_list[i];
00324       if(!(point.getType() == XmlRpc::XmlRpcValue::TypeArray && point.size() == 2)){
00325         ROS_FATAL("The footprint must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
00326         throw std::runtime_error("The footprint must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form");
00327       }
00328       
00329       //make sure that the value we're looking at is either a double or an int
00330       if(!(point[0].getType() == XmlRpc::XmlRpcValue::TypeInt || point[0].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
00331         ROS_FATAL("Values in the footprint specification must be numbers");
00332         throw std::runtime_error("Values in the footprint specification must be numbers");
00333       }
00334       pt.x = point[0].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(point[0]) : (double)(point[0]);
00335       pt.x += sign(pt.x) * padding;
00336       
00337       //make sure that the value we're looking at is either a double or an int
00338       if(!(point[1].getType() == XmlRpc::XmlRpcValue::TypeInt || point[1].getType() == XmlRpc::XmlRpcValue::TypeDouble)){
00339         ROS_FATAL("Values in the footprint specification must be numbers");
00340         throw std::runtime_error("Values in the footprint specification must be numbers");
00341       }
00342       pt.y = point[1].getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(point[1]) : (double)(point[1]);
00343       pt.y += sign(pt.y) * padding;
00344       
00345       footprint.push_back(pt);
00346       
00347     }
00348   }
00349     return footprint;
00350 }
00351 
00352   
00353 bool SBPLCartPlanner::makePlan(const geometry_msgs::PoseStamped& start,
00354                                const geometry_msgs::PoseStamped& goal,
00355                                std::vector<geometry_msgs::PoseStamped>& plan){
00356   if(!initialized_)
00357   {
00358     ROS_ERROR("Global planner is not initialized");
00359     return false;
00360   }
00361 
00362   plan.clear();
00363 
00364   ROS_INFO("[sbpl_lattice_planner] getting fresh copy of costmap");
00365   costmap_ros_->clearRobotFootprint();
00366   ROS_INFO("[sbpl_lattice_planner] robot footprint cleared");
00367   geometry_msgs::Pose cart_pose = getGlobalCartPose(start.pose,0.0);
00368   costmap_ros_->getCostmapCopy(cost_map_);
00369   clearFootprint(cart_pose,cart_footprint_);
00370 
00371   ROS_INFO("[sbpl_lattice_planner] getting start point (%g,%g) goal point (%g,%g)",
00372            start.pose.position.x, start.pose.position.y,goal.pose.position.x, goal.pose.position.y);
00373   double theta_start = 2 * atan2(start.pose.orientation.z, start.pose.orientation.w);
00374   double theta_goal = 2 * atan2(goal.pose.orientation.z, goal.pose.orientation.w);
00375   double cart_start = 0.0;
00376   double cart_goal = 0.0;
00377 
00378   try
00379   {
00380     int ret = env_->SetStart(start.pose.position.x - cost_map_.getOriginX(), start.pose.position.y - cost_map_.getOriginY(), theta_start, cart_start);
00381     if(ret < 0 || planner_->set_start(ret) == 0){
00382       ROS_ERROR("Failed to set start state");
00383       return false;
00384     }    
00385   }
00386   catch(SBPL_Exception e){
00387     ROS_ERROR("SBPL encountered a fatal exception while setting the start state");
00388     return false;
00389   }
00390 
00391   try{
00392     int ret = env_->SetGoal(goal.pose.position.x - cost_map_.getOriginX(), goal.pose.position.y - cost_map_.getOriginY(), theta_goal, cart_goal);
00393     if(ret < 0 || planner_->set_goal(ret) == 0){
00394       ROS_ERROR("Failed to set goal state");
00395       return false;
00396     }
00397   }
00398   catch(SBPL_Exception e){
00399     ROS_ERROR("SBPL encountered a fatal exception while setting the goal state");
00400     return false;
00401   }
00402 
00403   
00404   int offOnCount = 0;
00405   int onOffCount = 0;
00406   int allCount = 0;
00407   vector<nav2dcell_t> changedcellsV;
00408 
00409   for(unsigned int ix = 0; ix < cost_map_.getSizeInCellsX(); ix++) {
00410     for(unsigned int iy = 0; iy < cost_map_.getSizeInCellsY(); iy++) {
00411 
00412       unsigned char oldCost = env_->GetMapCost(ix,iy);
00413       unsigned char newCost = cost_map_.getCost(ix,iy);
00414 
00415       if(oldCost == newCost) continue;
00416 
00417       allCount++;
00418 
00419       //first case - off cell goes on
00420 
00421       if((oldCost != costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) && oldCost != costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE)) &&
00422          (newCost == costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) || newCost == costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE))) {
00423         offOnCount++;
00424       }
00425       
00426       if((oldCost == costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) || oldCost == costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE)) &&
00427          (newCost != costMapCostToSBPLCost(costmap_2d::LETHAL_OBSTACLE) && newCost != costMapCostToSBPLCost(costmap_2d::INSCRIBED_INFLATED_OBSTACLE))) {
00428         onOffCount++;
00429       }      
00430       env_->UpdateCost(ix, iy, costMapCostToSBPLCost(cost_map_.getCost(ix,iy)));
00431 
00432       nav2dcell_t nav2dcell;
00433       nav2dcell.x = ix;
00434       nav2dcell.y = iy;
00435       changedcellsV.push_back(nav2dcell);
00436     }
00437   }
00438 
00439   try{   
00440     if(!changedcellsV.empty()){
00441       StateChangeQuery* scq = new LatticeSCQ(env_, changedcellsV);
00442       planner_->costs_changed(*scq);
00443       delete scq;
00444     }    
00445     if(allCount > force_scratch_limit_)
00446       planner_->force_planning_from_scratch();
00447   }
00448   catch(SBPL_Exception e){
00449     ROS_ERROR("SBPL failed to update the costmap");
00450     return false;
00451   }
00452 
00453   //setting planner parameters
00454   ROS_INFO("allocated:%f, init eps:%f\n",allocated_time_,initial_epsilon_);
00455   planner_->set_initialsolution_eps(initial_epsilon_);
00456   planner_->set_search_mode(false);
00457 
00458   ROS_INFO("[sbpl_lattice_planner] run planner");
00459   vector<int> solution_stateIDs;
00460   int solution_cost;
00461   try{
00462     int ret = planner_->replan(allocated_time_, &solution_stateIDs, &solution_cost);
00463     if(ret)
00464       ROS_DEBUG("Solution is found\n");
00465     else
00466     {
00467       ROS_INFO("Solution does not exist\n");    
00468       ARAPlanner *ara_planner = dynamic_cast<ARAPlanner*>(planner_);
00469       // Fill up statistics and publish
00470       sbpl_cart_planner::SBPLCartPlannerStats stats;
00471       stats.initial_epsilon = initial_epsilon_;
00472       stats.plan_to_first_solution = false;
00473       stats.allocated_time = allocated_time_;
00474       if(ara_planner)
00475       {
00476         stats.actual_time = ara_planner->get_final_eps_planning_time();    
00477         stats.actual_time = ara_planner->get_initial_eps_planning_time();
00478         stats.number_of_expands_initial_solution = ara_planner->get_n_expands_init_solution();
00479         stats.final_epsilon = ara_planner->get_final_epsilon();
00480       }
00481       stats.solution_cost = solution_cost;
00482       stats.path_size = 0;
00483       stats.start = start;
00484       stats.goal = goal;
00485       stats.start_cart_angle = cart_start;
00486       stats.goal_cart_angle = cart_goal;
00487       stats_publisher_.publish(stats);
00488       stats.final_number_of_expands = planner_->get_n_expands();
00489       return false;
00490     }
00491   }
00492   catch(SBPL_Exception e){
00493     ROS_ERROR("SBPL encountered a fatal exception while planning");
00494     return false;
00495   }
00496 
00497   ROS_DEBUG("size of solution=%d", (int)solution_stateIDs.size());
00498 
00499   vector<EnvNAVXYTHETACARTLAT3Dpt_t> sbpl_path;
00500   try
00501   {
00502     env_->ConvertStateIDPathintoXYThetaPath(&solution_stateIDs, &sbpl_path);
00503   }
00504   catch(SBPL_Exception e)
00505   {
00506     ROS_ERROR("SBPL encountered a fatal exception while reconstructing the path");
00507     return false;
00508   }
00509 
00510   ROS_INFO("Plan has %d points.\n", (int)sbpl_path.size());
00511   ros::Time plan_time = ros::Time::now();
00512 
00513   //
00514   visualization_msgs::MarkerArray sbpl_plan_marker_array;
00515   convertPathToMarkerArray(sbpl_path,costmap_ros_->getGlobalFrameID(),sbpl_plan_marker_array);
00516   sbpl_plan_pub_.publish(sbpl_plan_marker_array);
00517 
00518   visualization_msgs::MarkerArray sbpl_plan_footprint;
00519   getFootprintList(sbpl_path,costmap_ros_->getGlobalFrameID(),sbpl_plan_footprint);
00520   sbpl_plan_footprint_pub_.publish(sbpl_plan_footprint);
00521 
00522   //create a message for the plan 
00523   nav_msgs::Path gui_path;
00524   gui_path.poses.resize(sbpl_path.size());
00525   gui_path.header.frame_id = costmap_ros_->getGlobalFrameID();
00526   gui_path.header.stamp = plan_time;
00527 
00528   cart_pushing_msgs::RobotCartPath sbpl_robot_cart_plan;
00529   sbpl_robot_cart_plan.header.frame_id = costmap_ros_->getGlobalFrameID();
00530   sbpl_robot_cart_plan.header.stamp = plan_time;
00531 
00532 
00533   for(unsigned int i=0; i<sbpl_path.size(); i++){
00534     geometry_msgs::PoseStamped pose;
00535     pose.header.stamp = plan_time;
00536     pose.header.frame_id = costmap_ros_->getGlobalFrameID();
00537 
00538     pose.pose.position.x = sbpl_path[i].x + cost_map_.getOriginX();
00539     pose.pose.position.y = sbpl_path[i].y + cost_map_.getOriginY();
00540     pose.pose.position.z = start.pose.position.z;
00541 
00542     btQuaternion temp;
00543     temp.setEulerZYX(sbpl_path[i].theta,0,0);
00544     pose.pose.orientation.x = temp.getX();
00545     pose.pose.orientation.y = temp.getY();
00546     pose.pose.orientation.z = temp.getZ();
00547     pose.pose.orientation.w = temp.getW();
00548 
00549     plan.push_back(pose);
00550 
00551     cart_pushing_msgs::RobotCartConfiguration robot_cart_configuration;
00552     robot_cart_configuration.robot_pose = pose.pose;
00553     robot_cart_configuration.cart_pose = getLocalCartControlFramePose(sbpl_path[i]);
00554     ROS_DEBUG("Cartangle: %d %f",i,sbpl_path[i].cartangle);
00555     sbpl_robot_cart_plan.path.push_back(robot_cart_configuration);
00556 
00557     gui_path.poses[i].pose.position.x = plan[i].pose.position.x;
00558     gui_path.poses[i].pose.position.y = plan[i].pose.position.y;
00559     gui_path.poses[i].pose.position.z = plan[i].pose.position.z;
00560   }
00561   plan_pub_.publish(gui_path);
00562   sbpl_robot_cart_plan_pub_.publish(sbpl_robot_cart_plan);
00563 
00564   ARAPlanner *ara_planner = dynamic_cast<ARAPlanner*>(planner_);
00565 
00566   // Fill up statistics and publish
00567   sbpl_cart_planner::SBPLCartPlannerStats stats;
00568   stats.initial_epsilon = initial_epsilon_;
00569   stats.plan_to_first_solution = false;
00570   stats.final_number_of_expands = planner_->get_n_expands();
00571   stats.allocated_time = allocated_time_;
00572   if(ara_planner)
00573   {
00574     stats.time_to_first_solution = ara_planner->get_initial_eps_planning_time();
00575     stats.actual_time = ara_planner->get_final_eps_planning_time();    
00576     stats.number_of_expands_initial_solution = ara_planner->get_n_expands_init_solution();
00577     stats.final_epsilon = ara_planner->get_final_epsilon();
00578   }
00579   stats.solution_cost = solution_cost;
00580   stats.path_size = sbpl_path.size();
00581   stats.start = start;
00582   stats.goal = goal;
00583   stats.start_cart_angle = cart_start;
00584   stats.goal_cart_angle = cart_goal;
00585   stats.solution = sbpl_robot_cart_plan;
00586   stats_publisher_.publish(stats);
00587 
00588   return true;
00589 }
00590 
00591 void SBPLCartPlanner::convertPathToMarkerArray(const std::vector<EnvNAVXYTHETACARTLAT3Dpt_t> &sbpl_path,
00592                                                const std::string &path_frame_id,
00593                                                visualization_msgs::MarkerArray &ma)
00594 {
00595   unsigned int num_markers = sbpl_path.size();
00596   ma.markers.resize(2*num_markers);
00597 
00598   for(unsigned int i=0; i< num_markers; i++)
00599   {
00600     ma.markers[2*i].header.frame_id = path_frame_id;
00601     ma.markers[2*i].header.stamp = ros::Time();
00602     ma.markers[2*i].ns = "sbpl_cart_plan";
00603     ma.markers[2*i].id = 2*i;
00604     ma.markers[2*i].type = visualization_msgs::Marker::ARROW;
00605     ma.markers[2*i].action = visualization_msgs::Marker::ADD;
00606     ma.markers[2*i].pose.position.x = sbpl_path[i].x;
00607     ma.markers[2*i].pose.position.y = sbpl_path[i].y;
00608     ma.markers[2*i].pose.position.z = 0.0;
00609     btQuaternion quat;
00610     quat.setRPY(0.0,0.0,sbpl_path[i].theta);
00611     tf::quaternionTFToMsg(quat,ma.markers[2*i].pose.orientation);
00612     ma.markers[2*i].scale.x = 0.1;
00613     ma.markers[2*i].scale.y = 0.05;
00614     ma.markers[2*i].scale.z = 0.05;
00615     ma.markers[2*i].color.a = 1.0;
00616     ma.markers[2*i].color.r = 0.0;
00617     ma.markers[2*i].color.g = 1.0;
00618     ma.markers[2*i].color.b = 0.0;
00619 
00620     geometry_msgs::Pose cart_pose;
00621     cart_pose.position.x = sbpl_path[i].x + cos(sbpl_path[i].theta)*cart_offset_.x - sin(sbpl_path[i].theta)*cart_offset_.y;
00622     cart_pose.position.y = sbpl_path[i].y + sin(sbpl_path[i].theta)*cart_offset_.x + cos(sbpl_path[i].theta)*cart_offset_.y;
00623     cart_pose.position.z = 0.0;
00624     double yaw = sbpl_path[i].theta + sbpl_path[i].cartangle;
00625     quat.setRPY(0.0,0.0,yaw);
00626     tf::quaternionTFToMsg(quat,cart_pose.orientation);
00627 
00628     ma.markers[2*i+1].header.frame_id = path_frame_id;
00629     ma.markers[2*i+1].header.stamp = ros::Time();
00630     ma.markers[2*i+1].ns = "sbpl_cart_plan";
00631     ma.markers[2*i+1].id = 2*i+1;
00632     ma.markers[2*i+1].type = visualization_msgs::Marker::ARROW;
00633     ma.markers[2*i+1].action = visualization_msgs::Marker::ADD;
00634     ma.markers[2*i+1].pose = cart_pose;
00635     ma.markers[2*i+1].scale.x = 0.1;
00636     ma.markers[2*i+1].scale.y = 0.05;
00637     ma.markers[2*i+1].scale.z = 0.05;
00638     ma.markers[2*i+1].color.a = 1.0;
00639     ma.markers[2*i+1].color.r = 1.0;
00640     ma.markers[2*i+1].color.g = 0.0;
00641     ma.markers[2*i+1].color.b = 0.0;
00642   }
00643   if(num_markers < num_sbpl_markers_)
00644   {
00645     for(unsigned int i = 0; i < (num_sbpl_markers_ - num_markers); i++)
00646     {     
00647       visualization_msgs::Marker new_marker;
00648       new_marker.header.frame_id = path_frame_id;
00649       new_marker.header.stamp = ros::Time();
00650       new_marker.ns = "sbpl_cart_plan";
00651       new_marker.id = 2*(num_markers+i);
00652       new_marker.type = visualization_msgs::Marker::ARROW;
00653       new_marker.action = visualization_msgs::Marker::DELETE;
00654 
00655       ma.markers.push_back(new_marker);
00656 
00657       new_marker.id = 2*(num_markers+i)+1;
00658 
00659       ma.markers.push_back(new_marker);
00660 
00661     }
00662   }
00663   num_sbpl_markers_ = num_markers;
00664 }
00665 
00666 
00667 
00668 geometry_msgs::Pose SBPLCartPlanner::getGlobalCartPose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00669 {
00670   geometry_msgs::Pose cart_pose;
00671   btQuaternion quat;
00672   cart_pose.position.x = sbpl_pose.x + cos(sbpl_pose.theta)*cart_offset_.x - sin(sbpl_pose.theta)*cart_offset_.y;
00673   cart_pose.position.y = sbpl_pose.y + sin(sbpl_pose.theta)*cart_offset_.x + cos(sbpl_pose.theta)*cart_offset_.y;
00674   cart_pose.position.z = 0.0;
00675   double yaw = sbpl_pose.theta + sbpl_pose.cartangle;
00676   quat.setRPY(0.0,0.0,yaw);
00677   tf::quaternionTFToMsg(quat,cart_pose.orientation);
00678   return cart_pose;
00679 }
00680 
00681 
00682 geometry_msgs::Pose SBPLCartPlanner::getLocalCartControlFramePose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00683 {
00684   geometry_msgs::Pose cart_pose;
00685   btQuaternion quat;
00686   cart_pose.position.x = cart_offset_.x + cos(sbpl_pose.cartangle)*cart_cp_offset_.x - sin(sbpl_pose.cartangle)*cart_cp_offset_.y;
00687   cart_pose.position.y = cart_offset_.y + sin(sbpl_pose.cartangle)*cart_cp_offset_.x + cos(sbpl_pose.cartangle)*cart_cp_offset_.y;
00688   cart_pose.position.z = 0.0;
00689   double yaw = sbpl_pose.cartangle;
00690   quat.setRPY(0.0,0.0,yaw);
00691   tf::quaternionTFToMsg(quat,cart_pose.orientation);
00692   return cart_pose;
00693 }
00694 
00695 geometry_msgs::Pose SBPLCartPlanner::getLocalCartPose(const EnvNAVXYTHETACARTLAT3Dpt_t& sbpl_pose)
00696 {
00697   geometry_msgs::Pose cart_pose;
00698   btQuaternion quat;
00699   cart_pose.position.x = cart_offset_.x;
00700   cart_pose.position.y = cart_offset_.y;
00701   cart_pose.position.z = 0.0;
00702   double yaw = sbpl_pose.cartangle;
00703   quat.setRPY(0.0,0.0,yaw);
00704   tf::quaternionTFToMsg(quat,cart_pose.orientation);
00705   return cart_pose;
00706 }
00707 
00708 void SBPLCartPlanner::getFootprintList(const std::vector<EnvNAVXYTHETACARTLAT3Dpt_t> &sbpl_path,
00709                                        const std::string &path_frame_id,
00710                                        visualization_msgs::MarkerArray & ma)
00711 { 
00712   ma.markers.resize(2); 
00713   ma.markers[0].header.frame_id = path_frame_id;
00714   ma.markers[0].header.stamp = ros::Time();
00715   ma.markers[0].ns = "sbpl_cart_footprint";
00716   ma.markers[0].id = 0;
00717   ma.markers[0].type = visualization_msgs::Marker::LINE_LIST;
00718   ma.markers[0].action = visualization_msgs::Marker::ADD;
00719 
00720   ma.markers[0].scale.x = 0.05;
00721   ma.markers[0].color.a = 1.0;
00722   ma.markers[0].color.r = 0.0;
00723   ma.markers[0].color.g = 0.0;
00724   ma.markers[0].color.b = 1.0;
00725 
00726   ma.markers[1].header.frame_id = path_frame_id;
00727   ma.markers[1].header.stamp = ros::Time();
00728   ma.markers[1].ns = "sbpl_cart_footprint";
00729   ma.markers[1].id = 1;
00730   ma.markers[1].type = visualization_msgs::Marker::LINE_LIST;
00731   ma.markers[1].action = visualization_msgs::Marker::ADD;
00732 
00733   ma.markers[1].scale.x = 0.05;
00734   ma.markers[1].color.a = 1.0;
00735   ma.markers[1].color.r = 0.0;
00736   ma.markers[1].color.g = 1.0;
00737   ma.markers[1].color.b = 0.0;
00738 
00739 
00740   for(unsigned int i=0; i <  sbpl_path.size(); i= i+visualizer_skip_poses_)
00741   {
00742     std::vector<geometry_msgs::Point> transformed_cfp, transformed_rfp;
00743     geometry_msgs::Pose robot_pose;
00744     robot_pose.position.x = sbpl_path[i].x;
00745     robot_pose.position.y = sbpl_path[i].y;
00746     robot_pose.position.z = 0.0;
00747     btQuaternion quat;
00748     quat.setRPY(0.0,0.0,sbpl_path[i].theta);
00749     tf::quaternionTFToMsg(quat,robot_pose.orientation);
00750 
00751     geometry_msgs::Pose cart_pose;
00752     cart_pose.position.x = sbpl_path[i].x + cos(sbpl_path[i].theta)*cart_offset_.x - sin(sbpl_path[i].theta)*cart_offset_.y;
00753     cart_pose.position.y = sbpl_path[i].y + sin(sbpl_path[i].theta)*cart_offset_.x + cos(sbpl_path[i].theta)*cart_offset_.y;
00754     cart_pose.position.z = 0.0;
00755     double yaw = sbpl_path[i].theta + sbpl_path[i].cartangle;
00756     quat.setRPY(0.0,0.0,yaw);
00757     tf::quaternionTFToMsg(quat,cart_pose.orientation);
00758 
00759     transformFootprintToEdges(robot_pose,robot_footprint_,transformed_rfp);
00760     transformFootprintToEdges(cart_pose,cart_footprint_,transformed_cfp);
00761 
00762     for(unsigned int i=0; i < transformed_rfp.size(); i++)
00763       ma.markers[0].points.push_back(transformed_rfp[i]);
00764 
00765     for(unsigned int i=0; i < transformed_cfp.size(); i++)
00766       ma.markers[1].points.push_back(transformed_cfp[i]);
00767   }
00768 
00769   return; 
00770 }
00771 
00772 void SBPLCartPlanner::transformFootprintToEdges(const geometry_msgs::Pose &robot_pose,
00773                                          const std::vector<geometry_msgs::Point> &footprint,
00774                                          std::vector<geometry_msgs::Point> &out_footprint)
00775 {
00776   out_footprint.resize(2*footprint.size());
00777   double yaw = tf::getYaw(robot_pose.orientation);
00778   for(unsigned int i=0; i < footprint.size(); i++)
00779   {
00780     out_footprint[2*i].x = robot_pose.position.x + cos(yaw)*footprint[i].x - sin(yaw)*footprint[i].y;
00781     out_footprint[2*i].y = robot_pose.position.y + sin(yaw)*footprint[i].x + cos(yaw)*footprint[i].y;
00782     if(i == 0)
00783     {
00784       out_footprint.back().x = out_footprint[i].x;
00785       out_footprint.back().y = out_footprint[i].y;
00786     }
00787     else
00788     {
00789       out_footprint[2*i-1].x = out_footprint[2*i].x;
00790       out_footprint[2*i-1].y = out_footprint[2*i].y;
00791     }
00792   }
00793   return;
00794 }
00795 
00796 bool SBPLCartPlanner::clearFootprint(const geometry_msgs::Pose &robot_pose, 
00797                                      const std::vector<geometry_msgs::Point> &footprint)
00798 {  
00799   vector<geometry_msgs::Point> oriented_footprint;
00800   getOrientedFootprint(robot_pose, footprint, oriented_footprint);
00801   
00802   //we also want to clear the robot footprint from the costmap we're using
00803   if(!cost_map_.setConvexPolygonCost(oriented_footprint, costmap_2d::FREE_SPACE)) 
00804   {
00805       ROS_ERROR("Could not clear robot footprint: ");
00806       for (uint i = 0; i < oriented_footprint.size(); ++i)
00807         ROS_ERROR("oriented_footprint: %.2lf %.2lf %.2lf", oriented_footprint[i].x, oriented_footprint[i].y, oriented_footprint[i].z);
00808       return false;     
00809   }
00810   return true;
00811 }
00812 
00813 void SBPLCartPlanner::getOrientedFootprint(const geometry_msgs::Pose &robot_pose,
00814                                            const std::vector<geometry_msgs::Point> &footprint,
00815                                            std::vector<geometry_msgs::Point> &oriented_footprint)
00816 {
00817   oriented_footprint.resize(footprint.size());
00818   double yaw = tf::getYaw(robot_pose.orientation);
00819   for(unsigned int i=0; i < footprint.size(); i++)
00820   {
00821     oriented_footprint[i].x = robot_pose.position.x + cos(yaw)*footprint[i].x - sin(yaw)*footprint[i].y;
00822     oriented_footprint[i].y = robot_pose.position.y + sin(yaw)*footprint[i].x + cos(yaw)*footprint[i].y;
00823   }
00824   return;
00825 }
00826 
00827 geometry_msgs::Pose SBPLCartPlanner::getGlobalCartPose(const geometry_msgs::Pose &robot_pose, const double &cart_angle)
00828 {
00829   EnvNAVXYTHETACARTLAT3Dpt_t sbpl_pose;
00830   sbpl_pose.x = robot_pose.position.x;
00831   sbpl_pose.y = robot_pose.position.y;
00832   sbpl_pose.theta = tf::getYaw(robot_pose.orientation);
00833   sbpl_pose.cartangle = cart_angle;
00834   return getGlobalCartPose(sbpl_pose);
00835 }


sbpl_cart_planner
Author(s): Sachin Chitta
autogenerated on Tue Jan 7 2014 11:12:32