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 <trajectory_planner.h>
00038 
00039 using namespace std;
00040 using namespace costmap_2d;
00041 
00042 namespace iri_ackermann_local_planner{
00043   void TrajectoryPlanner::reconfigure(AckermannLocalPlannerConfig &cfg) 
00044   {
00045     iri_ackermann_local_planner::AckermannLocalPlannerConfig config(cfg);
00046     boost::mutex::scoped_lock l(configuration_mutex_);
00047 
00048     sim_time_ = config.sim_time;
00049     sim_granularity_ = config.sim_granularity;
00050 
00051     pdist_scale_ = config.pdist_scale;
00052     gdist_scale_ = config.gdist_scale;
00053     hdiff_scale_ = config.hdiff_scale;
00054     occdist_scale_ = config.occdist_scale;
00055 
00056     vx_samples_ = config.vx_samples;
00057     vtheta_samples_ = config.vtheta_samples;
00058 
00059     if (vx_samples_ <= 0) 
00060     {
00061       config.vx_samples = 1;
00062       vx_samples_ = config.vx_samples;
00063       ROS_WARN("You've specified that you don't want any samples in the x dimension. We'll at least assume that you want to sample one value... so we're going to set vx_samples to 1 instead");
00064     }
00065     if(vtheta_samples_ <= 0) 
00066     {
00067       config.vtheta_samples = 1;
00068       vtheta_samples_ = config.vtheta_samples;
00069       ROS_WARN("You've specified that you don't want any samples in the theta dimension. We'll at least assume that you want to sample one value... so we're going to set vtheta_samples to 1 instead");
00070     }
00071 
00072     simple_attractor_ = config.simple_attractor;
00073 
00074     angular_sim_granularity_ = config.angular_sim_granularity;
00075 
00076     
00077     this->ack_vel_max_=config.ack_vel_max;
00078     this->ack_vel_min_=config.ack_vel_max;
00079     this->ack_acc_max_=config.ack_acc_max;
00080     this->ack_steer_angle_max_=config.ack_steer_angle_max;
00081     this->ack_steer_angle_min_=config.ack_steer_angle_min;
00082     this->ack_steer_speed_max_=config.ack_steer_speed_max;
00083     this->ack_steer_speed_min_=config.ack_steer_speed_min;
00084     this->ack_steer_acc_max_=config.ack_steer_acc_max;
00085     this->ack_axis_distance_=config.ack_axis_distance;
00086     this->heading_points_=config.heading_points;
00087   }
00088 
00089   TrajectoryPlanner::TrajectoryPlanner(WorldModel &world_model,
00090     const costmap_2d::Costmap2D& costmap,
00091     std::vector<geometry_msgs::Point> footprint_spec,
00092     double max_acc, double max_vel, double min_vel,
00093     double max_steer_acc, double max_steer_vel, double min_steer_vel,
00094     double max_steer_angle, double min_steer_angle,double axis_distance,
00095     double sim_time, double sim_granularity,
00096     int vx_samples, int vtheta_samples,
00097     double pdist_scale, double gdist_scale, double occdist_scale, double hdiff_scale,
00098     bool simple_attractor, double angular_sim_granularity,int heading_points,double xy_goal_tol)
00099     : map_(costmap.getSizeInCellsX(), costmap.getSizeInCellsY()), costmap_(costmap), 
00100     world_model_(world_model), footprint_spec_(footprint_spec),
00101     sim_time_(sim_time), sim_granularity_(sim_granularity), angular_sim_granularity_(angular_sim_granularity),
00102     vx_samples_(vx_samples), vtheta_samples_(vtheta_samples),
00103     pdist_scale_(pdist_scale), gdist_scale_(gdist_scale), occdist_scale_(occdist_scale),hdiff_scale_(hdiff_scale),
00104     ack_acc_max_(max_acc), ack_vel_min_(min_vel), ack_vel_max_(max_vel),
00105     ack_steer_acc_max_(max_steer_acc),ack_steer_speed_max_(max_steer_vel),ack_steer_speed_min_(min_steer_vel),
00106     ack_steer_angle_max_(max_steer_angle),ack_steer_angle_min_(min_steer_angle),ack_axis_distance_(axis_distance),
00107     simple_attractor_(simple_attractor),heading_points_(heading_points),xy_goal_tol_(xy_goal_tol)
00108   {
00109   }
00110 
00111   TrajectoryPlanner::~TrajectoryPlanner(){}
00112 
00113   bool TrajectoryPlanner::getCellCosts(int cx, int cy, float &path_cost, float &goal_cost, float &occ_cost, float &total_cost) {
00114     MapCell cell = map_(cx, cy);
00115     if (cell.within_robot) {
00116         return false;
00117     }
00118     occ_cost = costmap_.getCost(cx, cy);
00119     if (cell.path_dist >= map_.map_.size() || cell.goal_dist >= map_.map_.size() || occ_cost >= costmap_2d::INSCRIBED_INFLATED_OBSTACLE) {
00120         return false;
00121     }
00122     path_cost = cell.path_dist;
00123     goal_cost = cell.goal_dist;
00124     total_cost = pdist_scale_ * path_cost + gdist_scale_ * goal_cost + occdist_scale_ * occ_cost;
00125     return true;
00126   }
00127 
00128   
00129   void TrajectoryPlanner::generateTrajectory(double x, double y, double theta, double vx, double vy, 
00130       double vtheta, double vx_samp, double vy_samp, double vtheta_samp, 
00131       double acc_x, double acc_y, double acc_theta, double impossible_cost,
00132       Trajectory& traj){
00133 
00134     
00135     boost::mutex::scoped_lock l(configuration_mutex_);
00136 
00137     
00138     double x_i = x;
00139     double y_i = y;
00140     double theta_i = theta;
00141 
00142     
00143     double vt_i;
00144     double steer_angle_i,steer_speed_i;
00145     double vx_int,vy_int;
00146     double r,d;
00147 
00148     
00149     vt_i=vx;
00150     steer_angle_i=vy;
00151     steer_speed_i=vtheta;
00152 
00153     vx_int = vx_samp;
00154     vy_int = 0;
00155 
00156     
00157     int num_steps;
00158     num_steps = int(sim_time_ / sim_granularity_ + 0.5);
00159 
00160     
00161     if(num_steps == 0)
00162       num_steps = 1;
00163 
00164     double dt = sim_time_ / num_steps;
00165     double time = 0.0;
00166 
00167     
00168     traj.resetPoints();
00169     traj.xv_ = vx_int; 
00170     traj.yv_ = vy_int; 
00171     traj.thetav_ = vtheta_samp;
00172     traj.cost_ = -1.0;
00173 
00174     
00175     double path_dist = 0.0;
00176     double goal_dist = 0.0;
00177     double occ_cost = 0.0;
00178     double heading_diff = 0.0;
00179 
00180     double speed=0.0,angle=0.0;
00181     double T1=0.0,T4=0.0,T2=0.0,T3=0.0;
00182 
00183     
00184     if(vtheta<0 && (-vtheta*vtheta/(2*this->ack_steer_acc_max_)+vy)>this->ack_steer_angle_max_)
00185       return;
00186 
00187     if(vtheta>0 && (vtheta*vtheta/(2*this->ack_steer_acc_max_)+vy)>this->ack_steer_angle_max_)
00188       return;
00189 
00190     if(vtheta<0 && (-vtheta*vtheta/(2*this->ack_steer_acc_max_)+vy)<this->ack_steer_angle_min_)
00191       return;
00192 
00193     if(vtheta>0 && (vtheta*vtheta/(2*this->ack_steer_acc_max_)+vy)<this->ack_steer_angle_min_)
00194       return;
00195 
00196     
00197     if(steer_speed_i>=0)
00198     {
00199       if(vtheta_samp>steer_angle_i)
00200       { 
00201         speed=(steer_speed_i+this->ack_steer_acc_max_*sim_time_)/2.0;
00202         if(speed>=this->ack_steer_speed_max_)
00203         {
00204           speed=this->ack_steer_speed_max_;  
00205           T4=sim_time_-(2.0*speed-steer_speed_i)/this->ack_steer_acc_max_;
00206           angle=speed*speed/this->ack_steer_acc_max_-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+speed*sim_time_*T4+steer_angle_i;
00207           if(angle>vtheta_samp)
00208           {
00209             angle=vtheta_samp;
00210             T4=(vtheta_samp-steer_angle_i-speed*speed/this->ack_steer_acc_max_+steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_))/speed;
00211             if(T4<0)
00212             {
00213               T4=0;
00214               speed=sqrt(steer_speed_i*steer_speed_i/2.0+this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00215             }
00216           }
00217         }
00218         else
00219         { 
00220           angle=speed*speed/this->ack_steer_acc_max_-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+steer_angle_i;
00221           T4=0;
00222           if(angle>vtheta_samp)
00223           {
00224             angle=vtheta_samp;
00225             speed=sqrt(steer_speed_i*steer_speed_i/2.0+this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00226           }
00227         }
00228         T1=(speed-steer_speed_i)/this->ack_steer_acc_max_;
00229         if(T1<0)
00230           return;
00231       }
00232       else
00233       {
00234         speed=(steer_speed_i-this->ack_steer_acc_max_*sim_time_)/2.0;
00235         if(speed<=this->ack_steer_speed_min_)
00236         {
00237           speed=this->ack_steer_speed_min_;
00238           T4=sim_time_+(2.0*speed-steer_speed_i)/this->ack_steer_acc_max_;
00239           angle=steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)-speed*speed/this->ack_steer_acc_max_+speed*T4+steer_angle_i;
00240           if(angle<vtheta_samp)
00241           {
00242             angle=vtheta_samp;
00243             T4=(vtheta_samp-steer_angle_i+speed*speed/this->ack_steer_acc_max_-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_))/speed;
00244             if(T4<0)
00245             {
00246               T4=0;
00247               speed=-sqrt(steer_speed_i*steer_speed_i/2.0-this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00248             }
00249           }
00250         }
00251         else
00252         {
00253           angle=steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)-speed*speed/this->ack_steer_acc_max_+steer_angle_i;
00254           T4=0;
00255           if(angle<vtheta_samp)
00256           {
00257             angle=vtheta_samp;
00258             speed=-sqrt(steer_speed_i*steer_speed_i/2.0-this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i)); 
00259           }
00260         }
00261         T1=-(speed-steer_speed_i)/this->ack_steer_acc_max_;
00262         if(T1<0)
00263           return;
00264       }
00265     }
00266     else
00267     {
00268       if(vtheta_samp>steer_angle_i)
00269       {
00270         speed=(steer_speed_i+this->ack_steer_acc_max_*sim_time_)/2.0;
00271         if(speed>=this->ack_steer_speed_max_)
00272         {
00273           speed=this->ack_steer_speed_max_;
00274           T4=sim_time_-(2.0*speed-steer_speed_i)/this->ack_steer_acc_max_;
00275           angle=-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+speed*speed/this->ack_steer_acc_max_+speed*T4+steer_angle_i;
00276           if(angle>vtheta_samp)
00277           {
00278             angle=vtheta_samp;
00279             T4=(vtheta_samp-steer_angle_i-speed*speed/this->ack_steer_acc_max_+steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_))/speed;
00280             if(T4<0)
00281             {
00282               T4=0;
00283               speed=sqrt(steer_speed_i*steer_speed_i/2.0+this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00284             }
00285           }
00286         }
00287         else
00288         {
00289           angle=-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+speed*speed/this->ack_steer_acc_max_+steer_angle_i;
00290           T4=0;
00291           if(angle>vtheta_samp)
00292           {
00293             angle=vtheta_samp;
00294             speed=sqrt(steer_speed_i*steer_speed_i/2.0+this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00295           }
00296         }
00297         T1=(speed-steer_speed_i)/this->ack_steer_acc_max_;
00298         if(T1<0)
00299           return;
00300       }
00301       else
00302       {
00303         speed=(steer_speed_i-this->ack_steer_acc_max_*sim_time_)/2.0;
00304         if(speed<=this->ack_steer_speed_min_)
00305         {
00306           speed=this->ack_steer_speed_min_;
00307           T4=sim_time_+(2.0*speed-steer_speed_i)/this->ack_steer_acc_max_;
00308           angle=-speed*speed/this->ack_steer_acc_max_+steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+speed*T4+steer_angle_i;
00309           if(angle<vtheta_samp)
00310           {
00311             angle=vtheta_samp;
00312             T4=(vtheta_samp-steer_angle_i+speed*speed/this->ack_steer_acc_max_-steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_))/speed;
00313             if(T4<0)
00314             {
00315               T4=0;
00316               speed=-sqrt(steer_speed_i*steer_speed_i/2.0-this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i));
00317             }
00318           }
00319         }
00320         else
00321         {
00322           angle=-speed*speed/this->ack_steer_acc_max_+steer_speed_i*steer_speed_i/(2.0*this->ack_steer_acc_max_)+steer_angle_i;
00323           T4=0;
00324           if(angle<vtheta_samp)
00325           {
00326             angle=vtheta_samp;
00327             speed=-sqrt(steer_speed_i*steer_speed_i/2.0-this->ack_steer_acc_max_*(vtheta_samp-steer_angle_i)); 
00328           }
00329         }
00330         T1=-(speed-steer_speed_i)/this->ack_steer_acc_max_;
00331         if(T1<0)
00332           return;
00333       }
00334     }
00335 
00336     double v=0.0;
00337     if(vx_samp>vt_i)
00338     {
00339       v=(vt_i+this->ack_acc_max_*sim_time_)/2.0;
00340       if(v>vx_samp)
00341       {
00342         v=vx_samp;
00343         T3=sim_time_-(2.0*v-vt_i)/this->ack_acc_max_;
00344       }
00345       else
00346         T3=0;
00347       T2=(v-vt_i)/this->ack_acc_max_;
00348       if(T2<0)
00349         return;
00350     }
00351     else
00352     {
00353       v=(vt_i-this->ack_acc_max_*sim_time_)/2.0;
00354       if(v<vx_samp)
00355       {
00356         v=vx_samp;
00357         T3=sim_time_+(2.0*v-vt_i)/this->ack_acc_max_;
00358       }
00359       else
00360         T3=0;
00361       T2=-(v-vt_i)/this->ack_acc_max_;
00362       if(T2<0)
00363         return;
00364     }
00365 
00366     double time_window_start=sim_time_/heading_points_;
00367     double time_window_end=sim_time_/heading_points_+dt;
00368 
00369     for(int i = 0; i < num_steps; ++i){
00370       
00371       unsigned int cell_x, cell_y;
00372 
00373       
00374       if(!costmap_.worldToMap(x_i, y_i, cell_x, cell_y)){
00375         traj.cost_ = -1.0;
00376         ROS_DEBUG("TrajectoryPlanner::generateTrajectory: Current point out of map!");
00377         return;
00378       }
00379 
00380       
00381       double footprint_cost = footprintCost(x_i, y_i, theta_i);
00382 
00383       occ_cost = std::max(std::max(occ_cost, footprint_cost), double(costmap_.getCost(cell_x, cell_y)));
00384 
00385       double cell_pdist = map_(cell_x, cell_y).path_dist;
00386       double cell_gdist = map_(cell_x, cell_y).goal_dist;
00387      
00388       double near_dist=DBL_MAX,dist;
00389       unsigned int near_index=0;
00390  
00391       
00392       path_dist = cell_pdist;
00393       goal_dist = cell_gdist;
00394       if(time >= time_window_start && time < time_window_end)
00395       {
00396         
00397         for(unsigned int i = 0;i<global_plan_.size();i++)
00398         {
00399           dist=sqrt((global_plan_[i].pose.position.x-x_i)*(global_plan_[i].pose.position.x-x_i)+(global_plan_[i].pose.position.y-y_i)*(global_plan_[i].pose.position.y-y_i));
00400           if(dist<near_dist)
00401           { 
00402             near_dist=dist;
00403             near_index=i;
00404           }
00405         }
00406         double v1_x,v1_y;
00407         if(near_index==0)
00408         {
00409           v1_x = global_plan_[near_index+1].pose.position.x - global_plan_[near_index].pose.position.x;
00410           v1_y = global_plan_[near_index+1].pose.position.y - global_plan_[near_index].pose.position.y;
00411         }
00412         else
00413         {
00414           v1_x = global_plan_[near_index].pose.position.x - global_plan_[near_index-1].pose.position.x;
00415           v1_y = global_plan_[near_index].pose.position.y - global_plan_[near_index-1].pose.position.y;
00416         }
00417         double v2_x = cos(theta_i);
00418         double v2_y = sin(theta_i);
00419 
00420         double perp_dot = v1_x * v2_y - v1_y * v2_x;
00421         double dot = v1_x * v2_x + v1_y * v2_y;
00422 
00423         
00424         heading_diff += fabs(atan2(perp_dot, dot));
00425 
00426         time_window_start+=sim_time_/heading_points_;
00427         time_window_end=time_window_start+dt;
00428       }
00429 
00430       
00431       if(simple_attractor_){
00432         goal_dist = (x_i - global_plan_[global_plan_.size() -1].pose.position.x) * 
00433           (x_i - global_plan_[global_plan_.size() -1].pose.position.x) + 
00434           (y_i - global_plan_[global_plan_.size() -1].pose.position.y) * 
00435           (y_i - global_plan_[global_plan_.size() -1].pose.position.y);
00436         path_dist = 0.0;
00437       }
00438       else{
00439         
00440         if(impossible_cost <= goal_dist || impossible_cost <= path_dist){
00441           ROS_DEBUG("No path to goal with goal distance = %f, path_distance = %f and max cost = %f", 
00442               cell_gdist, cell_pdist, impossible_cost);
00443           traj.cost_ = -2.0;
00444           return;
00445         }
00446       }
00447 
00448 
00449       
00450       traj.addPoint(x_i, y_i, theta_i);
00451 
00452       
00453       if(vtheta_samp>vtheta)
00454       {
00455         if(time<T1)
00456         {
00457           steer_speed_i=steer_speed_i+this->ack_steer_acc_max_*dt;
00458           if(steer_speed_i>speed)
00459             steer_speed_i=speed;
00460         }
00461         else if(time<T1+T4)
00462           steer_speed_i=speed;
00463         else
00464         { 
00465           steer_speed_i=steer_speed_i-this->ack_steer_acc_max_*dt;
00466           if(steer_speed_i<0)
00467             steer_speed_i=0;
00468         }
00469       }
00470       else
00471       {
00472         if(time<T1)
00473         {
00474           steer_speed_i=steer_speed_i-this->ack_steer_acc_max_*dt;
00475           if(steer_speed_i<speed)
00476             steer_speed_i=speed;
00477         }
00478         else if(time<T1+T4)
00479           steer_speed_i=speed;
00480         else
00481         {
00482           steer_speed_i=steer_speed_i+this->ack_steer_acc_max_*dt;
00483           if(steer_speed_i>0)
00484             steer_speed_i=0;
00485         }
00486       }
00487       steer_angle_i+=steer_speed_i*dt;
00488       if(vx_samp>vx)
00489       {
00490         if(time<T2)
00491         {
00492           vt_i=vt_i+this->ack_acc_max_*dt;
00493           if(vt_i>v)
00494             vt_i=v;
00495         }
00496         else if(time<(T2+T3))
00497           vt_i=v;
00498         else
00499         {
00500           vt_i=vt_i-this->ack_acc_max_*dt;
00501           if(vt_i<0)
00502             vt_i=0;
00503         }
00504       }
00505       else
00506       {
00507         if(time<T2)
00508         {
00509           vt_i=vt_i-this->ack_acc_max_*dt;
00510           if(vt_i<v)
00511             vt_i=v;
00512         }
00513         else if(time<T2+T3)
00514           vt_i=v;
00515         else
00516         {  
00517           vt_i=vt_i+this->ack_acc_max_*dt;
00518           if(vt_i>0)
00519             vt_i=0;
00520         }
00521       }
00522 
00523       if(fabs(steer_angle_i)>0.02)
00524       {
00525         r=ack_axis_distance_*tan(3.14159/2.0-steer_angle_i);
00526         d=vt_i*dt;
00527         x_i+=d*cos(theta_i);
00528         y_i+=d*sin(theta_i);
00529         theta_i+=d/r;
00530       }
00531       else
00532       {
00533         d=vt_i*dt;
00534         x_i+=d*cos(theta_i);
00535         y_i+=d*sin(theta_i);
00536       }
00537 
00538       
00539       time += dt;
00540     }
00541 
00542     
00543     double cost = -1.0;
00544     cost = (pdist_scale_ * path_dist + goal_dist * gdist_scale_ + occdist_scale_ * occ_cost + hdiff_scale_ * heading_diff)*(1.0+0.0*fabs(vy-vtheta_samp));      
00545 
00546     traj.cost_ = cost;
00547   }
00548 
00549   double TrajectoryPlanner::headingDiff(int cell_x, int cell_y, double x, double y, double heading){
00550     double heading_diff = DBL_MAX;
00551     unsigned int goal_cell_x, goal_cell_y;
00552     
00553     for(int i = global_plan_.size() - 1; i >=0; --i){
00554       if(costmap_.worldToMap(global_plan_[i].pose.position.x, global_plan_[i].pose.position.y, goal_cell_x, goal_cell_y)){
00555         if(lineCost(cell_x, goal_cell_x, cell_y, goal_cell_y) >= 0){
00556           double gx, gy;
00557           costmap_.mapToWorld(goal_cell_x, goal_cell_y, gx, gy);
00558           double v1_x = gx - x;
00559           double v1_y = gy - y;
00560           double v2_x = cos(heading);
00561           double v2_y = sin(heading);
00562 
00563           double perp_dot = v1_x * v2_y - v1_y * v2_x;
00564           double dot = v1_x * v2_x + v1_y * v2_y;
00565 
00566           
00567           double vector_angle = atan2(perp_dot, dot);
00568 
00569           heading_diff = fabs(vector_angle);
00570           return heading_diff;
00571 
00572         }
00573       }
00574     }
00575     return heading_diff;
00576   }
00577 
00578   
00579   double TrajectoryPlanner::lineCost(int x0, int x1, 
00580       int y0, int y1){
00581     
00582     int deltax = abs(x1 - x0);        
00583     int deltay = abs(y1 - y0);        
00584     int x = x0;                       
00585     int y = y0;                       
00586 
00587     int xinc1, xinc2, yinc1, yinc2;
00588     int den, num, numadd, numpixels;
00589 
00590     double line_cost = 0.0;
00591     double point_cost = -1.0;
00592 
00593     if (x1 >= x0)                 
00594     {
00595       xinc1 = 1;
00596       xinc2 = 1;
00597     }
00598     else                          
00599     {
00600       xinc1 = -1;
00601       xinc2 = -1;
00602     }
00603 
00604     if (y1 >= y0)                 
00605     {
00606       yinc1 = 1;
00607       yinc2 = 1;
00608     }
00609     else                          
00610     {
00611       yinc1 = -1;
00612       yinc2 = -1;
00613     }
00614 
00615     if (deltax >= deltay)         
00616     {
00617       xinc1 = 0;                  
00618       yinc2 = 0;                  
00619       den = deltax;
00620       num = deltax / 2;
00621       numadd = deltay;
00622       numpixels = deltax;         
00623     }
00624     else                          
00625     {
00626       xinc2 = 0;                  
00627       yinc1 = 0;                  
00628       den = deltay;
00629       num = deltay / 2;
00630       numadd = deltax;
00631       numpixels = deltay;         
00632     }
00633 
00634     for (int curpixel = 0; curpixel <= numpixels; curpixel++)
00635     {
00636       point_cost = pointCost(x, y); 
00637 
00638       if(point_cost < 0)
00639         return -1;
00640 
00641       if(line_cost < point_cost)
00642         line_cost = point_cost;
00643 
00644       num += numadd;              
00645       if (num >= den)             
00646       {
00647         num -= den;               
00648         x += xinc1;               
00649         y += yinc1;               
00650       }
00651       x += xinc2;                 
00652       y += yinc2;                 
00653     }
00654 
00655     return line_cost;
00656   }
00657 
00658   double TrajectoryPlanner::pointCost(int x, int y){
00659     unsigned char cost = costmap_.getCost(x, y);
00660     
00661     if(cost == LETHAL_OBSTACLE || cost == INSCRIBED_INFLATED_OBSTACLE || cost == NO_INFORMATION){
00662       return -1;
00663     }
00664 
00665     return cost;
00666   }
00667 
00668   void TrajectoryPlanner::updatePlan(const vector<geometry_msgs::PoseStamped>& new_plan, bool compute_dists)
00669   {
00670     global_plan_.resize(new_plan.size());
00671     for(unsigned int i = 0; i < new_plan.size(); ++i)
00672     {
00673       global_plan_[i] = new_plan[i];
00674     }
00675     if(compute_dists){
00676       
00677       map_.resetPathDist();
00678       
00679       map_.setPathCells(costmap_, global_plan_);
00680       ROS_DEBUG("Path/Goal distance computed");
00681     }
00682   }
00683 
00684   bool TrajectoryPlanner::checkTrajectory(double x, double y, double theta, double vx, double vy, 
00685       double vtheta, double vx_samp, double vy_samp, double vtheta_samp){
00686     Trajectory t; 
00687 
00688     double cost = scoreTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp);
00689 
00690     
00691     if(cost >= 0)
00692       return true;
00693 
00694     
00695     return false;
00696   }
00697 
00698   double TrajectoryPlanner::scoreTrajectory(double x, double y, double theta, double vx, double vy, 
00699       double vtheta, double vx_samp, double vy_samp, double vtheta_samp){
00700     Trajectory t; 
00701     double impossible_cost = map_.map_.size();
00702     generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, 
00703         ack_acc_max_, ack_vel_max_, ack_vel_min_, impossible_cost, t);
00704 
00705     
00706     return double( t.cost_ );
00707   }
00708 
00709   
00710   Trajectory TrajectoryPlanner::createTrajectories(double x, double y, double theta, 
00711       double vx, double vy, double vtheta,
00712       double acc_x, double acc_y, double acc_theta){
00713     
00714     double max_vel_x, max_vel_theta;
00715     double min_vel_x, min_vel_theta;
00716     
00717     double v_t;
00718     double steer_angle;
00719     double min_steer=0,max_steer=0;
00720       
00721     double dvx;
00722     double dvtheta;
00723  
00724     
00725     
00726     v_t=vx;
00727     if(vy>this->ack_steer_angle_max_)
00728       vy=this->ack_steer_angle_max_;
00729     else if(vy<this->ack_steer_angle_min_)
00730       vy=this->ack_steer_angle_min_;
00731     steer_angle=vy;
00732     if(vtheta>this->ack_steer_speed_max_)
00733       vtheta=this->ack_steer_speed_max_;
00734     else if(vtheta<this->ack_steer_speed_min_)
00735       vtheta=this->ack_steer_speed_min_;
00736     this->steering_speed_=vtheta;
00737       
00738     
00739     double T4=0.0;
00740 
00741     
00742     double dist=sqrt((global_plan_[global_plan_.size()-1].pose.position.x-x)*(global_plan_[global_plan_.size()-1].pose.position.x-x)+
00743                      (global_plan_[global_plan_.size()-1].pose.position.y-y)*(global_plan_[global_plan_.size()-1].pose.position.y-y));
00744     sim_time_=dist/ack_vel_max_;
00745     if(sim_time_>10.0)
00746       sim_time_=10.0;
00747     else if(sim_time_<3.0)
00748       sim_time_=3.0;
00749     ROS_WARN("Simulation time %f\n",sim_time_);
00750     
00751     if(this->steering_speed_>=0)
00752     {
00753       max_vel_theta=(this->steering_speed_+this->ack_steer_acc_max_*sim_time_)/2.0;
00754       if(max_vel_theta>=this->ack_steer_speed_max_)
00755       {
00756         max_vel_theta=this->ack_steer_speed_max_;  
00757         T4=sim_time_-(2.0*max_vel_theta-this->steering_speed_)/this->ack_steer_acc_max_;
00758         max_steer=max_vel_theta*max_vel_theta/this->ack_steer_acc_max_-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+max_vel_theta*T4+steer_angle;
00759         if(max_steer>this->ack_steer_angle_max_) 
00760         {
00761           max_steer=this->ack_steer_angle_max_;
00762           T4=(this->ack_steer_angle_max_-steer_angle-max_vel_theta*max_vel_theta/this->ack_steer_acc_max_+this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_))/max_vel_theta;
00763           if(T4<0)
00764           {
00765             T4=0;
00766             max_vel_theta=sqrt(this->steering_speed_*this->steering_speed_/2.0+this->ack_steer_acc_max_*(this->ack_steer_angle_max_-steer_angle));
00767           }
00768         }
00769       }
00770       else
00771       { 
00772         max_steer=max_vel_theta*max_vel_theta/this->ack_steer_acc_max_-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+steer_angle;
00773         T4=0;
00774         if(max_steer>this->ack_steer_angle_max_)
00775         {
00776           max_steer=this->ack_steer_angle_max_;
00777           max_vel_theta=sqrt(this->steering_speed_*this->steering_speed_/2.0+this->ack_steer_acc_max_*(this->ack_steer_angle_max_-steer_angle));
00778         }
00779       }
00780       min_vel_theta=(this->steering_speed_-this->ack_steer_acc_max_*sim_time_)/2.0;
00781       if(min_vel_theta<=this->ack_steer_speed_min_)
00782       {
00783         min_vel_theta=this->ack_steer_speed_min_;
00784         T4=sim_time_+(2.0*min_vel_theta-this->steering_speed_)/this->ack_steer_acc_max_;
00785         min_steer=this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)-min_vel_theta*min_vel_theta/this->ack_steer_acc_max_+min_vel_theta*T4+steer_angle;
00786         if(min_steer<this->ack_steer_angle_min_)
00787         {
00788           min_steer=this->ack_steer_angle_min_;
00789           T4=(this->ack_steer_angle_min_-steer_angle+min_vel_theta*min_vel_theta/this->ack_steer_acc_max_-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_))/min_vel_theta;
00790           if(T4<0)
00791           {
00792             T4=0;
00793             min_vel_theta=-sqrt(this->steering_speed_*this->steering_speed_/2.0-this->ack_steer_acc_max_*(this->ack_steer_angle_min_-steer_angle));
00794           }
00795         }
00796       }
00797       else
00798       {
00799         min_steer=this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)-min_vel_theta*min_vel_theta/this->ack_steer_acc_max_+steer_angle;
00800         T4=0;
00801         if(min_steer<this->ack_steer_angle_min_)
00802         {
00803           min_steer=this->ack_steer_angle_min_;
00804           min_vel_theta=-sqrt(this->steering_speed_*this->steering_speed_/2.0-this->ack_steer_acc_max_*(this->ack_steer_angle_min_-steer_angle)); 
00805         }
00806       }
00807     }
00808     else
00809     {
00810       max_vel_theta=(this->steering_speed_+this->ack_steer_acc_max_*sim_time_)/2.0;
00811       if(max_vel_theta>=this->ack_steer_speed_max_)
00812       {
00813         max_vel_theta=this->ack_steer_speed_max_;
00814         T4=sim_time_-(2.0*max_vel_theta-this->steering_speed_)/this->ack_steer_acc_max_;
00815         max_steer=-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+max_vel_theta*max_vel_theta/this->ack_steer_acc_max_+max_vel_theta*T4+steer_angle;
00816         if(max_steer>this->ack_steer_angle_max_)
00817         {
00818           max_steer=this->ack_steer_angle_max_;
00819           T4=(this->ack_steer_angle_max_-steer_angle-max_vel_theta*max_vel_theta/this->ack_steer_acc_max_+this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_))/max_vel_theta;
00820           if(T4<0)
00821           {
00822             T4=0;
00823             max_vel_theta=sqrt(this->steering_speed_*this->steering_speed_/2.0+this->ack_steer_acc_max_*(this->ack_steer_angle_max_-steer_angle));
00824           }
00825         }
00826       }
00827       else
00828       {
00829         max_steer=-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+max_vel_theta*max_vel_theta/this->ack_steer_acc_max_+steer_angle;
00830         T4=0;
00831         if(max_steer>this->ack_steer_angle_max_)
00832         {
00833           max_steer=this->ack_steer_angle_max_;
00834           max_vel_theta=sqrt(this->steering_speed_*this->steering_speed_/2.0+this->ack_steer_acc_max_*(this->ack_steer_angle_max_-steer_angle));
00835         }
00836       }
00837       min_vel_theta=(this->steering_speed_-this->ack_steer_acc_max_*sim_time_)/2.0;
00838       if(min_vel_theta<=this->ack_steer_speed_min_)
00839       {
00840         min_vel_theta=this->ack_steer_speed_min_;
00841         T4=sim_time_+(2.0*min_vel_theta-this->steering_speed_)/this->ack_steer_acc_max_;
00842         min_steer=-min_vel_theta*min_vel_theta/this->ack_steer_acc_max_+this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+min_vel_theta*T4+steer_angle;
00843         if(min_steer<this->ack_steer_angle_min_)
00844         {
00845           min_steer=this->ack_steer_angle_min_;
00846           T4=(this->ack_steer_angle_min_-steer_angle+min_vel_theta*min_vel_theta/this->ack_steer_acc_max_-this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_))/min_vel_theta;
00847           if(T4<0)
00848           {
00849             T4=0;
00850             min_vel_theta=-sqrt(this->steering_speed_*this->steering_speed_/2.0-this->ack_steer_acc_max_*(this->ack_steer_angle_min_-steer_angle));
00851           }
00852         }
00853       }
00854       else
00855       {
00856         min_steer=-min_vel_theta*min_vel_theta/this->ack_steer_acc_max_+this->steering_speed_*this->steering_speed_/(2.0*this->ack_steer_acc_max_)+steer_angle;
00857         T4=0;
00858         if(min_steer<this->ack_steer_angle_min_)
00859         {
00860           min_steer=this->ack_steer_angle_min_;
00861           min_vel_theta=-sqrt(this->steering_speed_*this->steering_speed_/2.0-this->ack_steer_acc_max_*(this->ack_steer_angle_min_-steer_angle)); 
00862         }
00863       }
00864     }
00865 
00866     dist=sqrt((map_.goal_x_-x)*(map_.goal_x_-x)+(map_.goal_y_-y)*(map_.goal_y_-y));
00867     double d=0.0,T5=0.0,a,b,c;
00868 
00869     max_vel_x=(v_t+this->ack_acc_max_*sim_time_)/2.0;
00870     if(max_vel_x>this->ack_vel_max_)
00871       max_vel_x=this->ack_vel_max_;
00872     if(v_t>0)
00873     {
00874       T5=sim_time_-(2.0*max_vel_x-v_t)/this->ack_acc_max_;
00875       d=max_vel_x*max_vel_x/this->ack_acc_max_-v_t*v_t/(2.0*this->ack_acc_max_)+max_vel_x*T5;
00876       if(d>dist)
00877       {
00878         d=dist;
00879         a=1;
00880         b=-v_t-sim_time_*this->ack_acc_max_;
00881         c=v_t*v_t/2.0+dist*this->ack_acc_max_;
00882         max_vel_x=(-b-sqrt(b*b-4*a*c))/(2.0*a);
00883       }
00884     }
00885     else
00886     {
00887       T5=sim_time_-(2.0*max_vel_x-v_t)/this->ack_acc_max_;
00888       d=-v_t*v_t/(2.0*this->ack_acc_max_)+max_vel_x*max_vel_x/this->ack_acc_max_+max_vel_x*T5;
00889       if(d>dist)
00890       {
00891         d=dist;
00892         a=1;
00893         b=-v_t-sim_time_*this->ack_acc_max_;
00894         c=v_t*v_t/2.0+dist*this->ack_acc_max_;
00895         max_vel_x=(-b-sqrt(b*b-4*a*c))/(2.0*a);
00896       }
00897     }
00898     min_vel_x=-max_vel_x;
00899     ROS_INFO("TrajectoryPlanner::createTrajectories: Goal_dist: %f, Dist: %f, Max_vel: %f", dist, d, max_vel_x);
00900       
00901     dvx = (max_vel_x - min_vel_x) / (vx_samples_ - 1);
00902     dvtheta = (max_steer - min_steer) / (vtheta_samples_ - 1);
00903 
00904     double vx_samp = min_vel_x;
00905     double vtheta_samp = min_steer;
00906     double vy_samp = 0.0;
00907 
00908     
00909     Trajectory* best_traj = &traj_one;
00910     best_traj->cost_ = -1.0;
00911 
00912     Trajectory* comp_traj = &traj_two;
00913     comp_traj->cost_ = -1.0;
00914 
00915     Trajectory* swap = NULL;
00916 
00917     
00918     double impossible_cost = map_.map_.size();
00919 
00920     ROS_INFO("TrajectoryPlanner::createTrajectories: CurrentSteerAngle: %f, currentSteerSpeed: %f, CurrentSpeed: %f", vy, vtheta, vx);
00921     
00922     for(int i = 0; i < vx_samples_; ++i)
00923     {
00924       vtheta_samp = 0;
00925       
00926       
00927       generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, 
00928           acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00929 
00930       
00931       if(comp_traj->cost_ >= 0 && (comp_traj->cost_ <= best_traj->cost_ || best_traj->cost_ < 0)){
00932         swap = best_traj;
00933         best_traj = comp_traj;
00934         comp_traj = swap;
00935         ROS_DEBUG("TrajectoryPlanner::createTrajectories: vt: %f, SteerAngle: 0, Cost: %f", i*dvx+min_vel_x, comp_traj->cost_);
00936       }
00937 
00938       vtheta_samp = min_steer;
00939       
00940       for(int j = 0; j < vtheta_samples_ ; ++j){
00941         generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp, 
00942             acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00943         
00944         if(comp_traj->cost_ >= 0 && (comp_traj->cost_ <= best_traj->cost_ || best_traj->cost_ < 0)){
00945           swap = best_traj;
00946           best_traj = comp_traj;
00947           comp_traj = swap;
00948           ROS_DEBUG("TrajectoryPlanner::createTrajectories: vt: %f, SteerAngle: %f, Cost: %f", i*dvx + min_vel_x, j*dvtheta + min_steer, comp_traj->cost_);
00949         }
00950         vtheta_samp += dvtheta;
00951       }
00952       vx_samp += dvx;
00953     }
00954 
00955     
00956     vtheta_samp = min_vel_theta;
00957     vx_samp = 0.0;
00958     vy_samp = 0.0;
00959 
00960     
00961     if(best_traj->cost_ >= 0)
00962     {
00963       
00964       dist=sqrt((map_.goal_x_-x)*(map_.goal_x_-x)+(map_.goal_y_-y)*(map_.goal_y_-y));
00965       if(dist>xy_goal_tol_ && fabs(best_traj->xv_)<0.02)
00966         best_traj->cost_=-1;
00967       return *best_traj;
00968     }
00969 
00970     
00971     if(best_traj->cost_ == -1.0)
00972     {
00973       best_traj->resetPoints();
00974       best_traj->xv_ = 0.0;
00975       best_traj->yv_ = 0.0;
00976       best_traj->thetav_ = 0.0;
00977       best_traj->cost_ = -3.0;
00978     }
00979 
00980     return *best_traj;
00981   }
00982 
00983   
00984   Trajectory TrajectoryPlanner::findBestPath(tf::Stamped<tf::Pose> global_pose, tf::Stamped<tf::Pose> global_vel, 
00985       tf::Stamped<tf::Pose>& drive_velocities,geometry_msgs::Twist &ackermann_state)
00986   {
00987     static Trajectory last_best_traj;
00988 
00989     double yaw = tf::getYaw(global_pose.getRotation());
00990     
00991 
00992     double x = global_pose.getOrigin().getX();
00993     double y = global_pose.getOrigin().getY();
00994     double theta = yaw;
00995 
00996     double vx = ackermann_state.linear.z;
00997     double vy = ackermann_state.angular.x;
00998     double vtheta = ackermann_state.angular.y;
00999 
01000     
01001     map_.resetPathDist();
01002 
01003     
01004     vector<iri_ackermann_local_planner::Position2DInt> footprint_list = getFootprintCells(x, y, theta, true);
01005 
01006     
01007     for(unsigned int i = 0; i < footprint_list.size(); ++i){
01008       map_(footprint_list[i].x, footprint_list[i].y).within_robot = true;
01009     }
01010 
01011     
01012     map_.setPathCells(costmap_, global_plan_);
01013     ROS_DEBUG("Path/Goal distance computed");
01014 
01015 
01016     
01017     Trajectory best = createTrajectories(x, y, theta, 
01018         vx, vy, vtheta, 
01019         ack_acc_max_, ack_vel_max_, ack_vel_min_);
01020     ROS_DEBUG("Trajectories created");
01021 
01022     if(best.cost_ < 0){
01023       if(best.cost_==-3)
01024       {
01025         best.xv_=last_best_traj.xv_;
01026         best.yv_=last_best_traj.yv_;
01027         best.thetav_=last_best_traj.thetav_;
01028         best.cost_=last_best_traj.cost_;
01029         tf::Vector3 start(best.xv_, best.yv_, 0);
01030         drive_velocities.setOrigin(start);
01031         tf::Matrix3x3 matrix;
01032         matrix.setRotation(tf::createQuaternionFromYaw(best.thetav_));
01033         drive_velocities.setBasis(matrix);
01034       }
01035       else
01036         drive_velocities.setIdentity();
01037     }
01038     else{
01039       tf::Vector3 start(best.xv_, best.yv_, 0);
01040       drive_velocities.setOrigin(start);
01041       tf::Matrix3x3 matrix;
01042       matrix.setRotation(tf::createQuaternionFromYaw(best.thetav_));
01043       drive_velocities.setBasis(matrix);
01044       last_best_traj.xv_=best.xv_;
01045       last_best_traj.yv_=best.yv_;
01046       last_best_traj.thetav_=best.thetav_;
01047       last_best_traj.cost_=best.cost_;
01048     }
01049 
01050     return best;
01051   }
01052 
01053   
01054   double TrajectoryPlanner::footprintCost(double x_i, double y_i, double theta_i){
01055     
01056     double cos_th = cos(theta_i);
01057     double sin_th = sin(theta_i);
01058     vector<geometry_msgs::Point> oriented_footprint;
01059     for(unsigned int i = 0; i < footprint_spec_.size(); ++i){
01060       geometry_msgs::Point new_pt;
01061       new_pt.x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
01062       new_pt.y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
01063       oriented_footprint.push_back(new_pt);
01064     }
01065 
01066     geometry_msgs::Point robot_position;
01067     robot_position.x = x_i;
01068     robot_position.y = y_i;
01069 
01070     
01071     double footprint_cost = world_model_.footprintCost(robot_position, oriented_footprint, costmap_.getInscribedRadius(), costmap_.getCircumscribedRadius());
01072 
01073     return footprint_cost;
01074   }
01075 
01076   void TrajectoryPlanner::getLineCells(int x0, int x1, int y0, int y1, vector<iri_ackermann_local_planner::Position2DInt>& pts){
01077     
01078     int deltax = abs(x1 - x0);        
01079     int deltay = abs(y1 - y0);        
01080     int x = x0;                       
01081     int y = y0;                       
01082 
01083     int xinc1, xinc2, yinc1, yinc2;
01084     int den, num, numadd, numpixels;
01085 
01086     iri_ackermann_local_planner::Position2DInt pt;
01087 
01088     if (x1 >= x0)                 
01089     {
01090       xinc1 = 1;
01091       xinc2 = 1;
01092     }
01093     else                          
01094     {
01095       xinc1 = -1;
01096       xinc2 = -1;
01097     }
01098 
01099     if (y1 >= y0)                 
01100     {
01101       yinc1 = 1;
01102       yinc2 = 1;
01103     }
01104     else                          
01105     {
01106       yinc1 = -1;
01107       yinc2 = -1;
01108     }
01109 
01110     if (deltax >= deltay)         
01111     {
01112       xinc1 = 0;                  
01113       yinc2 = 0;                  
01114       den = deltax;
01115       num = deltax / 2;
01116       numadd = deltay;
01117       numpixels = deltax;         
01118     }
01119     else                          
01120     {
01121       xinc2 = 0;                  
01122       yinc1 = 0;                  
01123       den = deltay;
01124       num = deltay / 2;
01125       numadd = deltax;
01126       numpixels = deltay;         
01127     }
01128 
01129     for (int curpixel = 0; curpixel <= numpixels; curpixel++)
01130     {
01131       pt.x = x;      
01132       pt.y = y;
01133       pts.push_back(pt);
01134 
01135       num += numadd;              
01136       if (num >= den)             
01137       {
01138         num -= den;               
01139         x += xinc1;               
01140         y += yinc1;               
01141       }
01142       x += xinc2;                 
01143       y += yinc2;                 
01144     }
01145   }
01146 
01147   
01148   vector<iri_ackermann_local_planner::Position2DInt> TrajectoryPlanner::getFootprintCells(double x_i, double y_i, double theta_i, bool fill){
01149     vector<iri_ackermann_local_planner::Position2DInt> footprint_cells;
01150 
01151     
01152     if(footprint_spec_.size() <= 1){
01153       unsigned int mx, my;
01154       if(costmap_.worldToMap(x_i, y_i, mx, my)){
01155         Position2DInt center;
01156         center.x = mx;
01157         center.y = my;
01158         footprint_cells.push_back(center);
01159       }
01160       return footprint_cells;
01161     }
01162 
01163     
01164     double cos_th = cos(theta_i);
01165     double sin_th = sin(theta_i);
01166     double new_x, new_y;
01167     unsigned int x0, y0, x1, y1;
01168     unsigned int last_index = footprint_spec_.size() - 1;
01169 
01170     for(unsigned int i = 0; i < last_index; ++i){
01171       
01172       new_x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
01173       new_y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
01174       if(!costmap_.worldToMap(new_x, new_y, x0, y0))
01175         return footprint_cells;
01176 
01177       
01178       new_x = x_i + (footprint_spec_[i + 1].x * cos_th - footprint_spec_[i + 1].y * sin_th);
01179       new_y = y_i + (footprint_spec_[i + 1].x * sin_th + footprint_spec_[i + 1].y * cos_th);
01180       if(!costmap_.worldToMap(new_x, new_y, x1, y1))
01181         return footprint_cells;
01182 
01183       getLineCells(x0, x1, y0, y1, footprint_cells);
01184     }
01185 
01186     
01187     new_x = x_i + (footprint_spec_[last_index].x * cos_th - footprint_spec_[last_index].y * sin_th);
01188     new_y = y_i + (footprint_spec_[last_index].x * sin_th + footprint_spec_[last_index].y * cos_th);
01189     if(!costmap_.worldToMap(new_x, new_y, x0, y0))
01190       return footprint_cells;
01191 
01192     new_x = x_i + (footprint_spec_[0].x * cos_th - footprint_spec_[0].y * sin_th);
01193     new_y = y_i + (footprint_spec_[0].x * sin_th + footprint_spec_[0].y * cos_th);
01194     if(!costmap_.worldToMap(new_x, new_y, x1, y1))
01195       return footprint_cells;
01196 
01197     getLineCells(x0, x1, y0, y1, footprint_cells);
01198 
01199     if(fill)
01200       getFillCells(footprint_cells);
01201 
01202     return footprint_cells;
01203   }
01204 
01205   void TrajectoryPlanner::getFillCells(vector<iri_ackermann_local_planner::Position2DInt>& footprint){
01206     
01207     iri_ackermann_local_planner::Position2DInt swap, pt;
01208     unsigned int i = 0;
01209     while(i < footprint.size() - 1){
01210       if(footprint[i].x > footprint[i + 1].x){
01211         swap = footprint[i];
01212         footprint[i] = footprint[i + 1];
01213         footprint[i + 1] = swap;
01214         if(i > 0)
01215           --i;
01216       }
01217       else
01218         ++i;
01219     }
01220 
01221     i = 0;
01222     iri_ackermann_local_planner::Position2DInt min_pt;
01223     iri_ackermann_local_planner::Position2DInt max_pt;
01224     unsigned int min_x = footprint[0].x;
01225     unsigned int max_x = footprint[footprint.size() -1].x;
01226     
01227     for(unsigned int x = min_x; x <= max_x; ++x){
01228       if(i >= footprint.size() - 1)
01229         break;
01230 
01231       if(footprint[i].y < footprint[i + 1].y){
01232         min_pt = footprint[i];
01233         max_pt = footprint[i + 1];
01234       }
01235       else{
01236         min_pt = footprint[i + 1];
01237         max_pt = footprint[i];
01238       }
01239 
01240       i += 2;
01241       while(i < footprint.size() && footprint[i].x == x){
01242         if(footprint[i].y < min_pt.y)
01243           min_pt = footprint[i];
01244         else if(footprint[i].y > max_pt.y)
01245           max_pt = footprint[i];
01246         ++i;
01247       }
01248 
01249       
01250       for(unsigned int y = min_pt.y; y < max_pt.y; ++y){
01251         pt.x = x;
01252         pt.y = y;
01253         footprint.push_back(pt);
01254       }
01255     }
01256   }
01257 
01258   void TrajectoryPlanner::getLocalGoal(double& x, double& y){
01259     x = map_.goal_x_;
01260     y = map_.goal_y_;
01261   }
01262 
01263 };