00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <iri_diff_local_planner/trajectory_planner.h>
00039
00040 using namespace std;
00041 using namespace costmap_2d;
00042
00043 namespace iri_diff_local_planner{
00044 void TrajectoryPlanner::reconfigure(IriDiffLocalPlannerConfig &cfg)
00045 {
00046 iri_diff_local_planner::IriDiffLocalPlannerConfig config(cfg);
00047
00048 boost::mutex::scoped_lock l(configuration_mutex_);
00049
00050 acc_lim_x_ = config.acc_lim_x;
00051 acc_lim_y_ = config.acc_lim_y;
00052 acc_lim_theta_ = config.acc_lim_theta;
00053
00054 *max_vel_x_ = config.max_vel_x;
00055 min_vel_x_ = config.min_vel_x;
00056 max_vel_th_ = config.max_vel_theta;
00057 min_vel_th_ = config.min_vel_theta;
00058 min_in_place_vel_th_ = config.min_in_place_vel_theta;
00059
00060 sim_time_ = config.sim_time;
00061 sim_granularity_ = config.sim_granularity;
00062
00063 pdist_scale_ = config.pdist_scale;
00064 gdist_scale_ = config.gdist_scale;
00065 occdist_scale_ = config.occdist_scale;
00066
00067 oscillation_reset_dist_ = config.oscillation_reset_dist;
00068 escape_reset_dist_ = config.escape_reset_dist;
00069 escape_reset_theta_ = config.escape_reset_theta;
00070
00071 vx_samples_ = config.vx_samples;
00072 vtheta_samples_ = config.vtheta_samples;
00073
00074 if (vx_samples_ <= 0) {
00075 config.vx_samples = 1;
00076 vx_samples_ = config.vx_samples;
00077 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");
00078 }
00079 if(vtheta_samples_ <= 0) {
00080 config.vtheta_samples = 1;
00081 vtheta_samples_ = config.vtheta_samples;
00082 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");
00083 }
00084
00085 heading_lookahead_ = config.heading_lookahead;
00086
00087 holonomic_robot_ = config.holonomic_robot;
00088
00089 backup_vel_ = config.escape_vel;
00090
00091 dwa_ = config.dwa;
00092
00093 heading_scoring_ = config.heading_scoring;
00094 heading_scoring_timestep_ = config.heading_scoring_timestep;
00095
00096 simple_attractor_ = config.simple_attractor;
00097
00098 angular_sim_granularity_ = config.angular_sim_granularity;
00099
00100
00101 string y_string = config.y_vels;
00102 vector<string> y_strs;
00103 boost::split(y_strs, y_string, boost::is_any_of(", "), boost::token_compress_on);
00104
00105 vector<double>y_vels;
00106 for(vector<string>::iterator it=y_strs.begin(); it != y_strs.end(); ++it) {
00107 istringstream iss(*it);
00108 double temp;
00109 iss >> temp;
00110 y_vels.push_back(temp);
00111
00112 }
00113
00114 y_vels_ = y_vels;
00115
00116 }
00117
00118 TrajectoryPlanner::TrajectoryPlanner(WorldModel& world_model,
00119 const Costmap2D& costmap,
00120 std::vector<geometry_msgs::Point> footprint_spec,
00121 double acc_lim_x, double acc_lim_y, double acc_lim_theta,
00122 double sim_time, double sim_granularity,
00123 int vx_samples, int vtheta_samples,
00124 double pdist_scale, double gdist_scale, double occdist_scale,
00125 double heading_lookahead, double oscillation_reset_dist,
00126 double escape_reset_dist, double escape_reset_theta,
00127 bool holonomic_robot,
00128 double *max_vel_x, double min_vel_x,
00129 double max_vel_th, double min_vel_th, double min_in_place_vel_th,
00130 double backup_vel,
00131 bool dwa, bool heading_scoring, double heading_scoring_timestep, bool simple_attractor,
00132 vector<double> y_vels, double stop_time_buffer, double sim_period, double angular_sim_granularity)
00133 : map_(costmap.getSizeInCellsX(), costmap.getSizeInCellsY()), costmap_(costmap),
00134 world_model_(world_model), footprint_spec_(footprint_spec),
00135 sim_time_(sim_time), sim_granularity_(sim_granularity), angular_sim_granularity_(angular_sim_granularity),
00136 vx_samples_(vx_samples), vtheta_samples_(vtheta_samples),
00137 pdist_scale_(pdist_scale), gdist_scale_(gdist_scale), occdist_scale_(occdist_scale),
00138 acc_lim_x_(acc_lim_x), acc_lim_y_(acc_lim_y), acc_lim_theta_(acc_lim_theta),
00139 prev_x_(0), prev_y_(0), escape_x_(0), escape_y_(0), escape_theta_(0), heading_lookahead_(heading_lookahead),
00140 oscillation_reset_dist_(oscillation_reset_dist), escape_reset_dist_(escape_reset_dist),
00141 escape_reset_theta_(escape_reset_theta), holonomic_robot_(holonomic_robot),
00142 min_vel_x_(min_vel_x),
00143 max_vel_th_(max_vel_th), min_vel_th_(min_vel_th), min_in_place_vel_th_(min_in_place_vel_th),
00144 backup_vel_(backup_vel),
00145 dwa_(dwa), heading_scoring_(heading_scoring), heading_scoring_timestep_(heading_scoring_timestep),
00146 simple_attractor_(simple_attractor), y_vels_(y_vels), stop_time_buffer_(stop_time_buffer), sim_period_(sim_period)
00147 {
00148 this->max_vel_x_=max_vel_x;
00149
00150
00151 stuck_left = false;
00152 stuck_right = false;
00153 stuck_left_strafe = false;
00154 stuck_right_strafe = false;
00155 rotating_left = false;
00156 rotating_right = false;
00157 strafe_left = false;
00158 strafe_right = false;
00159
00160 escaping_ = false;
00161 }
00162
00163 TrajectoryPlanner::~TrajectoryPlanner(){}
00164
00165 bool TrajectoryPlanner::getCellCosts(int cx, int cy, float &path_cost, float &goal_cost, float &occ_cost, float &total_cost) {
00166 MapCell cell = map_(cx, cy);
00167 if (cell.within_robot) {
00168 return false;
00169 }
00170 occ_cost = costmap_.getCost(cx, cy);
00171 if (cell.path_dist >= map_.map_.size() || cell.goal_dist >= map_.map_.size() || occ_cost >= costmap_2d::INSCRIBED_INFLATED_OBSTACLE) {
00172 return false;
00173 }
00174 path_cost = cell.path_dist;
00175 goal_cost = cell.goal_dist;
00176 total_cost = pdist_scale_ * path_cost + gdist_scale_ * goal_cost + occdist_scale_ * occ_cost;
00177 return true;
00178 }
00179
00180
00181 void TrajectoryPlanner::generateTrajectory(double x, double y, double theta, double vx, double vy,
00182 double vtheta, double vx_samp, double vy_samp, double vtheta_samp,
00183 double acc_x, double acc_y, double acc_theta, double impossible_cost,
00184 Trajectory& traj){
00185
00186
00187 boost::mutex::scoped_lock l(configuration_mutex_);
00188
00189 double x_i = x;
00190 double y_i = y;
00191 double theta_i = theta;
00192
00193 double vx_i, vy_i, vtheta_i;
00194
00195 vx_i = vx;
00196 vy_i = vy;
00197 vtheta_i = vtheta;
00198
00199
00200 double vmag = sqrt(vx_samp * vx_samp + vy_samp * vy_samp);
00201
00202
00203 int num_steps;
00204 if(!heading_scoring_)
00205 num_steps = int(max((vmag * sim_time_) / sim_granularity_, fabs(vtheta_samp) / angular_sim_granularity_) + 0.5);
00206 else
00207 num_steps = int(sim_time_ / sim_granularity_ + 0.5);
00208
00209
00210 if(num_steps == 0)
00211 num_steps = 1;
00212
00213 double dt = sim_time_ / num_steps;
00214 double time = 0.0;
00215
00216
00217 traj.resetPoints();
00218 traj.xv_ = vx_samp;
00219 traj.yv_ = vy_samp;
00220 traj.thetav_ = vtheta_samp;
00221 traj.cost_ = -1.0;
00222
00223
00224 double path_dist = 0.0;
00225 double goal_dist = 0.0;
00226 double occ_cost = 0.0;
00227 double heading_diff = 0.0;
00228
00229 for(int i = 0; i < num_steps; ++i){
00230
00231 unsigned int cell_x, cell_y;
00232
00233
00234 if(!costmap_.worldToMap(x_i, y_i, cell_x, cell_y)){
00235 traj.cost_ = -1.0;
00236 return;
00237 }
00238
00239
00240 double footprint_cost = footprintCost(x_i, y_i, theta_i);
00241
00242
00243 if(footprint_cost < 0){
00244 traj.cost_ = -1.0;
00245 return;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 }
00268
00269 occ_cost = std::max(std::max(occ_cost, footprint_cost), double(costmap_.getCost(cell_x, cell_y)));
00270
00271 double cell_pdist = map_(cell_x, cell_y).path_dist;
00272 double cell_gdist = map_(cell_x, cell_y).goal_dist;
00273
00274
00275 if(!heading_scoring_){
00276 path_dist = cell_pdist;
00277 goal_dist = cell_gdist;
00278 }
00279 else if(time >= heading_scoring_timestep_ && time < heading_scoring_timestep_ + dt){
00280 heading_diff = headingDiff(cell_x, cell_y, x_i, y_i, theta_i);
00281
00282 path_dist = cell_pdist;
00283 goal_dist = cell_gdist;
00284 }
00285
00286
00287 if(simple_attractor_){
00288 goal_dist = (x_i - global_plan_[global_plan_.size() -1].pose.position.x) *
00289 (x_i - global_plan_[global_plan_.size() -1].pose.position.x) +
00290 (y_i - global_plan_[global_plan_.size() -1].pose.position.y) *
00291 (y_i - global_plan_[global_plan_.size() -1].pose.position.y);
00292 path_dist = 0.0;
00293 }
00294 else{
00295
00296 if(impossible_cost <= goal_dist || impossible_cost <= path_dist){
00297 ROS_DEBUG("No path to goal with goal distance = %f, path_distance = %f and max cost = %f",
00298 goal_dist, path_dist, impossible_cost);
00299 traj.cost_ = -2.0;
00300 return;
00301 }
00302 }
00303
00304
00305
00306 traj.addPoint(x_i, y_i, theta_i);
00307
00308
00309 vx_i = computeNewVelocity(vx_samp, vx_i, acc_x, dt);
00310 vy_i = computeNewVelocity(vy_samp, vy_i, acc_y, dt);
00311 vtheta_i = computeNewVelocity(vtheta_samp, vtheta_i, acc_theta, dt);
00312
00313
00314 x_i = computeNewXPosition(x_i, vx_i, vy_i, theta_i, dt);
00315 y_i = computeNewYPosition(y_i, vx_i, vy_i, theta_i, dt);
00316 theta_i = computeNewThetaPosition(theta_i, vtheta_i, dt);
00317
00318
00319 time += dt;
00320 }
00321
00322
00323 double cost = -1.0;
00324 if(!heading_scoring_)
00325 cost = pdist_scale_ * path_dist + goal_dist * gdist_scale_ + occdist_scale_ * occ_cost;
00326 else
00327 cost = occdist_scale_ * occ_cost + pdist_scale_ * path_dist + 0.3 * heading_diff + goal_dist * gdist_scale_;
00328
00329 traj.cost_ = cost;
00330 }
00331
00332 double TrajectoryPlanner::headingDiff(int cell_x, int cell_y, double x, double y, double heading){
00333 double heading_diff = DBL_MAX;
00334 unsigned int goal_cell_x, goal_cell_y;
00335
00336 for(int i = global_plan_.size() - 1; i >=0; --i){
00337 if(costmap_.worldToMap(global_plan_[i].pose.position.x, global_plan_[i].pose.position.y, goal_cell_x, goal_cell_y)){
00338 if(lineCost(cell_x, goal_cell_x, cell_y, goal_cell_y) >= 0){
00339 double gx, gy;
00340 costmap_.mapToWorld(goal_cell_x, goal_cell_y, gx, gy);
00341 double v1_x = gx - x;
00342 double v1_y = gy - y;
00343 double v2_x = cos(heading);
00344 double v2_y = sin(heading);
00345
00346 double perp_dot = v1_x * v2_y - v1_y * v2_x;
00347 double dot = v1_x * v2_x + v1_y * v2_y;
00348
00349
00350 double vector_angle = atan2(perp_dot, dot);
00351
00352 heading_diff = fabs(vector_angle);
00353 return heading_diff;
00354
00355 }
00356 }
00357 }
00358 return heading_diff;
00359 }
00360
00361
00362 double TrajectoryPlanner::lineCost(int x0, int x1,
00363 int y0, int y1){
00364
00365 int deltax = abs(x1 - x0);
00366 int deltay = abs(y1 - y0);
00367 int x = x0;
00368 int y = y0;
00369
00370 int xinc1, xinc2, yinc1, yinc2;
00371 int den, num, numadd, numpixels;
00372
00373 double line_cost = 0.0;
00374 double point_cost = -1.0;
00375
00376 if (x1 >= x0)
00377 {
00378 xinc1 = 1;
00379 xinc2 = 1;
00380 }
00381 else
00382 {
00383 xinc1 = -1;
00384 xinc2 = -1;
00385 }
00386
00387 if (y1 >= y0)
00388 {
00389 yinc1 = 1;
00390 yinc2 = 1;
00391 }
00392 else
00393 {
00394 yinc1 = -1;
00395 yinc2 = -1;
00396 }
00397
00398 if (deltax >= deltay)
00399 {
00400 xinc1 = 0;
00401 yinc2 = 0;
00402 den = deltax;
00403 num = deltax / 2;
00404 numadd = deltay;
00405 numpixels = deltax;
00406 }
00407 else
00408 {
00409 xinc2 = 0;
00410 yinc1 = 0;
00411 den = deltay;
00412 num = deltay / 2;
00413 numadd = deltax;
00414 numpixels = deltay;
00415 }
00416
00417 for (int curpixel = 0; curpixel <= numpixels; curpixel++)
00418 {
00419 point_cost = pointCost(x, y);
00420
00421 if(point_cost < 0)
00422 return -1;
00423
00424 if(line_cost < point_cost)
00425 line_cost = point_cost;
00426
00427 num += numadd;
00428 if (num >= den)
00429 {
00430 num -= den;
00431 x += xinc1;
00432 y += yinc1;
00433 }
00434 x += xinc2;
00435 y += yinc2;
00436 }
00437
00438 return line_cost;
00439 }
00440
00441 double TrajectoryPlanner::pointCost(int x, int y){
00442 unsigned char cost = costmap_.getCost(x, y);
00443
00444 if(cost == LETHAL_OBSTACLE || cost == INSCRIBED_INFLATED_OBSTACLE || cost == NO_INFORMATION){
00445 return -1;
00446 }
00447
00448 return cost;
00449 }
00450
00451 void TrajectoryPlanner::updatePlan(const vector<geometry_msgs::PoseStamped>& new_plan, bool compute_dists){
00452 global_plan_.resize(new_plan.size());
00453 for(unsigned int i = 0; i < new_plan.size(); ++i){
00454 global_plan_[i] = new_plan[i];
00455 }
00456
00457 if(compute_dists){
00458
00459 map_.resetPathDist();
00460
00461
00462 map_.setPathCells(costmap_, global_plan_);
00463 ROS_DEBUG("Path/Goal distance computed");
00464 }
00465 }
00466
00467 bool TrajectoryPlanner::checkTrajectory(double x, double y, double theta, double vx, double vy,
00468 double vtheta, double vx_samp, double vy_samp, double vtheta_samp){
00469 Trajectory t;
00470
00471 double cost = scoreTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp);
00472
00473
00474 if(cost >= 0)
00475 return true;
00476
00477
00478 return false;
00479 }
00480
00481 double TrajectoryPlanner::scoreTrajectory(double x, double y, double theta, double vx, double vy,
00482 double vtheta, double vx_samp, double vy_samp, double vtheta_samp){
00483 Trajectory t;
00484 double impossible_cost = map_.map_.size();
00485 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00486 acc_lim_x_, acc_lim_y_, acc_lim_theta_, impossible_cost, t);
00487
00488
00489 return double( t.cost_ );
00490 }
00491
00492
00493 Trajectory TrajectoryPlanner::createTrajectories(double x, double y, double theta,
00494 double vx, double vy, double vtheta,
00495 double acc_x, double acc_y, double acc_theta){
00496
00497 double max_vel_x, max_vel_theta;
00498 double min_vel_x, min_vel_theta;
00499
00500
00501 if(dwa_){
00502 max_vel_x = max(min(*max_vel_x_, vx + acc_x * sim_period_), min_vel_x_);
00503 min_vel_x = max(min_vel_x_, vx - acc_x * sim_period_);
00504
00505 max_vel_theta = min(max_vel_th_, vtheta + acc_theta * sim_period_);
00506 min_vel_theta = max(min_vel_th_, vtheta - acc_theta * sim_period_);
00507 }
00508 else{
00509 max_vel_x = max(min(*max_vel_x_, vx + acc_x * sim_time_), min_vel_x_);
00510 min_vel_x = max(min_vel_x_, vx - acc_x * sim_time_);
00511
00512 max_vel_theta = min(max_vel_th_, vtheta + acc_theta * sim_time_);
00513 min_vel_theta = max(min_vel_th_, vtheta - acc_theta * sim_time_);
00514 }
00515
00516
00517
00518 double dvx = (max_vel_x - min_vel_x) / (vx_samples_ - 1);
00519 double dvtheta = (max_vel_theta - min_vel_theta) / (vtheta_samples_ - 1);
00520
00521 double vx_samp = min_vel_x;
00522 double vtheta_samp = min_vel_theta;
00523 double vy_samp = 0.0;
00524
00525
00526 Trajectory* best_traj = &traj_one;
00527 best_traj->cost_ = -1.0;
00528
00529 Trajectory* comp_traj = &traj_two;
00530 comp_traj->cost_ = -1.0;
00531
00532 Trajectory* swap = NULL;
00533
00534
00535 double impossible_cost = map_.map_.size();
00536
00537
00538 if(!escaping_){
00539
00540 for(int i = 0; i < vx_samples_; ++i){
00541 vtheta_samp = 0;
00542
00543 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00544 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00545
00546
00547 if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
00548 swap = best_traj;
00549 best_traj = comp_traj;
00550 comp_traj = swap;
00551 }
00552
00553 vtheta_samp = min_vel_theta;
00554
00555 for(int j = 0; j < vtheta_samples_ - 1; ++j){
00556 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00557 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00558
00559
00560 if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
00561 swap = best_traj;
00562 best_traj = comp_traj;
00563 comp_traj = swap;
00564 }
00565 vtheta_samp += dvtheta;
00566 }
00567 vx_samp += dvx;
00568 }
00569
00570
00571 if(holonomic_robot_){
00572
00573 vx_samp = 0.1;
00574 vy_samp = 0.1;
00575 vtheta_samp = 0.0;
00576 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00577 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00578
00579
00580 if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
00581 swap = best_traj;
00582 best_traj = comp_traj;
00583 comp_traj = swap;
00584 }
00585
00586 vx_samp = 0.1;
00587 vy_samp = -0.1;
00588 vtheta_samp = 0.0;
00589 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00590 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00591
00592
00593 if(comp_traj->cost_ >= 0 && (comp_traj->cost_ < best_traj->cost_ || best_traj->cost_ < 0)){
00594 swap = best_traj;
00595 best_traj = comp_traj;
00596 comp_traj = swap;
00597 }
00598 }
00599 }
00600
00601
00602 vtheta_samp = min_vel_theta;
00603 vx_samp = 0.0;
00604 vy_samp = 0.0;
00605
00606
00607 double heading_dist = DBL_MAX;
00608
00609 for(int i = 0; i < vtheta_samples_; ++i){
00610
00611 double vtheta_samp_limited = vtheta_samp > 0 ? max(vtheta_samp, min_in_place_vel_th_)
00612 : min(vtheta_samp, -1.0 * min_in_place_vel_th_);
00613
00614 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp_limited,
00615 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00616
00617
00618
00619 if(comp_traj->cost_ >= 0
00620 && (comp_traj->cost_ <= best_traj->cost_ || best_traj->cost_ < 0 || best_traj->yv_ != 0.0)
00621 && (vtheta_samp > dvtheta || vtheta_samp < -1 * dvtheta)){
00622 double x_r, y_r, th_r;
00623 comp_traj->getEndpoint(x_r, y_r, th_r);
00624 x_r += heading_lookahead_ * cos(th_r);
00625 y_r += heading_lookahead_ * sin(th_r);
00626 unsigned int cell_x, cell_y;
00627
00628
00629 if(costmap_.worldToMap(x_r, y_r, cell_x, cell_y)){
00630 double ahead_gdist = map_(cell_x, cell_y).goal_dist;
00631 if(ahead_gdist < heading_dist){
00632
00633 if(vtheta_samp < 0 && !stuck_left){
00634 swap = best_traj;
00635 best_traj = comp_traj;
00636 comp_traj = swap;
00637 heading_dist = ahead_gdist;
00638 }
00639
00640 else if(vtheta_samp > 0 && !stuck_right){
00641 swap = best_traj;
00642 best_traj = comp_traj;
00643 comp_traj = swap;
00644 heading_dist = ahead_gdist;
00645 }
00646 }
00647 }
00648 }
00649
00650 vtheta_samp += dvtheta;
00651 }
00652
00653
00654 if(best_traj->cost_ >= 0){
00655 if(!(best_traj->xv_ > 0)){
00656 if(best_traj->thetav_ < 0){
00657 if(rotating_right){
00658 stuck_right = true;
00659 }
00660 rotating_left = true;
00661 }
00662 else if(best_traj->thetav_ > 0){
00663 if(rotating_left){
00664 stuck_left = true;
00665 }
00666 rotating_right = true;
00667 }
00668 else if(best_traj->yv_ > 0){
00669 if(strafe_right){
00670 stuck_right_strafe = true;
00671 }
00672 strafe_left = true;
00673 }
00674 else if(best_traj->yv_ < 0){
00675 if(strafe_left){
00676 stuck_left_strafe = true;
00677 }
00678 strafe_right = true;
00679 }
00680
00681
00682 prev_x_ = x;
00683 prev_y_ = y;
00684 }
00685
00686 double dist = sqrt((x - prev_x_) * (x - prev_x_) + (y - prev_y_) * (y - prev_y_));
00687 if(dist > oscillation_reset_dist_){
00688 rotating_left = false;
00689 rotating_right = false;
00690 strafe_left = false;
00691 strafe_right = false;
00692 stuck_left = false;
00693 stuck_right = false;
00694 stuck_left_strafe = false;
00695 stuck_right_strafe = false;
00696 }
00697
00698 dist = sqrt((x - escape_x_) * (x - escape_x_) + (y - escape_y_) * (y - escape_y_));
00699 if(dist > escape_reset_dist_ || fabs(angles::shortest_angular_distance(escape_theta_, theta)) > escape_reset_theta_){
00700 escaping_ = false;
00701 }
00702
00703 return *best_traj;
00704 }
00705
00706
00707
00708
00709 if(holonomic_robot_){
00710
00711 vtheta_samp = min_vel_theta;
00712 vx_samp = 0.0;
00713
00714
00715 for(unsigned int i = 0; i < y_vels_.size(); ++i){
00716 vtheta_samp = 0;
00717 vy_samp = y_vels_[i];
00718
00719 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00720 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00721
00722
00723 if(comp_traj->cost_ >= 0 && (comp_traj->cost_ <= best_traj->cost_ || best_traj->cost_ < 0)){
00724 double x_r, y_r, th_r;
00725 comp_traj->getEndpoint(x_r, y_r, th_r);
00726 x_r += heading_lookahead_ * cos(th_r);
00727 y_r += heading_lookahead_ * sin(th_r);
00728 unsigned int cell_x, cell_y;
00729
00730
00731 if(costmap_.worldToMap(x_r, y_r, cell_x, cell_y)){
00732 double ahead_gdist = map_(cell_x, cell_y).goal_dist;
00733 if(ahead_gdist < heading_dist){
00734
00735 if(vy_samp > 0 && !stuck_left_strafe){
00736 swap = best_traj;
00737 best_traj = comp_traj;
00738 comp_traj = swap;
00739 heading_dist = ahead_gdist;
00740 }
00741
00742 else if(vy_samp < 0 && !stuck_right_strafe){
00743 swap = best_traj;
00744 best_traj = comp_traj;
00745 comp_traj = swap;
00746 heading_dist = ahead_gdist;
00747 }
00748 }
00749 }
00750 }
00751 }
00752 }
00753
00754
00755 if(best_traj->cost_ >= 0){
00756 if(!(best_traj->xv_ > 0)){
00757 if(best_traj->thetav_ < 0){
00758 if(rotating_right){
00759 stuck_right = true;
00760 }
00761 rotating_left = true;
00762 }
00763 else if(best_traj->thetav_ > 0){
00764 if(rotating_left){
00765 stuck_left = true;
00766 }
00767 rotating_right = true;
00768 }
00769 else if(best_traj->yv_ > 0){
00770 if(strafe_right){
00771 stuck_right_strafe = true;
00772 }
00773 strafe_left = true;
00774 }
00775 else if(best_traj->yv_ < 0){
00776 if(strafe_left){
00777 stuck_left_strafe = true;
00778 }
00779 strafe_right = true;
00780 }
00781
00782
00783 prev_x_ = x;
00784 prev_y_ = y;
00785
00786 }
00787
00788 double dist = sqrt((x - prev_x_) * (x - prev_x_) + (y - prev_y_) * (y - prev_y_));
00789 if(dist > oscillation_reset_dist_){
00790 rotating_left = false;
00791 rotating_right = false;
00792 strafe_left = false;
00793 strafe_right = false;
00794 stuck_left = false;
00795 stuck_right = false;
00796 stuck_left_strafe = false;
00797 stuck_right_strafe = false;
00798 }
00799
00800 dist = sqrt((x - escape_x_) * (x - escape_x_) + (y - escape_y_) * (y - escape_y_));
00801 if(dist > escape_reset_dist_ || fabs(angles::shortest_angular_distance(escape_theta_, theta)) > escape_reset_theta_){
00802 escaping_ = false;
00803 }
00804
00805 return *best_traj;
00806 }
00807
00808
00809 vtheta_samp = 0.0;
00810 vx_samp = backup_vel_;
00811 vy_samp = 0.0;
00812 generateTrajectory(x, y, theta, vx, vy, vtheta, vx_samp, vy_samp, vtheta_samp,
00813 acc_x, acc_y, acc_theta, impossible_cost, *comp_traj);
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 swap = best_traj;
00826 best_traj = comp_traj;
00827 comp_traj = swap;
00828
00829 double dist = sqrt((x - prev_x_) * (x - prev_x_) + (y - prev_y_) * (y - prev_y_));
00830 if(dist > oscillation_reset_dist_){
00831 rotating_left = false;
00832 rotating_right = false;
00833 strafe_left = false;
00834 strafe_right = false;
00835 stuck_left = false;
00836 stuck_right = false;
00837 stuck_left_strafe = false;
00838 stuck_right_strafe = false;
00839 }
00840
00841
00842 if(!escaping_ && best_traj->cost_ > -2.0){
00843 escape_x_ = x;
00844 escape_y_ = y;
00845 escape_theta_ = theta;
00846 escaping_ = true;
00847 }
00848
00849 dist = sqrt((x - escape_x_) * (x - escape_x_) + (y - escape_y_) * (y - escape_y_));
00850
00851 if(dist > escape_reset_dist_ || fabs(angles::shortest_angular_distance(escape_theta_, theta)) > escape_reset_theta_){
00852 escaping_ = false;
00853 }
00854
00855
00856
00857 if(best_traj->cost_ == -1.0)
00858 best_traj->cost_ = 1.0;
00859
00860 return *best_traj;
00861
00862 }
00863
00864
00865 Trajectory TrajectoryPlanner::findBestPath(tf::Stamped<tf::Pose> global_pose, tf::Stamped<tf::Pose> global_vel,
00866 tf::Stamped<tf::Pose>& drive_velocities){
00867
00868 double yaw = tf::getYaw(global_pose.getRotation());
00869 double vel_yaw = tf::getYaw(global_vel.getRotation());
00870
00871 double x = global_pose.getOrigin().getX();
00872 double y = global_pose.getOrigin().getY();
00873 double theta = yaw;
00874
00875 double vx = global_vel.getOrigin().getX();
00876 double vy = global_vel.getOrigin().getY();
00877 double vtheta = vel_yaw;
00878
00879
00880 map_.resetPathDist();
00881
00882
00883 vector<iri_diff_local_planner::Position2DInt> footprint_list = getFootprintCells(x, y, theta, true);
00884
00885
00886 for(unsigned int i = 0; i < footprint_list.size(); ++i){
00887 map_(footprint_list[i].x, footprint_list[i].y).within_robot = true;
00888 }
00889
00890
00891 map_.setPathCells(costmap_, global_plan_);
00892 ROS_DEBUG("Path/Goal distance computed");
00893
00894
00895 Trajectory best = createTrajectories(x, y, theta,
00896 vx, vy, vtheta,
00897 acc_lim_x_, acc_lim_y_, acc_lim_theta_);
00898 ROS_DEBUG("Trajectories created");
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 if(best.cost_ < 0){
00926 drive_velocities.setIdentity();
00927 }
00928 else{
00929 tf::Vector3 start(best.xv_, best.yv_, 0);
00930 drive_velocities.setOrigin(start);
00931 tf::Matrix3x3 matrix;
00932 matrix.setRotation(tf::createQuaternionFromYaw(best.thetav_));
00933 drive_velocities.setBasis(matrix);
00934 }
00935
00936 return best;
00937 }
00938
00939
00940 double TrajectoryPlanner::footprintCost(double x_i, double y_i, double theta_i){
00941
00942 double cos_th = cos(theta_i);
00943 double sin_th = sin(theta_i);
00944 vector<geometry_msgs::Point> oriented_footprint;
00945 for(unsigned int i = 0; i < footprint_spec_.size(); ++i){
00946 geometry_msgs::Point new_pt;
00947 new_pt.x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
00948 new_pt.y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
00949 oriented_footprint.push_back(new_pt);
00950 }
00951
00952 geometry_msgs::Point robot_position;
00953 robot_position.x = x_i;
00954 robot_position.y = y_i;
00955
00956
00957 double footprint_cost = world_model_.footprintCost(robot_position, oriented_footprint, costmap_.getInscribedRadius(), costmap_.getCircumscribedRadius());
00958
00959 return footprint_cost;
00960 }
00961
00962 void TrajectoryPlanner::getLineCells(int x0, int x1, int y0, int y1, vector<iri_diff_local_planner::Position2DInt>& pts){
00963
00964 int deltax = abs(x1 - x0);
00965 int deltay = abs(y1 - y0);
00966 int x = x0;
00967 int y = y0;
00968
00969 int xinc1, xinc2, yinc1, yinc2;
00970 int den, num, numadd, numpixels;
00971
00972 iri_diff_local_planner::Position2DInt pt;
00973
00974 if (x1 >= x0)
00975 {
00976 xinc1 = 1;
00977 xinc2 = 1;
00978 }
00979 else
00980 {
00981 xinc1 = -1;
00982 xinc2 = -1;
00983 }
00984
00985 if (y1 >= y0)
00986 {
00987 yinc1 = 1;
00988 yinc2 = 1;
00989 }
00990 else
00991 {
00992 yinc1 = -1;
00993 yinc2 = -1;
00994 }
00995
00996 if (deltax >= deltay)
00997 {
00998 xinc1 = 0;
00999 yinc2 = 0;
01000 den = deltax;
01001 num = deltax / 2;
01002 numadd = deltay;
01003 numpixels = deltax;
01004 }
01005 else
01006 {
01007 xinc2 = 0;
01008 yinc1 = 0;
01009 den = deltay;
01010 num = deltay / 2;
01011 numadd = deltax;
01012 numpixels = deltay;
01013 }
01014
01015 for (int curpixel = 0; curpixel <= numpixels; curpixel++)
01016 {
01017 pt.x = x;
01018 pt.y = y;
01019 pts.push_back(pt);
01020
01021 num += numadd;
01022 if (num >= den)
01023 {
01024 num -= den;
01025 x += xinc1;
01026 y += yinc1;
01027 }
01028 x += xinc2;
01029 y += yinc2;
01030 }
01031 }
01032
01033
01034 vector<iri_diff_local_planner::Position2DInt> TrajectoryPlanner::getFootprintCells(double x_i, double y_i, double theta_i, bool fill){
01035 vector<iri_diff_local_planner::Position2DInt> footprint_cells;
01036
01037
01038 if(footprint_spec_.size() <= 1){
01039 unsigned int mx, my;
01040 if(costmap_.worldToMap(x_i, y_i, mx, my)){
01041 Position2DInt center;
01042 center.x = mx;
01043 center.y = my;
01044 footprint_cells.push_back(center);
01045 }
01046 return footprint_cells;
01047 }
01048
01049
01050 double cos_th = cos(theta_i);
01051 double sin_th = sin(theta_i);
01052 double new_x, new_y;
01053 unsigned int x0, y0, x1, y1;
01054 unsigned int last_index = footprint_spec_.size() - 1;
01055
01056 for(unsigned int i = 0; i < last_index; ++i){
01057
01058 new_x = x_i + (footprint_spec_[i].x * cos_th - footprint_spec_[i].y * sin_th);
01059 new_y = y_i + (footprint_spec_[i].x * sin_th + footprint_spec_[i].y * cos_th);
01060 if(!costmap_.worldToMap(new_x, new_y, x0, y0))
01061 return footprint_cells;
01062
01063
01064 new_x = x_i + (footprint_spec_[i + 1].x * cos_th - footprint_spec_[i + 1].y * sin_th);
01065 new_y = y_i + (footprint_spec_[i + 1].x * sin_th + footprint_spec_[i + 1].y * cos_th);
01066 if(!costmap_.worldToMap(new_x, new_y, x1, y1))
01067 return footprint_cells;
01068
01069 getLineCells(x0, x1, y0, y1, footprint_cells);
01070 }
01071
01072
01073 new_x = x_i + (footprint_spec_[last_index].x * cos_th - footprint_spec_[last_index].y * sin_th);
01074 new_y = y_i + (footprint_spec_[last_index].x * sin_th + footprint_spec_[last_index].y * cos_th);
01075 if(!costmap_.worldToMap(new_x, new_y, x0, y0))
01076 return footprint_cells;
01077
01078 new_x = x_i + (footprint_spec_[0].x * cos_th - footprint_spec_[0].y * sin_th);
01079 new_y = y_i + (footprint_spec_[0].x * sin_th + footprint_spec_[0].y * cos_th);
01080 if(!costmap_.worldToMap(new_x, new_y, x1, y1))
01081 return footprint_cells;
01082
01083 getLineCells(x0, x1, y0, y1, footprint_cells);
01084
01085 if(fill)
01086 getFillCells(footprint_cells);
01087
01088 return footprint_cells;
01089 }
01090
01091 void TrajectoryPlanner::getFillCells(vector<iri_diff_local_planner::Position2DInt>& footprint){
01092
01093 iri_diff_local_planner::Position2DInt swap, pt;
01094 unsigned int i = 0;
01095 while(i < footprint.size() - 1){
01096 if(footprint[i].x > footprint[i + 1].x){
01097 swap = footprint[i];
01098 footprint[i] = footprint[i + 1];
01099 footprint[i + 1] = swap;
01100 if(i > 0)
01101 --i;
01102 }
01103 else
01104 ++i;
01105 }
01106
01107 i = 0;
01108 iri_diff_local_planner::Position2DInt min_pt;
01109 iri_diff_local_planner::Position2DInt max_pt;
01110 unsigned int min_x = footprint[0].x;
01111 unsigned int max_x = footprint[footprint.size() -1].x;
01112
01113 for(unsigned int x = min_x; x <= max_x; ++x){
01114 if(i >= footprint.size() - 1)
01115 break;
01116
01117 if(footprint[i].y < footprint[i + 1].y){
01118 min_pt = footprint[i];
01119 max_pt = footprint[i + 1];
01120 }
01121 else{
01122 min_pt = footprint[i + 1];
01123 max_pt = footprint[i];
01124 }
01125
01126 i += 2;
01127 while(i < footprint.size() && footprint[i].x == x){
01128 if(footprint[i].y < min_pt.y)
01129 min_pt = footprint[i];
01130 else if(footprint[i].y > max_pt.y)
01131 max_pt = footprint[i];
01132 ++i;
01133 }
01134
01135
01136 for(unsigned int y = min_pt.y; y < max_pt.y; ++y){
01137 pt.x = x;
01138 pt.y = y;
01139 footprint.push_back(pt);
01140 }
01141 }
01142 }
01143
01144 void TrajectoryPlanner::getLocalGoal(double& x, double& y){
01145 x = map_.goal_x_;
01146 y = map_.goal_y_;
01147 }
01148
01149 };
01150
01151