00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00048
00049 }
00050
00051 PurePursuitControllerNode::~PurePursuitControllerNode()
00052 {
00053
00054 }
00055
00056
00057
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;
00070 quaternion[1] = cx * sy * cz + sx * cy * sz;
00071 quaternion[2] = cx * cy * sz - sx * sy * cz;
00072 quaternion[3] = cx * cy * cz + sx * sy * sz;
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
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
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
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
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