Go to the documentation of this file.00001 #include <force_rotate_recovery/force_rotate_recovery.h>
00002 #include <pluginlib/class_list_macros.h>
00003
00004 PLUGINLIB_EXPORT_CLASS(force_rotate_recovery::ForceRotateRecovery, nav_core::RecoveryBehavior);
00005
00006 namespace force_rotate_recovery {
00007 ForceRotateRecovery::ForceRotateRecovery() :
00008 global_costmap_(NULL),
00009 local_costmap_(NULL),
00010 initialized_(false),
00011 world_model_(NULL)
00012 {
00013
00014 }
00015
00016 void ForceRotateRecovery::initialize(std::string name, tf::TransformListener* tf,
00017 costmap_2d::Costmap2DROS* global_costmap, costmap_2d::Costmap2DROS* local_costmap){
00018 if(!initialized_){
00019 name_ = name;
00020 global_costmap_ = global_costmap;
00021 local_costmap_ = local_costmap;
00022
00023
00024 ros::NodeHandle private_nh("~/" + name_);
00025 ros::NodeHandle blp_nh("~/TrajectoryPlannerROS");
00026
00027
00028 private_nh.param("sim_granularity", sim_granularity_, 0.017);
00029 private_nh.param("frequency", frequency_, 20.0);
00030
00031 blp_nh.param("acc_lim_th", acc_lim_th_, 3.2);
00032 blp_nh.param("max_rotational_vel", max_rotational_vel_, 1.0);
00033 blp_nh.param("min_in_place_rotational_vel", min_rotational_vel_, 0.4);
00034 blp_nh.param("yaw_goal_tolerance", tolerance_, 0.10);
00035
00036 world_model_ = new base_local_planner::CostmapModel(*local_costmap_->getCostmap());
00037
00038 initialized_ = true;
00039 }else{
00040 ROS_ERROR("You should not call initialize twice on this object, doing nothing");
00041 }
00042 }
00043
00044 void ForceRotateRecovery::runBehavior(){
00045 if(!initialized_){
00046 ROS_ERROR("This object must be initialized before runBehavior is called");
00047 return;
00048 }
00049
00050 if(global_costmap_ == NULL || local_costmap_ == NULL){
00051 ROS_ERROR("The costmaps passed to the ForceRotateRecovery object cannot be NULL. Doing nothing.");
00052 return;
00053 }
00054
00055 ROS_WARN("rotate recovery behavior -f started.");
00056
00057 ros::Rate r(frequency_);
00058 ros::NodeHandle n;
00059 ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 10);
00060
00061 tf::Stamped<tf::Pose> global_pose;
00062 local_costmap_->getRobotPose(global_pose);
00063
00064 double current_angle = -1.0 * M_PI;
00065
00066 bool got_180 = false;
00067
00068 double start_offset = 0 - angles::normalize_angle(tf::getYaw(global_pose.getRotation()));
00069 while(n.ok()){
00070 local_costmap_->getRobotPose(global_pose);
00071
00072 double norm_angle = angles::normalize_angle(tf::getYaw(global_pose.getRotation()));
00073 current_angle = angles::normalize_angle(norm_angle + start_offset);
00074
00075
00076 double dist_left = 4 * M_PI - current_angle;
00077
00078 double x = global_pose.getOrigin().x(), y = global_pose.getOrigin().y();
00079
00080
00081 double sim_angle = 0.0;
00082 while(sim_angle < dist_left){
00083 double theta = tf::getYaw(global_pose.getRotation()) + sim_angle;
00084
00085 double footprint_cost = world_model_->footprintCost(x, y, theta, local_costmap_->getRobotFootprint(), 0.0, 0.0);
00086 if(footprint_cost < 0.0){
00087 ROS_WARN("Rotate recovery can't rotate in place because there is a potential collision. Cost: %.2f", footprint_cost);
00088 }
00089
00090 sim_angle += sim_granularity_;
00091 }
00092
00093 double vel = sqrt(2 * acc_lim_th_ * dist_left);
00094
00095 vel = std::min(std::max(vel, min_rotational_vel_), max_rotational_vel_);
00096
00097 geometry_msgs::Twist cmd_vel;
00098 cmd_vel.linear.x = 0.0;
00099 cmd_vel.linear.y = 0.0;
00100 cmd_vel.angular.z = vel;
00101
00102 vel_pub.publish(cmd_vel);
00103
00104 if(current_angle < 0.0)
00105 got_180 = true;
00106
00107 if(got_180 && current_angle >= (0.0 - tolerance_))
00108 return;
00109
00110 r.sleep();
00111 }
00112 }
00113 };
00114