timed_elastic_band.hpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2016,
00006  *  TU Dortmund - Institute of Control Theory and Systems Engineering.
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of the institute nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * Author: Christoph Rösmann
00037  *********************************************************************/
00038 
00039 #include <teb_local_planner/timed_elastic_band.h>
00040 
00041 namespace teb_local_planner
00042 {
00043 
00044   
00045 
00046 template<typename BidirIter, typename Fun>
00047 bool TimedElasticBand::initTEBtoGoal(BidirIter path_start, BidirIter path_end, Fun fun_position, double max_vel_x, double max_vel_theta,
00048                                      boost::optional<double> max_acc_x, boost::optional<double> max_acc_theta,
00049                                      boost::optional<double> start_orientation, boost::optional<double> goal_orientation, int min_samples, bool guess_backwards_motion) 
00050 {
00051     Eigen::Vector2d start_position = fun_position( *path_start );
00052     Eigen::Vector2d goal_position = fun_position( *boost::prior(path_end) );
00053     
00054     bool backwards = false;
00055     
00056     double start_orient, goal_orient;
00057     if (start_orientation)
00058     {
00059       start_orient = *start_orientation;
00060       
00061       // check if the goal is behind the start pose (w.r.t. start orientation)
00062       if (guess_backwards_motion && (goal_position-start_position).dot(Eigen::Vector2d(std::cos(start_orient), std::sin(start_orient))) < 0) 
00063         backwards = true;
00064     }
00065     else
00066     {
00067       Eigen::Vector2d start2goal =  goal_position - start_position;
00068       start_orient = atan2(start2goal[1],start2goal[0]);
00069     }
00070     double timestep = 1; // TODO: time
00071     
00072     
00073     if (goal_orientation)
00074     {
00075       goal_orient = *goal_orientation;
00076     }
00077     else
00078     {
00079       goal_orient = start_orient;
00080     }
00081     
00082     if (!isInit())
00083     {
00084       addPose(start_position, start_orient, true); // add starting point and mark it as fixed for optimization          
00085 
00086       // we insert middle points now (increase start by 1 and decrease goal by 1)
00087       std::advance(path_start,1);
00088       std::advance(path_end,-1);
00089       int idx=0;
00090       for (; path_start != path_end; ++path_start) // insert middle-points
00091       {
00092             //Eigen::Vector2d point_to_goal = path.back()-*it;
00093             //double dir_to_goal = atan2(point_to_goal[1],point_to_goal[0]); // direction to goal
00094             // Alternative: Direction from last path
00095             Eigen::Vector2d curr_point = fun_position(*path_start);
00096             Eigen::Vector2d diff_last = curr_point - Pose(idx).position(); // we do not use boost::prior(*path_start) for those cases,
00097                                                                         // where fun_position() does not return a reference or is expensive.
00098             double diff_norm = diff_last.norm();
00099             
00100             double timestep_vel = diff_norm/max_vel_x; // constant velocity
00101             double timestep_acc;
00102             if (max_acc_x)
00103             {
00104                     timestep_acc = sqrt(2*diff_norm/(*max_acc_x)); // constant acceleration
00105                     if (timestep_vel < timestep_acc && max_acc_x) timestep = timestep_acc;
00106                     else timestep = timestep_vel;
00107             }
00108             else timestep = timestep_vel;
00109             
00110             if (timestep<0) timestep=0.2; // TODO: this is an assumption
00111             
00112             double yaw = atan2(diff_last[1],diff_last[0]);
00113             if (backwards)
00114                 yaw = g2o::normalize_theta(yaw + M_PI);
00115             addPoseAndTimeDiff(curr_point, yaw ,timestep);
00116             
00117             Eigen::Vector2d diff_next = fun_position(*boost::next(path_start))-curr_point; // TODO maybe store the boost::next for the following iteration
00118             double ang_diff = std::abs( g2o::normalize_theta( atan2(diff_next[1],diff_next[0])
00119                                                             -atan2(diff_last[1],diff_last[0]) ) );
00120             
00121             timestep_vel = ang_diff/max_vel_theta; // constant velocity
00122             if (max_acc_theta)
00123             {
00124                     timestep_acc = sqrt(2*ang_diff/(*max_acc_theta)); // constant acceleration
00125                     if (timestep_vel < timestep_acc) timestep = timestep_acc;
00126                     else timestep = timestep_vel;
00127             }
00128             else timestep = timestep_vel;
00129             
00130             if (timestep<0) timestep=0.2; // TODO: this is an assumption
00131             
00132             yaw = atan2(diff_last[1],diff_last[0]); // TODO redundant right now, not yet finished
00133             if (backwards)
00134                 yaw = g2o::normalize_theta(yaw + M_PI);
00135             addPoseAndTimeDiff(curr_point, yaw ,timestep);
00136             
00137             ++idx;
00138       }
00139       Eigen::Vector2d diff = goal_position-Pose(idx).position();
00140       double diff_norm = diff.norm();
00141       double timestep_vel = diff_norm/max_vel_x; // constant velocity
00142       if (max_acc_x)
00143       {
00144             double timestep_acc = sqrt(2*diff_norm/(*max_acc_x)); // constant acceleration
00145             if (timestep_vel < timestep_acc) timestep = timestep_acc;
00146             else timestep = timestep_vel;
00147       }
00148       else timestep = timestep_vel;
00149 
00150       
00151       PoseSE2 goal(goal_position, goal_orient);
00152       
00153       // if number of samples is not larger than min_samples, insert manually
00154       if ( sizePoses() < min_samples-1 )
00155       {
00156         ROS_DEBUG("initTEBtoGoal(): number of generated samples is less than specified by min_samples. Forcing the insertion of more samples...");
00157         while (sizePoses() < min_samples-1) // subtract goal point that will be added later
00158         {
00159           // simple strategy: interpolate between the current pose and the goal
00160           addPoseAndTimeDiff( PoseSE2::average(BackPose(), goal), timestep ); // let the optimier correct the timestep (TODO: better initialization     
00161         }
00162       }
00163       
00164       // now add goal
00165       addPoseAndTimeDiff(goal, timestep); // add goal point
00166       setPoseVertexFixed(sizePoses()-1,true); // GoalConf is a fixed constraint during optimization
00167     }
00168     else // size!=0
00169     {
00170       ROS_WARN("Cannot init TEB between given configuration and goal, because TEB vectors are not empty or TEB is already initialized (call this function before adding states yourself)!");
00171       ROS_WARN("Number of TEB configurations: %d, Number of TEB timediffs: %d", sizePoses(), sizeTimeDiffs());
00172       return false;
00173     }
00174     return true;
00175 }  
00176   
00177 
00178 } // namespace teb_local_planner
00179 
00180 
00181 


teb_local_planner
Author(s): Christoph Rösmann
autogenerated on Sat Jun 8 2019 20:21:34