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
00035 #include <stepback_and_steerturn_recovery/stepback_and_steerturn_recovery.h>
00036 #include <pluginlib/class_list_macros.h>
00037 #include <tf/transform_datatypes.h>
00038
00039
00040 PLUGINLIB_DECLARE_CLASS(stepback_and_steerturn_recovery, StepBackAndSteerTurnRecovery, stepback_and_steerturn_recovery::StepBackAndSteerTurnRecovery,
00041 nav_core::RecoveryBehavior)
00042
00043 namespace stepback_and_steerturn_recovery
00044 {
00045
00046 StepBackAndSteerTurnRecovery::StepBackAndSteerTurnRecovery () :
00047 global_costmap_(NULL), local_costmap_(NULL), tf_(NULL), initialized_(false)
00048 {
00049 TWIST_STOP.linear.x = 0.0;
00050 TWIST_STOP.linear.y = 0.0;
00051 TWIST_STOP.linear.z = 0.0;
00052 TWIST_STOP.angular.x = 0.0;
00053 TWIST_STOP.angular.y = 0.0;
00054 TWIST_STOP.angular.z = 0.0;
00055 }
00056
00057 StepBackAndSteerTurnRecovery::~StepBackAndSteerTurnRecovery ()
00058 {
00059 delete world_model_;
00060 }
00061
00062 void StepBackAndSteerTurnRecovery::initialize (std::string name, tf::TransformListener* tf,
00063 cmap::Costmap2DROS* global_cmap, cmap::Costmap2DROS* local_cmap)
00064 {
00065 ROS_ASSERT(!initialized_);
00066 name_ = name;
00067 tf_ = tf;
00068 local_costmap_ = local_cmap;
00069 global_costmap_ = global_cmap;
00070
00071
00072
00073
00074 world_model_ = new base_local_planner::CostmapModel(*local_costmap_->getCostmap());
00075
00076 cmd_vel_pub_ = nh_.advertise<gm::Twist>("cmd_vel", 10);
00077 recover_run_pub_ = nh_.advertise<std_msgs::Bool>("recover_run", 10);
00078 ros::NodeHandle private_nh("~/" + name);
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 private_nh.param("duration", duration_, 1.0);
00094 private_nh.param("linear_speed_limit", linear_speed_limit_, 0.3);
00095 private_nh.param("angular_speed_limit", angular_speed_limit_, 1.0);
00096 private_nh.param("linear_acceleration_limit", linear_acceleration_limit_, 4.0);
00097 private_nh.param("angular_acceleration_limit", angular_acceleration_limit_, 3.2);
00098 private_nh.param("controller_frequency", controller_frequency_, 20.0);
00099 private_nh.param("simulation_frequency", simulation_frequency_, 5.0);
00100 private_nh.param("simulation_inc", simulation_inc_, 1/simulation_frequency_);
00101
00102 private_nh.param("only_single_steering", only_single_steering_, true);
00103 private_nh.param("trial_times", trial_times_, 5);
00104 private_nh.param("obstacle_patience", obstacle_patience_, 0.5);
00105 private_nh.param("obstacle_check_frequency", obstacle_check_frequency_, 5.0);
00106 private_nh.param("sim_angle_resolution", sim_angle_resolution_, 0.1);
00107
00108
00109 private_nh.param("linear_vel_back", linear_vel_back_, -0.3);
00110 private_nh.param("step_back_length", step_back_length_, 1.0);
00111 private_nh.param("step_back_timeout", step_back_timeout_, 15.0);
00112
00113 private_nh.param("linear_vel_steer", linear_vel_steer_, 0.3);
00114 private_nh.param("angular_speed_steer", angular_speed_steer_, 0.5);
00115 private_nh.param("turn_angle", turn_angle_, 2.0);
00116 private_nh.param("steering_timeout", steering_timeout_, 15.0);
00117
00118 private_nh.param("linear_vel_forward", linear_vel_forward_, 0.3);
00119 private_nh.param("step_forward_length", step_forward_length_, 0.5);
00120 private_nh.param("step_forward_timeout", step_forward_timeout_, 15.0);
00121
00122
00123
00124
00125
00126
00127 ROS_INFO_NAMED ("top", "Initialized with only_single_steering = %s", (only_single_steering_ ? "true" : "false"));
00128 ROS_INFO_NAMED ("top", "Initialized with recovery_trial_times = %d", trial_times_);
00129 ROS_INFO_NAMED ("top", "Initialized with obstacle_patience = %.2f", obstacle_patience_);
00130 ROS_INFO_NAMED ("top", "Initialized with obstacle_check_frequency = %.2f", obstacle_check_frequency_);
00131 ROS_INFO_NAMED ("top", "Initialized with simulation_frequency = %.2f", simulation_frequency_);
00132 ROS_INFO_NAMED ("top", "Initialized with sim_angle_resolution = %.2f", sim_angle_resolution_);
00133 ROS_INFO_NAMED ("top", "Initialized with linear_vel_back = %.2f, step_back_length = %.2f, step_back_steering = %.2f",
00134 linear_vel_back_, step_back_length_, step_back_timeout_);
00135 ROS_INFO_NAMED ("top", "Initialized with linear_vel_steer = %.2f, angular_speed_steer = %.2f,"
00136 " turn_angle = %.2f, steering_timeout = %.2f",
00137 linear_vel_steer_, angular_speed_steer_, turn_angle_, steering_timeout_);
00138 ROS_INFO_NAMED ("top", "Initialized with linear_vel_forward = %.2f, step_forward_length = %.2f, step_forward_timeout = %.2f",
00139 linear_vel_forward_, step_forward_length_, step_forward_timeout_);
00140
00141 initialized_ = true;
00142 }
00143
00144 gm::Twist scaleTwist (const gm::Twist& twist, const double scale)
00145 {
00146 gm::Twist t;
00147 t.linear.x = twist.linear.x * scale;
00148 t.linear.y = twist.linear.y * scale;
00149 t.angular.z = twist.angular.z * scale;
00150 return t;
00151 }
00152
00153 gm::Pose2D forwardSimulate (const gm::Pose2D& p, const gm::Twist& twist, const double t=1.0)
00154 {
00155 gm::Pose2D p2;
00156 const double linear_vel = twist.linear.x;
00157 p2.theta = p.theta + twist.angular.z;
00158 p2.x = p.x + linear_vel * cos(p2.theta)*t;
00159 p2.y = p.y + linear_vel * sin(p2.theta)*t;
00160
00161 return p2;
00162 }
00163
00165 double StepBackAndSteerTurnRecovery::normalizedPoseCost (const gm::Pose2D& pose) const
00166 {
00167 gm::Point p;
00168 p.x = pose.x;
00169 p.y = pose.y;
00170
00171 unsigned int pose_map_idx_x, pose_map_idx_y;
00172 costmap_2d::Costmap2D* costmap = local_costmap_->getCostmap();
00173 costmap->worldToMap(p.x, p.y, pose_map_idx_x, pose_map_idx_y);
00174 ROS_DEBUG_NAMED ("top", "Trying to get cost at (%d, %d) in getCost", pose_map_idx_x, pose_map_idx_y);
00175 const double c = costmap->getCost(pose_map_idx_x, pose_map_idx_y);
00176
00177 return c < 0 ? 1e9 : c;
00178 }
00179
00180
00185 gm::Pose2D StepBackAndSteerTurnRecovery::getPoseToObstacle (const gm::Pose2D& current, const gm::Twist& twist) const
00186 {
00187 double cost = 0;
00188 cost = normalizedPoseCost(current);
00189 double t;
00190 gm::Pose2D current_tmp = current;
00191 double next_cost;
00192
00193 ROS_DEBUG_NAMED ("top", " ");
00194 for (t=simulation_inc_; t<=duration_ + 500; t+=simulation_inc_) {
00195 ROS_DEBUG_NAMED ("top", "start loop");
00196 current_tmp = forwardSimulate(current, twist, t);
00197 ROS_DEBUG_NAMED ("top", "finish fowardSimulate");
00198 next_cost = normalizedPoseCost(current_tmp);
00199 ROS_DEBUG_NAMED ("top", "finish Cost");
00200
00201 if ( next_cost == costmap_2d::LETHAL_OBSTACLE) {
00202 ROS_DEBUG_STREAM_NAMED ("cost", "Cost at " << t << " and pose " << forwardSimulate(current, twist, t)
00203 << " is " << next_cost << " which is greater than previous cost " << cost);
00204 break;
00205 }
00206 cost = next_cost;
00207 }
00208 ROS_DEBUG_NAMED ("top", "cost = %.2f, next_cost = %.2f", cost, next_cost);
00209 ROS_DEBUG_NAMED ("top", "twist.linear.x = %.2f, twist.angular.z = %.2f", twist.linear.x, twist.angular.z);
00210 ROS_DEBUG_NAMED ("top", "init = (%.2f, %.2f, %.2f), current = (%.2f, %.2f, %.2f)",
00211 current.x, current.y, current.theta, current_tmp.x, current_tmp.y, current_tmp.theta);
00212 ROS_DEBUG_NAMED ("top", "time = %.2f", t);
00213
00214
00215 return current_tmp;
00216 }
00217
00218 double linearSpeed (const gm::Twist& twist)
00219 {
00220 return sqrt(twist.linear.x*twist.linear.x + twist.linear.y*twist.linear.y);
00221 }
00222
00223 double angularSpeed (const gm::Twist& twist)
00224 {
00225 return fabs(twist.angular.z);
00226 }
00227
00228
00229 gm::Twist StepBackAndSteerTurnRecovery::scaleGivenAccelerationLimits (const gm::Twist& twist, const double time_remaining) const
00230 {
00231 const double linear_speed = linearSpeed(twist);
00232 const double angular_speed = angularSpeed(twist);
00233 const double linear_acc_scaling = linear_speed/(time_remaining*linear_acceleration_limit_);
00234 const double angular_acc_scaling = angular_speed/(time_remaining*angular_acceleration_limit_);
00235 const double acc_scaling = max(linear_acc_scaling, angular_acc_scaling);
00236 const double linear_vel_scaling = linear_speed/linear_speed_limit_;
00237 const double angular_vel_scaling = angular_speed/angular_speed_limit_;
00238 const double vel_scaling = max(linear_vel_scaling, angular_vel_scaling);
00239 return scaleTwist(twist, max(1.0, max(acc_scaling, vel_scaling)));
00240 }
00241
00242
00243 gm::Pose2D StepBackAndSteerTurnRecovery::getCurrentLocalPose () const
00244 {
00245 tf::Stamped<tf::Pose> p;
00246 local_costmap_->getRobotPose(p);
00247 gm::Pose2D pose;
00248 pose.x = p.getOrigin().x();
00249 pose.y = p.getOrigin().y();
00250 pose.theta = tf::getYaw(p.getRotation());
00251 return pose;
00252 }
00253
00254 void StepBackAndSteerTurnRecovery::moveSpacifiedLength (const gm::Twist twist, const double distination, const COSTMAP_SEARCH_MODE mode) const
00255 {
00256 double distination_cmd = distination;
00257 double min_dist_to_obstacle = getMinimalDistanceToObstacle(mode);
00258
00259 std::string mode_name;
00260 double time_out;
00261
00262 switch (mode) {
00263 case FORWARD:
00264 mode_name = "FORWARD";
00265 time_out = step_forward_timeout_;
00266 if (min_dist_to_obstacle < distination)
00267 {
00268 distination_cmd = min_dist_to_obstacle - obstacle_patience_;
00269
00270 ROS_WARN_NAMED ("top", "obstacle detected before moving %s", mode_name.c_str());
00271 ROS_WARN_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist_to_obstacle, mode_name.c_str());
00272 ROS_WARN_NAMED ("top", "moving length is switched from %.2f [m] to %.2f in %s", distination, distination_cmd,mode_name.c_str());
00273 }
00274 break;
00275 case FORWARD_LEFT:
00276 mode_name = "FORWARD_LEFT";
00277 time_out = steering_timeout_;
00278 if (min_dist_to_obstacle < obstacle_patience_)
00279 {
00280 distination_cmd = 0.0;
00281
00282 ROS_WARN_NAMED ("top", "obstacle detected before moving %s", mode_name.c_str());
00283 ROS_WARN_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist_to_obstacle, mode_name.c_str());
00284 ROS_WARN_NAMED ("top", "stop turning because an obstacle is too close in %s", mode_name.c_str());
00285 }
00286 break;
00287 case FORWARD_RIGHT:
00288 mode_name = "FORWARD_RIGHT";
00289 time_out = steering_timeout_;
00290 if (min_dist_to_obstacle < obstacle_patience_)
00291 {
00292 distination_cmd = 0.0;
00293
00294 ROS_WARN_NAMED ("top", "obstacle detected before moving %s", mode_name.c_str());
00295 ROS_WARN_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist_to_obstacle, mode_name.c_str());
00296 ROS_WARN_NAMED ("top", "stop turning because an obstacle is too close in %s", mode_name.c_str());
00297 }
00298 break;
00299 case BACKWARD:
00300 mode_name = "BACKWARD";
00301 time_out = step_back_timeout_;
00302 if (min_dist_to_obstacle < distination)
00303 {
00304 distination_cmd = min_dist_to_obstacle - 2 * obstacle_patience_;
00305
00306 ROS_WARN_NAMED ("top", "obstacle detected before moving %s", mode_name.c_str());
00307 ROS_WARN_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist_to_obstacle, mode_name.c_str());
00308 ROS_WARN_NAMED ("top", "moving length is switched from %.2f [m] to %.2f in %s", distination, distination_cmd, mode_name.c_str());
00309 }
00310 break;
00311 default:
00312 break;
00313 }
00314
00315 const double frequency = 5.0;
00316 ros::Rate r(frequency);
00317
00318 const gm::Pose2D initialPose = getCurrentLocalPose();
00319
00320 int log_cnt = 0;
00321 int log_frequency = (int)obstacle_check_frequency_;
00322
00323 ros::Time time_begin = ros::Time::now();
00324 while (double dist_diff = getCurrentDistDiff(initialPose, distination_cmd, mode) > 0.01)
00325 {
00326 double remaining_time = dist_diff / base_frame_twist_.linear.x;
00327 double min_dist = getMinimalDistanceToObstacle(mode);
00328
00329
00330 if(time_out > 0.0 &&
00331 time_begin + ros::Duration(time_out) < ros::Time::now())
00332 {
00333
00334 cmd_vel_pub_.publish(TWIST_STOP);
00335 ROS_WARN_NAMED ("top", "time out at %s", mode_name.c_str());
00336 ROS_WARN_NAMED ("top", "%.2f [sec] elapsed.", time_out);
00337 break;
00338 }
00339
00340
00341 if(min_dist < obstacle_patience_)
00342 {
00343
00344 cmd_vel_pub_.publish(TWIST_STOP);
00345 ROS_WARN_NAMED ("top", "obstacle detected at %s", mode_name.c_str());
00346 ROS_WARN_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist, mode_name.c_str());
00347 break;
00348 }
00349
00350
00351 cmd_vel_pub_.publish(twist);
00352 if(log_cnt++ % log_frequency == 0)
00353 {
00354 ROS_DEBUG_NAMED ("top", "no obstacle around");
00355 ROS_INFO_NAMED ("top", "min dist to obstacle = %.2f [m] in %s", min_dist, mode_name.c_str());
00356 }
00357
00358 ros::spinOnce();
00359 r.sleep();
00360 }
00361
00362 return;
00363 }
00364
00365 double StepBackAndSteerTurnRecovery::getCurrentDiff(const gm::Pose2D initialPose, const COSTMAP_SEARCH_MODE mode) const
00366 {
00367
00368 const gm::Pose2D& currentPose = getCurrentLocalPose();
00369 ROS_DEBUG_NAMED ("top", "current pose (%.2f, %.2f, %.2f)", currentPose.x,
00370 currentPose.y, currentPose.theta);
00371
00372 double current_diff;
00373
00374 switch (mode) {
00375 case FORWARD:
00376 case BACKWARD:
00377 current_diff = getDistBetweenTwoPoints(currentPose, initialPose);
00378 ROS_DEBUG_NAMED ("top", "current_diff in translation = %.2f", current_diff);
00379 break;
00380 case FORWARD_LEFT:
00381 case FORWARD_RIGHT:
00382 current_diff = initialPose.theta - currentPose.theta;
00383 current_diff = fabs(current_diff);
00384 ROS_DEBUG_NAMED ("top", "initialPose.Theta = %.2f, currentPose.theta = %.2f", initialPose.theta, currentPose.theta);
00385 ROS_DEBUG_NAMED ("top", "current_diff in angle = %.2f", current_diff);
00386 default:
00387 break;
00388 }
00389
00390 return current_diff;
00391 }
00392
00393 double StepBackAndSteerTurnRecovery::getCurrentDistDiff(const gm::Pose2D initialPose, const double distination, COSTMAP_SEARCH_MODE mode) const
00394 {
00395 const double dist_diff = distination - getCurrentDiff(initialPose, mode);
00396 ROS_DEBUG_NAMED ("top", "dist_diff = %.2f", dist_diff);
00397
00398 return dist_diff;
00399 }
00400
00401 double StepBackAndSteerTurnRecovery::getMinimalDistanceToObstacle(const COSTMAP_SEARCH_MODE mode) const
00402 {
00403 double max_angle, min_angle;
00404 gm::Twist twist = TWIST_STOP;
00405
00406 switch (mode) {
00407 case FORWARD:
00408 twist.linear.x = linear_vel_forward_;
00409 max_angle = M_PI/3.0;
00410 min_angle = -M_PI/3.0;
00411 break;
00412 case FORWARD_LEFT:
00413 twist.linear.x = linear_vel_forward_;
00414 max_angle = M_PI/2.0;
00415 min_angle = 0.0;
00416 break;
00417 case FORWARD_RIGHT:
00418 twist.linear.x = linear_vel_forward_;
00419 max_angle = 0.0;
00420 min_angle = -M_PI/2.0;
00421 break;
00422 case BACKWARD:
00423 twist.linear.x = linear_vel_back_;
00424 max_angle = M_PI/3.0;
00425 min_angle = -M_PI/3.0;
00426 break;
00427 default:
00428 break;
00429 }
00430
00431 const gm::Pose2D& current = getCurrentLocalPose();
00432 double min_dist = INFINITY;
00433
00434 for(double angle = min_angle; angle < max_angle; angle+=sim_angle_resolution_)
00435 {
00436 twist.angular.z = angle;
00437 gm::Pose2D pose_to_obstacle = getPoseToObstacle(current, twist);
00438 double dist_to_obstacle = getDistBetweenTwoPoints(current, pose_to_obstacle);
00439
00440 if(dist_to_obstacle < min_dist)
00441 min_dist = dist_to_obstacle;
00442 }
00443
00444 ROS_DEBUG_NAMED ("top", "min_dist = %.2f", min_dist);
00445
00446 return min_dist;
00447 }
00448
00449 int StepBackAndSteerTurnRecovery::determineTurnDirection()
00450 {
00451
00452 const gm::Pose2D& current = getCurrentLocalPose();
00453
00454 gm::Twist twist = TWIST_STOP;
00455 twist.linear.x = linear_vel_forward_;
00456
00457 vector<double> dist_to_obstacle_r;
00458 vector<double> dist_to_obstacle_l;
00459 double max = M_PI/2.0;
00460 double min = - max;
00461 for(double angle = min; angle < max; angle+=sim_angle_resolution_)
00462 {
00463 twist.angular.z = angle;
00464 gm::Pose2D pose_to_obstacle = getPoseToObstacle(current, twist);
00465 double dist_to_obstacle = getDistBetweenTwoPoints(current, pose_to_obstacle);
00466
00467 ROS_DEBUG_NAMED ("top", "(%.2f, %.2f, %.2f) for %.2f [m] to obstacle",
00468 twist.linear.x, twist.linear.y, twist.angular.z, dist_to_obstacle);
00469
00470 if(angle > 0.0)
00471 dist_to_obstacle_l.push_back(dist_to_obstacle);
00472 else if(angle < 0.0)
00473 dist_to_obstacle_r.push_back(dist_to_obstacle);
00474 else
00475 ;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 double min_l = *min_element(dist_to_obstacle_l.begin(), dist_to_obstacle_l.end());
00496 double min_r = *min_element(dist_to_obstacle_r.begin(), dist_to_obstacle_r.end());
00497 ROS_INFO_NAMED ("top", "min_l = %.2f [m], min_r = %.2f [m]", min_l, min_r);
00498
00499 int ret_val;
00500
00501 if(min_l < min_r)
00502 ret_val = RIGHT;
00503 else
00504 ret_val = LEFT;
00505
00506 return ret_val;
00507 }
00508
00509 double StepBackAndSteerTurnRecovery::getDistBetweenTwoPoints(const gm::Pose2D pose1, const gm::Pose2D pose2) const
00510 {
00511 double dist_to_obstacle = (pose1.x - pose2.x) * (pose1.x - pose2.x) +
00512 (pose1.y - pose2.y) * (pose1.y - pose2.y);
00513 return sqrt(dist_to_obstacle);
00514 }
00515
00516 void StepBackAndSteerTurnRecovery::runBehavior ()
00517 {
00518 ROS_ASSERT (initialized_);
00519
00520 ROS_INFO_NAMED ("top", "*****************************************************");
00521 ROS_INFO_NAMED ("top", "********Start StepBackAndSteerTurnRecovery!!!********");
00522 ROS_INFO_NAMED ("top", "*****************************************************");
00523
00524 std_msgs::Bool run_state;
00525
00526
00527 run_state.data = true;
00528 recover_run_pub_.publish(run_state);
00529
00530 int cnt = 0;
00531 const double stop_duaration = 1.0;
00532 while(true)
00533 {
00534 cnt++;
00535 ROS_INFO_NAMED ("top", "==== %d th recovery trial ====", cnt);
00536
00537
00538 const gm::Pose2D& initialPose = getCurrentLocalPose();
00539
00540
00541 ROS_DEBUG_NAMED ("top", "initial pose (%.2f, %.2f, %.2f)", initialPose.x,
00542 initialPose.y, initialPose.theta);
00543 ros::Rate r(controller_frequency_);
00544
00545
00546 base_frame_twist_.linear.x = linear_vel_back_;
00547 ROS_INFO_NAMED ("top", "attempting step back");
00548 moveSpacifiedLength(base_frame_twist_, step_back_length_, BACKWARD);
00549 ROS_INFO_NAMED ("top", "complete step back");
00550
00551 double final_diff = getCurrentDiff(initialPose);
00552 ROS_DEBUG_NAMED ("top", "final_diff = %.2f",final_diff);
00553
00554
00555 for (double t=0; t<stop_duaration; t+=1/controller_frequency_) {
00556 cmd_vel_pub_.publish(TWIST_STOP);
00557 r.sleep();
00558 }
00559
00560 int turn_dir = determineTurnDirection();
00561 int costmap_search_mode[CNT_TURN];
00562
00563 double z;
00564 if(turn_dir == LEFT)
00565 {
00566 z = angular_speed_steer_;
00567 costmap_search_mode[FIRST_TURN] = FORWARD_LEFT;
00568 costmap_search_mode[SECOND_TURN] = FORWARD_RIGHT;
00569 ROS_INFO_NAMED ("top", "attempting to turn left at the 1st turn");
00570 }
00571 else
00572 {
00573 z = -1 * angular_speed_steer_;
00574 costmap_search_mode[FIRST_TURN] = FORWARD_RIGHT;
00575 costmap_search_mode[SECOND_TURN] = FORWARD_LEFT;
00576 ROS_INFO_NAMED ("top", "attemping to turn right at the 1st turn");
00577 }
00578
00579
00580
00581 gm::Twist twist;
00582 twist = TWIST_STOP;
00583 twist.linear.x = linear_vel_steer_;
00584 twist.angular.z = z;
00585 moveSpacifiedLength(twist, turn_angle_, (COSTMAP_SEARCH_MODE)costmap_search_mode[FIRST_TURN]);
00586 ROS_INFO_NAMED ("top", "complete the 1st turn");
00587
00588 if(!only_single_steering_) {
00589
00590 ROS_INFO_NAMED ("top", "attemping step forward");
00591 twist = TWIST_STOP;
00592 twist.linear.x = linear_vel_forward_;
00593 moveSpacifiedLength(twist, step_forward_length_, FORWARD);
00594 ROS_INFO_NAMED ("top", "complete step forward");
00595
00596
00597 ROS_INFO_NAMED ("top", "attempting second turn");
00598 twist = TWIST_STOP;
00599 twist.linear.x = linear_vel_steer_;
00600 twist.angular.z = -z;
00601 moveSpacifiedLength(twist, turn_angle_, (COSTMAP_SEARCH_MODE)costmap_search_mode[SECOND_TURN]);
00602 ROS_INFO_NAMED ("top", "complete second turn");
00603 }
00604
00605
00606 for (double t=0; t<stop_duaration; t+=1/controller_frequency_) {
00607 cmd_vel_pub_.publish(TWIST_STOP);
00608 r.sleep();
00609 }
00610
00611
00612 if(cnt == trial_times_)
00613 {
00614 ROS_INFO_NAMED ("top", "break after %d times recovery", cnt);
00615 break;
00616 }
00617
00618
00619 const gm::Pose2D& current = getCurrentLocalPose();
00620 double max_angle = 0.1;
00621 double min_angle = -max_angle;
00622 double max_clearance = 0;
00623 twist.linear.x = 3.0;
00624 for(double angle = min_angle; angle < max_angle; angle+=sim_angle_resolution_)
00625 {
00626 twist.angular.z = angle;
00627 gm::Pose2D pose_to_obstacle = getPoseToObstacle(current, twist);
00628 double dist_to_obstacle = getDistBetweenTwoPoints(current, pose_to_obstacle);
00629
00630 if(dist_to_obstacle > max_clearance)
00631 max_clearance = dist_to_obstacle;
00632 }
00633
00634 if(max_clearance < 3.0)
00635 {
00636 ROS_INFO_NAMED ("top", "continue recovery because the robot couldn't get clearance");
00637 ROS_DEBUG_NAMED ("top", "continue at (%.2f, %.2f, %.2f) for max_clearance %.2f m",
00638 twist.linear.x, twist.linear.y, twist.angular.z, max_clearance);
00639 continue;
00640 }
00641 else
00642 {
00643 ROS_INFO_NAMED ("top", "break recovery because the robot got clearance");
00644 ROS_DEBUG_NAMED ("top", "break at (%.2f, %.2f, %.2f) for max_clearance %.2f m",
00645 twist.linear.x, twist.linear.y, twist.angular.z, max_clearance);
00646 break;
00647 }
00648 }
00649
00650
00651 run_state.data = false;
00652 recover_run_pub_.publish(run_state);
00653
00654 ROS_INFO_NAMED ("top", "*****************************************************");
00655 ROS_INFO_NAMED ("top", "********Finish StepBackAndSteerTurnRecovery!!********");
00656 ROS_INFO_NAMED ("top", "*****************************************************");
00657
00658 }
00659
00660
00661 }