dt_planner_ros.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2014, Austin Hendrix
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of Willow Garage, Inc. nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Stephan Hofstaetter
00036 *********************************************************************/
00037 
00038 #include <dt_local_planner/dt_planner_ros.h>
00039 #include <dt_local_planner/polyfit.hpp>
00040 #include <cmath>
00041 #include <limits>
00042 #include <ros/console.h>
00043 #include <pluginlib/class_list_macros.h>
00044 #include <base_local_planner/goal_functions.h>
00045 #include <nav_msgs/Path.h>
00046 #include <angles/angles.h>
00047 
00048 //register this planner as a BaseLocalPlanner plugin
00049 PLUGINLIB_EXPORT_CLASS(dt_local_planner::DTPlannerROS, nav_core::BaseLocalPlanner)
00050 
00051 namespace dt_local_planner {
00052 
00053   void DTPlannerROS::reconfigureCB(DTPlannerConfig &config, uint32_t level) {
00054       max_vel_ = config.max_vel;
00055       max_ang_ = config.max_ang;
00056       max_vel_deltaT0_ = config.max_vel_deltaT0;
00057       stepCnt_max_vel_ = config.stepCnt_max_vel;
00058       nPolyGrad_ = config.nPolyGrad;
00059       K_p_ = config.K_p;
00060       K_d_ = config.K_d;
00061       move_ = config.move;
00062   }
00063 
00064   DTPlannerROS::DTPlannerROS() : initialized_(false),goal_reached_(false), firstComputeVelocityCommands_(true) {
00065 
00066   }
00067 
00068   void DTPlannerROS::initialize(
00069     std::string name,
00070     tf::TransformListener* tf,
00071     costmap_2d::Costmap2DROS* costmap_ros) {
00072     if (! isInitialized()) {
00073 
00074       ros::NodeHandle private_nh("~/" + name);
00075       tf_ = tf;
00076       costmap_ros_ = costmap_ros;
00077 
00078       // make sure to update the costmap we'll use for this cycle
00079       costmap_2d::Costmap2D* costmap = costmap_ros_->getCostmap();
00080 
00081       std::string odom_topic;
00082       private_nh.param<std::string>("odom_topic", odom_topic, "odom");
00083       odom_helper_.setOdomTopic( odom_topic );
00084       
00085       initialized_ = true;
00086 
00087       dsrv_ = new dynamic_reconfigure::Server<DTPlannerConfig>(private_nh);
00088       dynamic_reconfigure::Server<DTPlannerConfig>::CallbackType cb = boost::bind(&DTPlannerROS::reconfigureCB, this, _1, _2);
00089       dsrv_->setCallback(cb);
00090     }
00091     else{
00092       ROS_WARN("This planner has already been initialized, doing nothing.");
00093     }
00094   }
00095   
00096   bool DTPlannerROS::setPlan(const std::vector<geometry_msgs::PoseStamped>& orig_global_plan) {
00097     if (! isInitialized()) {
00098       ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00099       return false;
00100     }
00101 
00102     //getting the plan
00103     plan_ = orig_global_plan;
00104     planSize_ = plan_.size();
00105     ROS_INFO_NAMED("dt_local_planner", "Got new plan with size: %d",planSize_);
00106 
00107     //setting our goal
00108     goal_x_ = plan_[planSize_-1].pose.position.x;
00109     goal_y_ = plan_[planSize_-1].pose.position.y;
00110 
00111     //declaration of the polyfit parameter
00112     std::vector<double> p_x (planSize_, 0.);
00113     std::vector<double> p_y (planSize_, 0.);
00114     std::vector<double> p_t (planSize_, 0.);
00115 
00116     //generating p_x,p_y out of the global plan
00117     for(int index = 0;index < planSize_;index++){
00118       p_x[index] = plan_[index].pose.position.x;
00119       p_y[index] = plan_[index].pose.position.y;
00120       //ROS_INFO_NAMED("dt_local_planner", "p_x %f",p_x[index]);
00121     }
00122     ROS_INFO_NAMED("dt_local_planner", "p_x,p_y generated!");
00123   
00124     //calculating time between each points with x = v * t
00125     double max_vel_deltaT;
00126     double deltaR;
00127     double deltaT;
00128     
00129     //calculating time between each points with x = v * t
00130     //with a weighting of the first steps until the full speed should apply
00131 
00132     for(int index = 1;index < planSize_;index++){
00133       deltaR = sqrt( pow(p_x[index] - p_x[index-1], 2.0) + pow(p_y[index] - p_y[index-1], 2.0) );
00134       if(index <= stepCnt_max_vel_){
00135         max_vel_deltaT = max_vel_deltaT0_*index/stepCnt_max_vel_;
00136       }
00137       deltaT = deltaR / max_vel_deltaT;
00138       p_t[index] = p_t[index-1] + deltaT;
00139       //ROS_INFO_NAMED("dt_local_planner", "p_t %f",p_t[index]);
00140     }
00141     ROS_INFO_NAMED("dt_local_planner", "p_t generated!");
00142 
00143     //define polygrad
00144     //nPolyGrad_ = 15;//planSize_-1;
00145 
00146     //calculation of the polynom coefficiencies from a0 to an
00147     //http://vilipetek.com/2013/10/07/polynomial-fitting-in-c-using-boost/
00148     aCoeff_x_ = polyfit(p_t, p_x, nPolyGrad_);
00149     aCoeff_y_ = polyfit(p_t, p_y, nPolyGrad_);
00150     ROS_INFO_NAMED("dt_local_planner", "Calculated polyfit for x and y with grade %d",
00151     nPolyGrad_);
00152 
00153     //we are at he beginning; goal_reached_ set to false;
00154     goal_reached_ = false;
00155     // return false here if we would like the global planner to re-plan
00156     ROS_INFO_NAMED("dt_local_planner", "----------------------");
00157     return true;
00158   }
00159 
00160   bool DTPlannerROS::isGoalReached() {
00161     if (! isInitialized()) {
00162       ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
00163       return false;
00164     }
00165     return goal_reached_;
00166   }
00167 
00168   DTPlannerROS::~DTPlannerROS(){
00169     //make sure to clean things up
00170     delete dsrv_;
00171   }
00172 
00173   bool DTPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel) {
00174     // if we don't have a plan, what are we doing here???
00175     if( plan_.size() < 2) {
00176       return false;
00177     }
00178 
00179     if(firstComputeVelocityCommands_){
00180       start_time_ = ros::Time::now().toSec();
00181       lastCall_time_ = start_time_;
00182     }
00183 
00184     //use our current pose
00185     tf::Stamped<tf::Pose> current_pose;
00186     costmap_ros_->getRobotPose(current_pose);
00187     double pos_cur_x = current_pose.getOrigin().x();
00188     double pos_cur_y = current_pose.getOrigin().y();
00189     double gamma_cur = tf::getYaw(current_pose.getRotation());
00190     ROS_INFO_NAMED("dt_local_planner", "Current position (costmap) is (%f, %f) with Angular (%f)",
00191         pos_cur_x, pos_cur_y, gamma_cur);
00192 
00193     //check if we are at the goal
00194     double dist_x = fabs(goal_x_ - current_pose.getOrigin().x());
00195     double dist_y = fabs(goal_y_ - current_pose.getOrigin().x());
00196     ROS_INFO_NAMED("dt_local_planner", "Current distance to goal (%f, %f)",dist_x, dist_y);
00197   
00198     //(dist_x > 0.00001 || dist_y > 0.00001) && 
00199     if(move_){//we are not at the goal, compute on when we are allowed to move
00200       ROS_INFO_NAMED("dt_local_planner", "preparing to move:"); 
00201   
00202       //get the current velocity -> vel_cur
00203       tf::Stamped<tf::Pose> robot_vel;
00204       odom_helper_.getRobotVel(robot_vel);
00205       double vel_cur_lin = robot_vel.getOrigin().x();
00206       double vel_cur_ang = robot_vel.getOrigin().y();
00207       
00208       /* //different way to get the velocity
00209       nav_msgs::Odometry odom;
00210       odom_helper_.getOdom(odom);
00211       double vel_cur_lin = odom.twist.twist.linear.x;
00212       double vel_cur_ang = odom.twist.twist.angular.z;
00213       */
00214       ROS_INFO_NAMED("dt_local_planner", "Current robot velocity (lin/ang): (%f/%f)",   vel_cur_lin,vel_cur_ang);
00215 
00216       //calculate time in seconds
00217       double current_time = ros::Time::now().toSec() - start_time_;
00218       ROS_INFO_NAMED("dt_local_planner", "time in seconds: %f",current_time); 
00219 
00220       std::vector<double> time_vec (nPolyGrad_, 0.);
00221 
00222       for(int index = 0; index < nPolyGrad_;index++){
00223         time_vec[index] = pow(current_time,index);
00224         //ROS_INFO_NAMED("dt_local_planner", "calculated poly_t: %f",t_vec[index]); 
00225       }
00226       //ROS_INFO_NAMED("dt_local_planner", "calculated poly_t index n-1: %f",t_vec[nPolyGrad_-1]); 
00227 
00228       double temp_x = 0;
00229       double temp_y = 0;
00230       double pos_dest_x = 0;
00231       double pos_dest_y = 0;
00232       double vel_dest_x = 0;
00233       double vel_dest_y = 0;      
00234       double acc_dest_x = 0;
00235       double acc_dest_y = 0;
00236 
00237       for(int i=0;i<nPolyGrad_;i++)
00238       {
00239         temp_x = aCoeff_x_[i]*time_vec[i];
00240         temp_y = aCoeff_y_[i]*time_vec[i];
00241         pos_dest_x += temp_x;
00242         pos_dest_y += temp_y;
00243       }
00244       ROS_INFO_NAMED("dt_local_planner", "p_x0=%f and p_y0=%f",pos_dest_x,pos_dest_y);
00245       for(int i=1;i<nPolyGrad_-1;i++)
00246       {
00247         temp_x = aCoeff_x_[i]*i*time_vec[i-1];
00248         temp_y = aCoeff_y_[i]*i*time_vec[i-1];
00249         vel_dest_x += temp_x;
00250         vel_dest_y += temp_y;
00251       }
00252       ROS_INFO_NAMED("dt_local_planner", "p_x1=%f and p_y1=%f",vel_dest_x,vel_dest_y);
00253       for(int i=2;i<nPolyGrad_-2;i++)
00254       {
00255         temp_x = aCoeff_x_[i]*i*(i+1)*time_vec[i-2];
00256         temp_y = aCoeff_y_[i]*i*(i+1)*time_vec[i-2];
00257         acc_dest_x += temp_x;
00258         acc_dest_y += temp_y;
00259       }
00260       ROS_INFO_NAMED("dt_local_planner", "p_x2=%f and p_y2=%f",acc_dest_x,acc_dest_y);
00261 
00262       //calculate only at the first run
00263       if(firstComputeVelocityCommands_){
00264         double vel_dest_x0 = vel_dest_x;
00265         double vel_dest_y0 = vel_dest_y;
00266         vel_dest0_ = sqrt(fabs(vel_dest_x0) + fabs(vel_dest_y0));
00267         ROS_INFO_NAMED("dt_local_planner", "sqrt(vel_dest_x0(%f)+vel_dest_y0(%f))=vel_dest0_(%f)",vel_dest_x0,vel_dest_y0,vel_dest0_);
00268       }
00269 
00270       //dynamic trajectory
00271       double lambda_x = acc_dest_x + K_d_ * (vel_dest_x - vel_cur_lin * cos(gamma_cur)) + K_p_ * (pos_dest_x - pos_cur_x);
00272       double lambda_y = acc_dest_y + K_d_ * (vel_dest_y - vel_cur_lin * sin(gamma_cur)) + K_p_ * (pos_dest_y - pos_cur_y);
00273       ROS_INFO_NAMED("dt_local_planner", "lambda x, y: (%f, %f)",lambda_x, lambda_y);
00274 
00275       double acc_l = cos( gamma_cur ) * lambda_x + sin( gamma_cur ) * lambda_y;
00276 
00277       
00278       double omega = 0;
00279       if(fabs(vel_cur_lin) > 0.001){
00280         omega = (-sin(gamma_cur) * lambda_x + cos(gamma_cur) * lambda_y) / vel_cur_lin;
00281       }//else omega = 0
00282 
00283       //euler integragtion
00284       //delta_time  = time between calls of the computeVelocityCommands function
00285       double delta_time = ros::Time::now().toSec() - lastCall_time_;
00286       ROS_INFO_NAMED("dt_local_planner", "deltaT in seconds: %f",delta_time); 
00287 
00288       double vel_dest1 = vel_dest0_ + acc_l * delta_time;
00289       ROS_INFO_NAMED("dt_local_planner", "vel_dest0_ + acc_l: (%f, %f)", vel_dest0_, acc_l*delta_time);
00290       double gamma_dest1 = gamma_dest0_ + omega * delta_time;
00291 
00292       //saving params for the next call
00293       vel_dest0_ = vel_dest1;
00294       gamma_dest0_ = gamma_dest1;
00295       lastCall_time_ = current_time;
00296 
00297       //setting the velocity commands
00298       ROS_INFO_NAMED("dt_local_planner", "Trying to set velocity and angular speed: (%f, %f)",
00299         vel_dest1, gamma_dest1);
00300       if(max_vel_ < fabs(vel_dest1)){
00301         ROS_WARN_NAMED("dt_local_planner", "speed exceed: velocity set to: %f m/s",max_vel_);
00302         cmd_vel.linear.x = max_vel_;
00303       }else{
00304         cmd_vel.linear.x = vel_dest1;
00305       }
00306       if(max_ang_ < fabs(gamma_dest1)){
00307         cmd_vel.angular.z = max_ang_;
00308         ROS_WARN_NAMED("dt_local_planner", "speed exceed: angular velocity set to: %f m/s",max_ang_);
00309       }else{
00310         cmd_vel.angular.z = gamma_dest1; 
00311       }
00312     }else//goal reached
00313     {
00314       ROS_INFO_NAMED("dt_local_planner", "goal reached"); 
00315       if(!goal_reached_) goal_reached_ = true;
00316       cmd_vel.linear.x = 0;
00317       cmd_vel.angular.z = 0;
00318     }
00319     
00320     //false when the first call ended
00321     if(firstComputeVelocityCommands_) firstComputeVelocityCommands_ = false;
00322 
00323     // return true if we were abtmwtypes.hle to find a path, false otherwise
00324     ROS_INFO_NAMED("dt_local_planner", "----------------------");
00325     return true;
00326      
00327     
00328   }
00329 
00330 };


dt_local_planner
Author(s): Stephan Hofstaetter
autogenerated on Fri Aug 28 2015 13:41:25