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 #include <pluginlib/class_list_macros.h>
00032 #include <base_local_planner/goal_functions.h>
00033
00034 #include "collvoid_local_planner/collvoid_local_planner.h"
00035
00036 using namespace std;
00037 using namespace costmap_2d;
00038
00039
00040 PLUGINLIB_DECLARE_CLASS(collvoid_local_planner, CollvoidLocalPlanner, collvoid_local_planner::CollvoidLocalPlanner, nav_core::BaseLocalPlanner)
00041
00042
00043 template <typename T>
00044 void getParam (const ros::NodeHandle nh, const string& name, T* place)
00045 {
00046 bool found = nh.getParam(name, *place);
00047 ROS_ASSERT_MSG (found, "Could not find parameter %s", name.c_str());
00048 ROS_DEBUG_STREAM_NAMED ("init", "Initialized " << name << " to " << *place);
00049 }
00050
00051
00052 template <class T>
00053 T getParamDef (const ros::NodeHandle nh, const string& name, const T& default_val)
00054 {
00055 T val;
00056 nh.param(name, val, default_val);
00057 ROS_DEBUG_STREAM_NAMED ("init", "Initialized " << name << " to " << val <<
00058 "(default was " << default_val << ")");
00059 return val;
00060 }
00061
00062 namespace collvoid_local_planner {
00063
00064 CollvoidLocalPlanner::CollvoidLocalPlanner():
00065 costmap_ros_(NULL), tf_(NULL), initialized_(false){
00066 }
00067
00068 CollvoidLocalPlanner::CollvoidLocalPlanner(std::string name, tf::TransformListener* tf, Costmap2DROS* costmap_ros):
00069 costmap_ros_(NULL), tf_(NULL), initialized_(false){
00070
00071
00072 initialize(name, tf, costmap_ros);
00073 }
00074
00075 CollvoidLocalPlanner::~CollvoidLocalPlanner() {
00076 }
00077
00078
00079 void CollvoidLocalPlanner::initialize(std::string name, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros){
00080 if (!initialized_){
00081 tf_ = tf;
00082 costmap_ros_ = costmap_ros;
00083
00084 rot_stopped_velocity_ = 1e-2;
00085 trans_stopped_velocity_ = 1e-2;
00086
00087 current_waypoint_ = 0;
00088
00089 ros::NodeHandle private_nh("~/" + name);
00090
00091
00092
00093 yaw_goal_tolerance_ = getParamDef(private_nh,"yaw_goal_tolerance", 0.05);
00094 xy_goal_tolerance_ = getParamDef(private_nh,"xy_goal_tolerance", 0.10);
00095 latch_xy_goal_tolerance_ = getParamDef(private_nh,"latch_xy_goal_tolerance", false);
00096 ignore_goal_yaw_ = getParamDef(private_nh, "ignore_goal_jaw", false);
00097
00098
00099 ros::NodeHandle nh;
00100
00101
00102
00103 std::string my_id = nh.getNamespace();
00104 if (strcmp(my_id.c_str(), "/") == 0) {
00105 char hostname[1024];
00106 hostname[1023] = '\0';
00107 gethostname(hostname,1023);
00108 my_id = std::string(hostname);
00109 }
00110 my_id = getParamDef<std::string>(private_nh,"name",my_id);
00111 ROS_INFO("My name is: %s",my_id.c_str());
00112
00113
00114
00115 me_.reset(new ROSAgent());
00116
00117
00118 getParam(private_nh,"acc_lim_x", &acc_lim_x_ );
00119 getParam(private_nh,"acc_lim_y", &acc_lim_y_ );
00120 getParam(private_nh,"acc_lim_th", &acc_lim_th_ );
00121
00122 me_->setAccelerationConstraints(acc_lim_x_, acc_lim_y_, acc_lim_th_);
00123
00124
00125 getParam(private_nh, "holo_robot",&holo_robot_);
00126 me_->setIsHoloRobot(holo_robot_);
00127
00128 if (!holo_robot_)
00129 getParam(private_nh,"wheel_base", &wheel_base_);
00130 else
00131 wheel_base_ = 0.0;
00132 me_->setWheelBase(wheel_base_);
00133
00134
00135
00136 getParam(private_nh,"max_vel_with_obstacles", &max_vel_with_obstacles_);
00137 me_->setMaxVelWithObstacles(max_vel_with_obstacles_);
00138
00139 getParam(private_nh,"max_vel_x", &max_vel_x_);
00140 getParam(private_nh,"min_vel_x", &min_vel_x_);
00141 getParam(private_nh,"max_vel_y", &max_vel_y_);
00142 getParam(private_nh,"min_vel_y", &min_vel_y_);
00143 getParam(private_nh,"max_vel_th", &max_vel_th_);
00144 getParam(private_nh,"min_vel_th", &min_vel_th_);
00145 getParam(private_nh,"min_vel_th_inplace", &min_vel_th_inplace_);
00146
00147 me_->setMinMaxSpeeds(min_vel_x_, max_vel_x_, min_vel_y_, max_vel_y_, min_vel_th_, max_vel_th_, min_vel_th_inplace_);
00148
00149
00150 getParam(private_nh,"footprint_radius",&radius_);
00151 me_->setFootprintRadius(radius_);
00152
00153
00154 robot_base_frame_ = costmap_ros_->getBaseFrameID();
00155 global_frame_ = getParamDef<std::string>(private_nh,"global_frame", "/map");
00156 me_->setGlobalFrame(global_frame_);
00157 me_->setRobotBaseFrame(robot_base_frame_);
00158
00159
00160 std::string controller_frequency_param_name;
00161 if(!private_nh.searchParam("controller_frequency", controller_frequency_param_name))
00162 sim_period_ = 0.05;
00163 else
00164 {
00165 double controller_frequency = 0;
00166 private_nh.param(controller_frequency_param_name, controller_frequency, 20.0);
00167 if(controller_frequency > 0)
00168 sim_period_ = 1.0 / controller_frequency;
00169 else
00170 {
00171 ROS_WARN("A controller_frequency less than 0 has been set. Ignoring the parameter, assuming a rate of 20Hz");
00172 sim_period_ = 0.05;
00173 }
00174 }
00175 ROS_INFO("Sim period is set to %.2f", sim_period_);
00176 me_->setSimPeriod(sim_period_);
00177
00178
00179
00180
00181 time_horizon_obst_ = getParamDef(private_nh,"time_horizon_obst",10.0);
00182 time_to_holo_ = getParamDef(private_nh,"time_to_holo", 0.4);
00183 min_error_holo_ = getParamDef(private_nh,"min_error_holo", 0.01);
00184 max_error_holo_ = getParamDef(private_nh, "max_error_holo", 0.15);
00185 delete_observations_ = getParamDef(private_nh, "delete_observations", true);
00186 threshold_last_seen_ = getParamDef(private_nh,"threshold_last_seen",1.0);
00187 eps_= getParamDef(private_nh, "eps", 0.1);
00188
00189 bool orca, convex, clearpath, use_truncation;
00190 int num_samples, type_vo;
00191 getParam(private_nh, "orca", &orca);
00192 getParam(private_nh, "convex", &convex);
00193 getParam(private_nh, "clearpath", &clearpath);
00194 getParam(private_nh, "use_truncation", &use_truncation);
00195
00196 num_samples = getParamDef(private_nh, "num_samples", 400);
00197 type_vo = getParamDef(private_nh, "type_vo", 0);
00198
00199
00200 me_->setTimeHorizonObst(time_horizon_obst_);
00201 me_->setTimeToHolo(time_to_holo_);
00202 me_->setMinMaxErrorHolo(min_error_holo_, max_error_holo_);
00203 me_->setDeleteObservations(delete_observations_);
00204 me_->setThresholdLastSeen(threshold_last_seen_);
00205 me_->setLocalizationEps(eps_);
00206
00207 me_->setOrca(orca);
00208 me_->setClearpath(clearpath);
00209 me_->setTypeVO(type_vo);
00210 me_->setConvex(convex);
00211 me_->setUseTruncation(use_truncation);
00212 me_->setNumSamples(num_samples);
00213
00214
00215 trunc_time_ = getParamDef(private_nh,"trunc_time",5.0);
00216 left_pref_ = getParamDef(private_nh,"left_pref",0.1);
00217
00218 publish_positions_period_ = getParamDef(private_nh,"publish_positions_frequency",10.0);
00219 publish_positions_period_ = 1.0 / publish_positions_period_;
00220
00221 publish_me_period_ = getParamDef(private_nh,"publish_me_frequency",10.0);
00222 publish_me_period_ = 1.0/publish_me_period_;
00223
00224 me_->setTruncTime(trunc_time_);
00225 me_->setLeftPref(left_pref_);
00226 me_->setPublishPositionsPeriod(publish_positions_period_);
00227 me_->setPublishMePeriod(publish_me_period_);
00228
00229
00230
00231
00232
00233 std::vector<geometry_msgs::Point> footprint_points;
00234 footprint_points = costmap_ros_->getRobotFootprint();
00235
00236 geometry_msgs::PolygonStamped footprint;
00237 geometry_msgs::Point32 p;
00238 for (int i = 0; i<(int)footprint_points.size(); i++) {
00239 p.x = footprint_points[i].x;
00240 p.y = footprint_points[i].y;
00241 footprint.polygon.points.push_back(p);
00242 }
00243 if (footprint.polygon.points.size()>2)
00244 me_->setFootprint(footprint);
00245 else {
00246 double angle = 0;
00247 double step = 2 * M_PI / 72;
00248 while(angle < 2 * M_PI){
00249 geometry_msgs::Point32 pt;
00250 pt.x = radius_ * cos(angle);
00251 pt.y = radius_ * sin(angle);
00252 pt.z = 0.0;
00253 footprint.polygon.points.push_back(pt);
00254 angle += step;
00255 }
00256 me_->setFootprint(footprint);
00257 }
00258
00259 me_->initAsMe(tf_);
00260 me_->setId(my_id);
00261
00262
00263
00264 skip_next_ = false;
00265 g_plan_pub_ = private_nh.advertise<nav_msgs::Path>("global_plan", 1);
00266 l_plan_pub_ = private_nh.advertise<nav_msgs::Path>("local_plan", 1);
00267 std::string move_base_name = ros::this_node::getName();
00268
00269 obstacles_sub_ = nh.subscribe(move_base_name + "/local_costmap/obstacles",1,&CollvoidLocalPlanner::obstaclesCallback,this);
00270
00271 setup_= false;
00272 dsrv_ = new dynamic_reconfigure::Server<collvoid_local_planner::CollvoidConfig>(private_nh);
00273 dynamic_reconfigure::Server<collvoid_local_planner::CollvoidConfig>::CallbackType cb = boost::bind(&CollvoidLocalPlanner::reconfigureCB, this, _1, _2);
00274 dsrv_->setCallback(cb);
00275 initialized_ = true;
00276 }
00277 else
00278 ROS_WARN("This planner has already been initialized, you can't call it twice, doing nothing");
00279
00280 }
00281
00282
00283 void CollvoidLocalPlanner::reconfigureCB(collvoid_local_planner::CollvoidConfig &config, uint32_t level){
00284 boost::recursive_mutex::scoped_lock l(configuration_mutex_);
00285
00286
00287
00288 if(!setup_)
00289 {
00290 last_config_ = config;
00291 default_config_ = config;
00292 setup_ = true;
00293 return;
00294 }
00295 if(config.restore_defaults) {
00296 config = default_config_;
00297
00298 config.restore_defaults = false;
00299 }
00300
00301 acc_lim_x_ = config.acc_lim_x;
00302 acc_lim_y_ = config.acc_lim_y;
00303 acc_lim_th_ = config.acc_lim_th;
00304
00305 max_vel_with_obstacles_ = config.max_vel_with_obstacles;
00306 max_vel_x_ = config.max_vel_x;
00307 min_vel_x_ = config.min_vel_x;
00308 max_vel_y_ = config.max_vel_y;
00309 min_vel_y_ = config.min_vel_y;
00310 max_vel_th_ = config.max_vel_th;
00311 min_vel_th_ = config.min_vel_th;
00312 min_vel_th_inplace_ = config.min_vel_th_inplace;
00313
00314 radius_ = config.footprint_radius;
00315
00316 time_horizon_obst_ = config.time_horizon_obst;
00317 time_to_holo_ = config.time_to_holo;
00318 min_error_holo_ = config.min_error_holo;
00319 max_error_holo_ = config.max_error_holo;
00320 delete_observations_ = config.delete_observations;
00321 threshold_last_seen_ = config.threshold_last_seen;
00322
00323 eps_ = config.eps;
00324
00325
00326 trunc_time_ = config.trunc_time;
00327 left_pref_ = config.left_pref;
00328 publish_positions_period_ = config.publish_positions_frequency;
00329 publish_positions_period_ = 1.0 / publish_positions_period_;
00330 publish_me_period_ = config.publish_me_frequency;
00331 publish_me_period_ = 1.0 / publish_me_period_;
00332
00333
00334 me_->setAccelerationConstraints(acc_lim_x_, acc_lim_y_, acc_lim_th_);
00335
00336 me_->setMaxVelWithObstacles(max_vel_with_obstacles_);
00337
00338 me_->setMinMaxSpeeds(min_vel_x_, max_vel_x_, min_vel_y_, max_vel_y_, min_vel_th_, max_vel_th_, min_vel_th_inplace_);
00339
00340 me_->setFootprintRadius(radius_);
00341
00342 me_->setTimeHorizonObst(time_horizon_obst_);
00343 me_->setTimeToHolo(time_to_holo_);
00344 me_->setMinMaxErrorHolo(min_error_holo_, max_error_holo_);
00345
00346 me_->setDeleteObservations(delete_observations_);
00347 me_->setThresholdLastSeen(threshold_last_seen_);
00348 me_->setLocalizationEps(eps_);
00349
00350 me_->setTruncTime(trunc_time_);
00351 me_->setLeftPref(left_pref_);
00352 me_->setPublishPositionsPeriod(publish_positions_period_);
00353 me_->setPublishMePeriod(publish_me_period_);
00354
00355
00356 me_->setOrca(config.orca);
00357 me_->setClearpath(config.clearpath);
00358 me_->setTypeVO(config.type_vo);
00359 me_->setConvex(config.convex);
00360 me_->setUseTruncation(config.use_truncation);
00361 me_->setNumSamples(config.num_samples);
00362
00363
00364 last_config_ = config;
00365 }
00366
00367
00368 bool CollvoidLocalPlanner::rotateToGoal(const tf::Stamped<tf::Pose>& global_pose, const tf::Stamped<tf::Pose>& robot_vel, double goal_th, geometry_msgs::Twist& cmd_vel){
00369 if (ignore_goal_yaw_) {
00370 cmd_vel.angular.z = 0.0;
00371 return true;
00372 }
00373 double yaw = tf::getYaw(global_pose.getRotation());
00374 double vel_yaw = tf::getYaw(robot_vel.getRotation());
00375 cmd_vel.linear.x = 0;
00376 cmd_vel.linear.y = 0;
00377 double ang_diff = angles::shortest_angular_distance(yaw, goal_th);
00378
00379 double v_th_samp = ang_diff > 0.0 ? std::min(max_vel_th_,
00380 std::max(min_vel_th_inplace_, ang_diff)) : std::max(-1.0 * max_vel_th_,
00381 std::min(-1.0 * min_vel_th_inplace_, ang_diff));
00382
00383
00384 double max_acc_vel = fabs(vel_yaw) + acc_lim_th_ * sim_period_;
00385 double min_acc_vel = fabs(vel_yaw) - acc_lim_th_ * sim_period_;
00386
00387 v_th_samp = sign(v_th_samp) * std::min(std::max(fabs(v_th_samp), min_acc_vel), max_acc_vel);
00388
00389
00390 double max_speed_to_stop = sqrt(2 * acc_lim_th_ * fabs(ang_diff));
00391
00392 v_th_samp = sign(v_th_samp) * std::min(max_speed_to_stop, fabs(v_th_samp));
00393 if (fabs(v_th_samp) <= 0.0 * min_vel_th_inplace_)
00394 v_th_samp = 0.0;
00395 else if (fabs(v_th_samp) < min_vel_th_inplace_)
00396 v_th_samp = sign(v_th_samp) * max(min_vel_th_inplace_,fabs(v_th_samp));
00397
00398 bool valid_cmd = true;
00399
00400 ROS_DEBUG("Moving to desired goal orientation, th cmd: %.2f", v_th_samp);
00401
00402 if(valid_cmd){
00403 cmd_vel.angular.z = v_th_samp;
00404 return true;
00405 }
00406
00407 cmd_vel.angular.z = 0.0;
00408 return false;
00409 }
00410
00411 bool CollvoidLocalPlanner::stopWithAccLimits(const tf::Stamped<tf::Pose>& global_pose, const tf::Stamped<tf::Pose>& robot_vel, geometry_msgs::Twist& cmd_vel){
00412
00413
00414 double vx = sign(robot_vel.getOrigin().x()) * std::max(0.0, (fabs(robot_vel.getOrigin().x()) - acc_lim_x_ * sim_period_));
00415 double vy = sign(robot_vel.getOrigin().y()) * std::max(0.0, (fabs(robot_vel.getOrigin().y()) - acc_lim_y_ * sim_period_));
00416
00417 double vel_yaw = tf::getYaw(robot_vel.getRotation());
00418 double vth = sign(vel_yaw) * std::max(0.0, (fabs(vel_yaw) - acc_lim_th_ * sim_period_));
00419
00420
00421
00422 bool valid_cmd = true;
00423
00424
00425 if(valid_cmd){
00426
00427 cmd_vel.linear.x = vx;
00428 cmd_vel.linear.y = vy;
00429 cmd_vel.angular.z = vth;
00430 return true;
00431 }
00432
00433 cmd_vel.linear.x = 0.0;
00434 cmd_vel.linear.y = 0.0;
00435 cmd_vel.angular.z = 0.0;
00436 return false;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 bool CollvoidLocalPlanner::setPlan(const std::vector<geometry_msgs::PoseStamped>& orig_global_plan){
00451 if(!initialized_){
00452 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00453 return false;
00454 }
00455
00456
00457 global_plan_.clear();
00458 global_plan_ = orig_global_plan;
00459 current_waypoint_ = 0;
00460 xy_tolerance_latch_ = false;
00461
00462
00463 if(!transformGlobalPlan(*tf_, global_plan_, *costmap_ros_, global_frame_, transformed_plan_)){
00464 ROS_WARN("Could not transform the global plan to the frame of the controller");
00465 return false;
00466 }
00467
00468 return true;
00469 }
00470
00471 bool CollvoidLocalPlanner::isGoalReached(){
00472 if(!initialized_){
00473 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00474 return false;
00475 }
00476
00477
00478 nav_msgs::Odometry base_odom;
00479 {
00480 boost::mutex::scoped_lock(me_->me_lock_);
00481 base_odom = me_->base_odom_;
00482 }
00483
00484 return base_local_planner::isGoalReached(*tf_, global_plan_, *costmap_ros_, global_frame_, base_odom,
00485 rot_stopped_velocity_, trans_stopped_velocity_, xy_goal_tolerance_, yaw_goal_tolerance_);
00486 }
00487
00488
00489
00490 bool CollvoidLocalPlanner::computeVelocityCommands(geometry_msgs::Twist& cmd_vel){
00491 if(!initialized_){
00492 ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00493 return false;
00494 }
00495
00496 tf::Stamped<tf::Pose> global_pose;
00497
00498 global_pose.setIdentity();
00499 global_pose.frame_id_ = robot_base_frame_;
00500 global_pose.stamp_ = ros::Time();
00501 tf_->transformPose(global_frame_, global_pose, global_pose);
00502
00503
00504 geometry_msgs::Twist global_vel;
00505 me_->me_lock_.lock();
00506 global_vel.linear.x = me_->base_odom_.twist.twist.linear.x;
00507 global_vel.linear.y = me_->base_odom_.twist.twist.linear.y;
00508 global_vel.angular.z = me_->base_odom_.twist.twist.angular.z;
00509 me_->me_lock_.unlock();
00510
00511 tf::Stamped<tf::Pose> robot_vel;
00512 robot_vel.setData(tf::Transform(tf::createQuaternionFromYaw(global_vel.angular.z), tf::Vector3(global_vel.linear.x, global_vel.linear.y, 0)));
00513 robot_vel.frame_id_ = robot_base_frame_;
00514 robot_vel.stamp_ = ros::Time();
00515
00516 tf::Stamped<tf::Pose> goal_point;
00517 tf::poseStampedMsgToTF(global_plan_.back(), goal_point);
00518
00519
00520 double goal_x = goal_point.getOrigin().getX();
00521 double goal_y = goal_point.getOrigin().getY();
00522 double yaw = tf::getYaw(goal_point.getRotation());
00523 double goal_th = yaw;
00524
00525
00526 if(base_local_planner::goalPositionReached(global_pose, goal_x, goal_y, xy_goal_tolerance_) || xy_tolerance_latch_){
00527
00528
00529
00530 if(latch_xy_goal_tolerance_)
00531 xy_tolerance_latch_ = true;
00532
00533
00534 if(base_local_planner::goalOrientationReached(global_pose, goal_th, yaw_goal_tolerance_)){
00535
00536 cmd_vel.linear.x = 0.0;
00537 cmd_vel.linear.y = 0.0;
00538 cmd_vel.angular.z = 0.0;
00539 rotating_to_goal_ = false;
00540 xy_tolerance_latch_ = false;
00541 }
00542 else {
00543
00544 nav_msgs::Odometry base_odom;
00545 {
00546 boost::mutex::scoped_lock(me_->me_lock_);
00547 base_odom = me_->base_odom_;
00548 }
00549
00550
00551 if(!rotating_to_goal_ && !base_local_planner::stopped(base_odom, rot_stopped_velocity_, trans_stopped_velocity_)){
00552
00553 if(!stopWithAccLimits(global_pose, robot_vel, cmd_vel))
00554 return false;
00555 }
00556
00557 else{
00558
00559 rotating_to_goal_ = true;
00560 if(!rotateToGoal(global_pose, robot_vel, goal_th, cmd_vel))
00561 return false;
00562 }
00563 }
00564
00565
00566 transformed_plan_.clear();
00567 base_local_planner::publishPlan(transformed_plan_, g_plan_pub_, 0.0, 1.0, 0.0, 0.0);
00568 base_local_planner::publishPlan(transformed_plan_, l_plan_pub_, 0.0, 0.0, 1.0, 0.0);
00569
00570 return true;
00571 }
00572
00573 tf::Stamped<tf::Pose> target_pose;
00574 target_pose.setIdentity();
00575 target_pose.frame_id_ = robot_base_frame_;
00576
00577 if (!skip_next_){
00578 if(!transformGlobalPlan(*tf_, global_plan_, *costmap_ros_, global_frame_, transformed_plan_)){
00579 ROS_WARN("Could not transform the global plan to the frame of the controller");
00580 return false;
00581 }
00582 geometry_msgs::PoseStamped target_pose_msg;
00583 findBestWaypoint(target_pose_msg, global_pose);
00584 }
00585 tf::poseStampedMsgToTF(transformed_plan_[current_waypoint_], target_pose);
00586
00587
00588 geometry_msgs::Twist res;
00589
00590 res.linear.x = target_pose.getOrigin().x() - global_pose.getOrigin().x();
00591 res.linear.y = target_pose.getOrigin().y() - global_pose.getOrigin().y();
00592 res.angular.z = angles::shortest_angular_distance(tf::getYaw(global_pose.getRotation()),atan2(res.linear.y, res.linear.x));
00593
00594
00595 collvoid::Vector2 goal_dir = collvoid::Vector2(res.linear.x,res.linear.y);
00596
00597 if (collvoid::abs(goal_dir) > max_vel_x_) {
00598 goal_dir = max_vel_x_ * collvoid::normalize(goal_dir);
00599 }
00600 else if (collvoid::abs(goal_dir) < min_vel_x_) {
00601 goal_dir = min_vel_x_ * 1.2* collvoid::normalize(goal_dir);
00602 }
00603
00604
00605 collvoid::Vector2 pref_vel = collvoid::Vector2(goal_dir.x(),goal_dir.y());
00606
00607
00608
00609 me_->computeNewVelocity(pref_vel, cmd_vel);
00610
00611
00612 if(std::abs(cmd_vel.angular.z)<min_vel_th_)
00613 cmd_vel.angular.z = 0.0;
00614 if(std::abs(cmd_vel.linear.x)<min_vel_x_)
00615 cmd_vel.linear.x = 0.0;
00616 if(std::abs(cmd_vel.linear.y)<min_vel_y_)
00617 cmd_vel.linear.y = 0.0;
00618
00619 bool valid_cmd = true;
00620
00621 if (!valid_cmd){
00622 cmd_vel.angular.z = 0.0;
00623 cmd_vel.linear.x = 0.0;
00624 cmd_vel.linear.y = 0.0;
00625 }
00626
00627 if (cmd_vel.linear.x == 0.0 && cmd_vel.angular.z == 0.0 && cmd_vel.linear.y == 0.0) {
00628
00629 ROS_DEBUG("Did not find a good vel, calculated best holonomic velocity was: %f, %f, cur wp %d of %d trying next waypoint", me_->velocity_.x(),me_->velocity_.y(), current_waypoint_, (int)transformed_plan_.size());
00630 if (current_waypoint_ < transformed_plan_.size()-1){
00631 current_waypoint_++;
00632 skip_next_= true;
00633 }
00634 else {
00635 transformed_plan_.clear();
00636 base_local_planner::publishPlan(transformed_plan_, g_plan_pub_, 0.0, 1.0, 0.0, 0.0);
00637 base_local_planner::publishPlan(transformed_plan_, l_plan_pub_, 0.0, 0.0, 1.0, 0.0);
00638
00639 return false;
00640 }
00641 }
00642 else {
00643 skip_next_ = false;
00644 }
00645
00646
00647
00648
00649 std::vector<geometry_msgs::PoseStamped> local_plan;
00650 geometry_msgs::PoseStamped pos;
00651
00652
00653 tf::poseStampedTFToMsg(global_pose,pos);
00654 local_plan.push_back(pos);
00655 local_plan.push_back(transformed_plan_[current_waypoint_]);
00656 base_local_planner::publishPlan(transformed_plan_, g_plan_pub_, 0.0, 1.0, 0.0, 0.0);
00657 base_local_planner::publishPlan(local_plan, l_plan_pub_, 0.0, 0.0, 1.0, 0.0);
00658
00659 return true;
00660 }
00661
00662 void CollvoidLocalPlanner::findBestWaypoint(geometry_msgs::PoseStamped& target_pose, const tf::Stamped<tf::Pose>& global_pose){
00663 current_waypoint_ = 0;
00664 double min_dist = DBL_MAX;
00665 for (size_t i=current_waypoint_; i < transformed_plan_.size(); i++)
00666 {
00667 double y = global_pose.getOrigin().y();
00668 double x = global_pose.getOrigin().x();
00669 double dist = base_local_planner::distance(x, y, transformed_plan_[i].pose.position.x, transformed_plan_[i].pose.position.y);
00670 if (dist < me_->getRadius() || dist < min_dist) {
00671 min_dist = dist;
00672 target_pose = transformed_plan_[i];
00673 current_waypoint_ = i;
00674
00675 }
00676 }
00677
00678
00679
00680
00681
00682 if (current_waypoint_ == transformed_plan_.size()-1)
00683 return;
00684
00685 double dif_x = transformed_plan_[current_waypoint_+1].pose.position.x - target_pose.pose.position.x;
00686 double dif_y = transformed_plan_[current_waypoint_+1].pose.position.y - target_pose.pose.position.y;
00687
00688 double plan_dir = atan2(dif_y, dif_x);
00689
00690 double dif_ang = plan_dir;
00691
00692
00693
00694
00695
00696
00697 for (size_t i=current_waypoint_+1; i<transformed_plan_.size(); i++) {
00698 dif_x = transformed_plan_[i].pose.position.x - target_pose.pose.position.x;
00699 dif_y = transformed_plan_[i].pose.position.y - target_pose.pose.position.y;
00700
00701 dif_ang = atan2(dif_y, dif_x);
00702
00703
00704 if(fabs(plan_dir - dif_ang) > 1.0* yaw_goal_tolerance_) {
00705 target_pose = transformed_plan_[i-1];
00706 current_waypoint_ = i-1;
00707
00708
00709 return;
00710 }
00711 }
00712 target_pose = transformed_plan_.back();
00713 current_waypoint_ = transformed_plan_.size()-1;
00714
00715
00716 }
00717
00718 bool CollvoidLocalPlanner::transformGlobalPlan(const tf::TransformListener& tf, const std::vector<geometry_msgs::PoseStamped>& global_plan,
00719 const costmap_2d::Costmap2DROS& costmap, const std::string& global_frame,
00720 std::vector<geometry_msgs::PoseStamped>& transformed_plan){
00721 const geometry_msgs::PoseStamped& plan_pose = global_plan[0];
00722
00723 transformed_plan.clear();
00724
00725 try{
00726 if (!global_plan.size() > 0)
00727 {
00728 ROS_ERROR("Recieved plan with zero length");
00729 return false;
00730 }
00731
00732 tf::StampedTransform transform;
00733 tf.lookupTransform(global_frame, ros::Time(),
00734 plan_pose.header.frame_id, plan_pose.header.stamp,
00735 plan_pose.header.frame_id, transform);
00736
00737
00738 tf::Stamped<tf::Pose> robot_pose;
00739 robot_pose.setIdentity();
00740 robot_pose.frame_id_ = costmap.getBaseFrameID();
00741 robot_pose.stamp_ = ros::Time();
00742 tf.transformPose(plan_pose.header.frame_id, robot_pose, robot_pose);
00743
00744
00745
00746
00747
00748 double sq_dist = DBL_MAX;
00749
00750 unsigned int cur_waypoint = 0;
00751 for (size_t i=0; i < global_plan_.size(); i++)
00752 {
00753 double y = robot_pose.getOrigin().y();
00754 double x = robot_pose.getOrigin().x();
00755 double dist = base_local_planner::distance(x, y, global_plan_[i].pose.position.x, global_plan_[i].pose.position.y);
00756 if (dist < sqrt(sq_dist)) {
00757 sq_dist = dist * dist;
00758 cur_waypoint = i;
00759
00760 }
00761 }
00762
00763 unsigned int i = cur_waypoint;
00764
00765 tf::Stamped<tf::Pose> tf_pose;
00766 geometry_msgs::PoseStamped newer_pose;
00767
00768
00769 while(i < (unsigned int)global_plan.size()) {
00770 double x_diff = robot_pose.getOrigin().x() - global_plan[i].pose.position.x;
00771 double y_diff = robot_pose.getOrigin().y() - global_plan[i].pose.position.y;
00772 sq_dist = x_diff * x_diff + y_diff * y_diff;
00773
00774 const geometry_msgs::PoseStamped& pose = global_plan[i];
00775 poseStampedMsgToTF(pose, tf_pose);
00776 tf_pose.setData(transform * tf_pose);
00777 tf_pose.stamp_ = transform.stamp_;
00778 tf_pose.frame_id_ = global_frame;
00779 poseStampedTFToMsg(tf_pose, newer_pose);
00780
00781 transformed_plan.push_back(newer_pose);
00782
00783 ++i;
00784 }
00785 }
00786 catch(tf::LookupException& ex) {
00787 ROS_ERROR("No Transform available Error: %s\n", ex.what());
00788 return false;
00789 }
00790 catch(tf::ConnectivityException& ex) {
00791 ROS_ERROR("Connectivity Error: %s\n", ex.what());
00792 return false;
00793 }
00794 catch(tf::ExtrapolationException& ex) {
00795 ROS_ERROR("Extrapolation Error: %s\n", ex.what());
00796 if (global_plan.size() > 0)
00797 ROS_ERROR("Global Frame: %s Plan Frame size %d: %s\n", global_frame.c_str(), (unsigned int)global_plan.size(), global_plan[0].header.frame_id.c_str());
00798
00799 return false;
00800 }
00801
00802 return true;
00803 }
00804
00805 void CollvoidLocalPlanner::obstaclesCallback(const nav_msgs::GridCells::ConstPtr& msg){
00806 size_t num_obst = msg->cells.size();
00807 boost::mutex::scoped_lock lock(me_->obstacle_lock_);
00808 me_->obstacle_points_.clear();
00809
00810 for (size_t i = 0; i < num_obst; i++) {
00811 geometry_msgs::PointStamped in, result;
00812 in.header = msg->header;
00813 in.point = msg->cells[i];
00814
00815 try {
00816 tf_->waitForTransform(global_frame_, robot_base_frame_, msg->header.stamp, ros::Duration(0.2));
00817
00818 tf_->transformPoint(global_frame_, in, result);
00819 }
00820 catch (tf::TransformException ex){
00821 ROS_ERROR("%s",ex.what());
00822 return;
00823 };
00824
00825 me_->obstacle_points_.push_back(collvoid::Vector2(result.point.x,result.point.y));
00826 }
00827 }
00828
00829
00830
00831 };
00832
00833