purePursuitController.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  * Copyright (C) 2014 by Jerome Maye                                          *
00003  * jerome.maye@gmail.com                                                      *
00004  *                                                                            *
00005  * This program is free software; you can redistribute it and/or modify       *
00006  * it under the terms of the Lesser GNU General Public License as published by*
00007  * the Free Software Foundation; either version 3 of the License, or          *
00008  * (at your option) any later version.                                        *
00009  *                                                                            *
00010  * This program is distributed in the hope that it will be useful,            *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  * Lesser GNU General Public License for more details.                        *
00014  *                                                                            *
00015  * You should have received a copy of the Lesser GNU General Public License   *
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.       *
00017  ******************************************************************************/
00018 
00019 #include "pure_pursuit_controller/purePursuitController.h"
00020 
00021 #include <cmath>
00022 
00023 #include <geometry_msgs/Twist.h>
00024 
00025 #include <visualization_msgs/Marker.h>
00026 
00027 /******************************************************************************/
00028 /* Constructors and Destructor                                                */
00029 /******************************************************************************/
00030 
00031 PurePursuitControllerNode::PurePursuitControllerNode(const ros::NodeHandle &nh) :
00032     _nodeHandle(nh),
00033     _nextWayPoint(-1)
00034 {
00035    getParameters();
00036   _cmdVelocityPublisher = _nodeHandle.advertise<geometry_msgs::Twist>(_cmdVelocityTopicName, 1);
00037   _timer = nh.createTimer(ros::Duration(1.0 / _frequency), &PurePursuitControllerNode::timerCallback, this);
00038   _goTriExecute=_nodeHandle.advertiseService("/execute_goTri",&PurePursuitControllerNode::goTriExecute,this);
00039   _pathExecute = _nodeHandle.advertiseService("/execute_path",&PurePursuitControllerNode::pathExecute, this);
00040   _pathCancel=_nodeHandle.advertiseService("/cancel_path",&PurePursuitControllerNode::pathCancel,this);
00041   _pathCut=_nodeHandle.advertiseService("/cut_path",&PurePursuitControllerNode::pathCut,this);
00042   _finishGoTri=_nodeHandle.advertise<std_msgs::String>("finish_go_tri",1);
00043   isFinish = false;
00044   ifGoTrisector=false;
00045   ifFirstPoint=false;
00046   safeWayNum=std::numeric_limits<double>::max();
00047   //zlt
00048   //
00049 }
00050 
00051 PurePursuitControllerNode::~PurePursuitControllerNode()
00052 {
00053 
00054 }
00055 
00056 /******************************************************************************/
00057 /* Methods                                                                    */
00058 /******************************************************************************/
00059 // 由欧拉角创建四元数
00060 void PurePursuitControllerNode::angle2quat(vector<float> &angle, vector<float> &quaternion)
00061 {
00062   float cx = cos(angle[0] / 2);
00063   float sx = sin(angle[0] / 2);
00064   float cy = cos(angle[1] / 2);
00065   float sy = sin(angle[1] / 2);
00066   float cz = cos(angle[2] / 2);
00067   float sz = sin(angle[2] / 2);
00068 
00069   quaternion[0] = sx * cy * cz - cx * sy * sz; // x
00070   quaternion[1] = cx * sy * cz + sx * cy * sz; // y
00071   quaternion[2] = cx * cy * sz - sx * sy * cz; // z
00072   quaternion[3] = cx * cy * cz + sx * sy * sz; // w
00073 }
00074 //
00075 bool PurePursuitControllerNode::pathExecute(pure_pursuit_controller::executePath::Request &req,pure_pursuit_controller::executePath::Response &res)
00076 {
00077     resetParam();
00078     _currentReferencePath = req.curPath;
00079     ifFirstPoint=req.ifFirstPoint;
00080     ROS_INFO("receive path msg");
00081     res.success=true;
00082     return true;
00083 }
00084 
00085 bool PurePursuitControllerNode::goTriExecute(pure_pursuit_controller::executePath::Request &req,pure_pursuit_controller::executePath::Response &res)
00086 {
00087     resetParam();
00088     _currentReferencePath = req.curPath;
00089     ifFirstPoint=req.ifFirstPoint;
00090     ifGoTrisector=true;
00091     ROS_INFO("receive branch msg");
00092     res.success=true;
00093     return true;
00094 }
00095 
00096 bool PurePursuitControllerNode::pathCancel(pure_pursuit_controller::cancelPath::Request &req, pure_pursuit_controller::cancelPath::Response &res){
00097     resetParam();
00098     res.success=true;
00099     return true;
00100 }
00101 
00102 bool PurePursuitControllerNode::pathCut(pure_pursuit_controller::cutPath::Request &req, pure_pursuit_controller::cutPath::Response &res){
00103     safeWayNum=req.safeWayPoint;
00104     ifCutPath=true;
00105     res.success=true;
00106     return true;
00107 }
00108 
00109 void PurePursuitControllerNode::odometryCallback(const nav_msgs::Odometry &
00110                                                      msg)
00111 {
00112   _currentVelocity = msg.twist.twist;
00113 }
00114 
00115 void PurePursuitControllerNode::resetParam(){
00116     _nextWayPoint=-1;
00117     _currentReferencePath.poses.clear();
00118     safeWayNum=std::numeric_limits<int>::max();
00119     isFinish=false;
00120     ifFirstPoint=false;
00121     ifGoTrisector=false;
00122     ifCutPath=false;
00123 }
00124 
00125 void PurePursuitControllerNode::spin()
00126 {
00127   ros::spin();
00128 }
00129 
00130 void PurePursuitControllerNode::timerCallback(const ros::TimerEvent &
00131                                                   event)
00132 {
00133   if(_nextWayPoint>safeWayNum){
00134      resetParam();
00135      return ;
00136   }
00137   geometry_msgs::Twist cmdVelocity;
00138 
00139   if (step(cmdVelocity))
00140       _cmdVelocityPublisher.publish(cmdVelocity);
00141 
00142   if(ifGoTrisector){
00143       if(isFinish){
00144             //do something
00145           std_msgs::String msg;
00146           for(int i=0;i<2;i++)
00147             _finishGoTri.publish(msg);
00148           ifGoTrisector=false;
00149       }
00150   }
00151 
00152 }
00153 
00154 bool PurePursuitControllerNode::step(geometry_msgs::Twist &twist)
00155 {
00156   twist.linear.x = 0.0;
00157   twist.linear.y = 0.0;
00158   twist.linear.z = 0.0;
00159 
00160   twist.angular.x = 0.0;
00161   twist.angular.y = 0.0;
00162   twist.angular.z = 0.0;
00163 
00164   if(_currentReferencePath.poses.size()==0) return false;
00165 
00166   _nextWayPoint = getNextWayPoint(_nextWayPoint);
00167   if(_nextWayPoint>safeWayNum){
00168      resetParam();
00169      return false;
00170   }
00171 
00172   if (_nextWayPoint >= 0)
00173   {
00174     double angularVelocity = 0.0;
00175     double linearVelocity = _velocity;
00176     //
00177     geometry_msgs::PoseStamped origin = getCurrentPose();
00178     //
00179     double x = origin.pose.orientation.x;
00180     double y = origin.pose.orientation.y;
00181     double z = origin.pose.orientation.z;
00182     double w = origin.pose.orientation.w;
00183     double robot_angel = atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z));
00184 
00185     geometry_msgs::PoseStamped next= _currentReferencePath.poses[_nextWayPoint];
00186     double x1 = next.pose.position.x;
00187     double y1 = next.pose.position.y;
00188     double x0 = origin.pose.position.x;
00189     double y0 = origin.pose.position.y;
00190     double d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
00191     double distance = std::sqrt(d);
00192     // double r = distance / (2*std::sin(angle));
00193 
00194     //
00195     double line_angel = asin((y1 - y0) / distance);
00196     //
00197     if (line_angel > 0)
00198     {
00199       if (x1 < x0)
00200       {
00201         line_angel = M_PI - line_angel;
00202       }
00203     }
00204     else
00205     {
00206       if (x1 < x0)
00207       {
00208         line_angel = -M_PI - line_angel;
00209       }
00210       if (line_angel == -M_PI)
00211       {
00212         line_angel = M_PI;
00213       }
00214     }
00215 
00216     double angel = robot_angel - line_angel;
00217     double r = distance / (2 * std::sin(angel));
00218     angularVelocity = -linearVelocity / r;
00219 
00220 
00221     if(ifFirstPoint){
00222         twist.linear.x = 0;
00223         if(std::sin(angel)>0)
00224           twist.angular.z = -0.4;
00225         else
00226           twist.angular.z = 0.4;
00227         if (std::abs(angel) < M_PI/8)
00228             ifFirstPoint=false;
00229         return true;
00230     }
00231     twist.linear.x = linearVelocity;
00232     twist.angular.z = angularVelocity;
00233 
00234     return true;
00235   }
00236   return false;
00237 }
00238 
00239 geometry_msgs::PoseStamped PurePursuitControllerNode::getCurrentPose() const
00240 {
00241   geometry_msgs::PoseStamped pose, transformedPose;
00242   pose.header.frame_id = "base_footprint";
00243   pose.pose.position.x = 0;
00244   pose.pose.position.y = 0;
00245   pose.pose.position.z = 0;
00246   pose.pose.orientation.x = 0;
00247   pose.pose.orientation.y = 0;
00248   pose.pose.orientation.z = 0;
00249   pose.pose.orientation.w = 1;
00250   try
00251   {
00252     _tfListener.transformPose(_currentReferencePath.header.frame_id,
00253                               pose, transformedPose);
00254   }
00255   catch (tf::TransformException &exception)
00256   {
00257     ROS_ERROR("_poseFrameId: %s ", _poseFrameId.c_str());
00258   }
00259 
00260   return transformedPose;
00261 }
00262 
00263 
00264 double PurePursuitControllerNode::getLookAheadThreshold() const
00265 {
00266   return _lookAheadRatio * 0.1;
00267 }
00268 
00269 int PurePursuitControllerNode::getNextWayPoint(int wayPoint)
00270 {
00271   if (!_currentReferencePath.poses.empty())
00272   {
00273     if (_nextWayPoint >= 0)
00274     {
00275       geometry_msgs::PoseStamped origin = getCurrentPose();
00276       tf::Vector3 v_1(origin.pose.position.x,
00277                       origin.pose.position.y,
00278                       0);
00279       double lookAheadThreshold = getLookAheadThreshold();
00280 
00281       for (int i = _nextWayPoint; i < _currentReferencePath.poses.size();
00282            ++i)
00283       {
00284         tf::Vector3 v_2(_currentReferencePath.poses[i].pose.position.x,
00285                         _currentReferencePath.poses[i].pose.position.y,
00286                         0);
00287         if(ifCutPath){
00288             if (i >= safeWayNum-3)
00289             {
00290                 //ROS_INFO("Path finish!");
00291                 isFinish = true;
00292             }
00293         }else
00294         {
00295             if(_currentReferencePath.poses.size()>3){
00296                 if(ifGoTrisector){
00297                     if (i == _currentReferencePath.poses.size()-1)
00298                         isFinish = true;
00299 
00300                 }else{
00301                     if (i >= _currentReferencePath.poses.size()-3)
00302                         isFinish = true;
00303 
00304                 }
00305             }
00306         }
00307         if (tf::tfDistance(v_1, v_2) > lookAheadThreshold)
00308         {
00309           return i;
00310         }
00311       }
00312       if (_nextWayPoint == _currentReferencePath.poses.size()-1)
00313       {
00314           //ROS_INFO("Path finish!");
00315           isFinish = true;
00316       }
00317       return _nextWayPoint;
00318     }
00319     else
00320       return 0;
00321   }
00322 
00323   return -1;
00324 }
00325 
00326 void PurePursuitControllerNode::getParameters()
00327 {
00328   _nodeHandle.param<int>("pure_pursuit_controller/ros/queue_depth", _queueDepth, 100);
00329   _nodeHandle.param<std::string>("pure_pursuit_controller/ros/odometry_topic_name", _odometryTopicName, "/odom");
00330   _nodeHandle.param<std::string>("pure_pursuit_controller/ros/cmd_velocity_topic_name", _cmdVelocityTopicName, "/cmd_vel_mux/input/teleop");
00331   _nodeHandle.param<std::string>("pure_pursuit_controller/ros/pose_frame_id", _poseFrameId, "base_footprint");
00332 
00333   _nodeHandle.param<double>("pure_pursuit_controller/controller/frequency", _frequency, 20.0);
00334   _nodeHandle.param<int>("pure_pursuit_controller/controller/initial_waypoint", _initialWayPoint, -1);
00335   _nodeHandle.param<double>("pure_pursuit_controller/controller/velocity", _velocity, 0.2);
00336   _nodeHandle.param<double>("pure_pursuit_controller/controller/look_ahead_ratio", _lookAheadRatio, 3.0);
00337   _nodeHandle.param<double>("pure_pursuit_controller/controller/epsilon", _epsilon, 1e-6);
00338 }
00339 


pure_pursuit_controller
Author(s): Lintao Zheng, Kai Xu
autogenerated on Thu Jun 6 2019 19:50:45