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 };