00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ros/ros.h"
00023 #include "geometry_msgs/Twist.h"
00024 #include "sensor_msgs/LaserScan.h"
00025 #include "../laserscan/LaserScanner.h"
00026 #include "nav_msgs/Odometry.h"
00027 #include "tf/tf.h"
00028 #include <fstream>
00029
00030 using namespace std;
00031
00032 sensor_msgs::LaserScan _scanMsg;
00033 ros::Publisher velocity_publisher;
00034 ros::Subscriber scanSubscriber;
00035
00036 ros::Subscriber pose_subscriber;
00037
00038 nav_msgs::Odometry turtlebot_odom_pose;
00039 nav_msgs::Odometry obstacle_pose;
00040
00041
00042 void scanCallback (sensor_msgs::LaserScan scanMessage);
00043
00044 void poseCallback(const nav_msgs::Odometry::ConstPtr & pose_message);
00045 bool GoToGoal(nav_msgs::Odometry goal_pose, double distance_tolerance);
00046 double getDistance(double x1, double y1, double x2, double y2);
00047 nav_msgs::Odometry setGoalPosition(double x, double y);
00048 double minDistanceToObstacle();
00049 double avoidObstacle(double speed, double desiredSafeDistanceToObstacle);
00050 void hardSwitches(nav_msgs::Odometry goal_pose);
00051 bool blendedBehavior(nav_msgs::Odometry goal_pose, double distance_tolerance);
00052
00053 int main(int argc, char **argv){
00054
00055
00056 ros::init(argc, argv, "laser_stopper_node");
00057 ros::NodeHandle n;
00058
00059
00060 scanSubscriber = n.subscribe("/scan", 10, scanCallback);
00061
00062 pose_subscriber = n.subscribe("/odom", 10, poseCallback);
00063
00064 velocity_publisher =n.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop", 1000);
00065
00066
00067 ros::spinOnce();
00068 ros::Rate loop(1);
00069 loop.sleep();
00070 ros::spinOnce();
00071 nav_msgs::Odometry goal_pose = setGoalPosition(0.45, 2.55);
00072
00073 blendedBehavior(goal_pose, 0.75);
00074
00075 ros::spin();
00076 return 0;
00077 }
00078
00079 bool blendedBehavior(nav_msgs::Odometry goal_pose, double distance_tolerance){
00080 geometry_msgs::Twist vel_msg;
00081
00082 ros::Rate loop_rate(100);
00083 double E = 0.0;
00084 double Xr=0.0;
00085 double Yr=0.0;
00086 double Xg=0.0;
00087 double Yg=0.0;
00088 double Xo=0.0;
00089 double Yo=0.0;
00090
00091 double Xg_bl=0.0;
00092 double Yg_bl=0.0;
00093
00094 double sigma_gtg = 0.65;
00095
00096 do{
00097
00098
00099 double Kp_gtg=1.0;
00100 double Kp_oa=1.2;
00101 double Kp_gtg_angvel=4.0;
00102 double Kp_oa_angvel=1.0;
00103
00104
00105
00106
00107
00108 Xr = turtlebot_odom_pose.pose.pose.position.x;
00109 Yr = turtlebot_odom_pose.pose.pose.position.y;
00110 double theta = tf::getYaw(turtlebot_odom_pose.pose.pose.orientation);
00111
00112
00113 Xg = goal_pose.pose.pose.position.x;
00114 Yg = goal_pose.pose.pose.position.y;
00115
00116
00117 double distObst = LaserScanner::getFrontRange(_scanMsg);
00118
00119
00120 Xo=Xr+(distObst*cos(theta));
00121 Yo=Yr+(distObst*sin(theta));
00122
00123
00124 double Xop=Xr+(distObst*cos(theta+(PI/2)));
00125 double Yop=Yr+(distObst*sin(theta+(PI/2)));
00126 ROS_INFO("xo= %.2f, yo= %.2f | xop= %.2f, yop= %.2f", Xo, Yo,
00127 Xop, Yop);
00128
00129 Xg_bl=((1.0-sigma_gtg)*Xop)+(sigma_gtg*Xg);
00130 Yg_bl=((1.0-sigma_gtg)*Yop)+(sigma_gtg*Yg);
00131
00132 ROS_INFO("xblend= %.2f, yblend= %.2f | xr=%.2f, yr=%.2f, theta=%.2f", Xg_bl, Yg_bl,
00133 Xr,Yr,theta);
00134 double e_gtg = getDistance(Xr, Yr, Xg,Yg);
00135 double e_oa = getDistance(Xr, Yr, Xop,Yop);
00136
00137
00138
00139 double ang_vel_oa = Kp_oa_angvel*abs(atan2(Yop-Yr, Xop-Xr)-theta);
00140 double ang_vel_gtg = Kp_gtg_angvel*(atan2(Yg-Yr, Xg-Xr)-theta);
00141
00142
00143
00144 vel_msg.angular.x = 0;
00145 vel_msg.angular.y = 0;
00146 vel_msg.angular.z =((1-sigma_gtg)*ang_vel_oa)+((sigma_gtg)*ang_vel_gtg);
00147
00148
00149 double linear_vel_oa = (Kp_oa*e_oa)/ang_vel_oa;
00150 double linear_vel_gtg = (Kp_gtg*e_gtg);
00151 vel_msg.linear.x = ((1-sigma_gtg)*linear_vel_oa)+((sigma_gtg)*linear_vel_gtg);
00152
00153 vel_msg.linear.y =0;
00154 vel_msg.linear.z =0;
00155
00156
00157 velocity_publisher.publish(vel_msg);
00158
00159
00160 ros::spinOnce();
00161
00162 loop_rate.sleep();
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 }while(ros::ok()&&getDistance(Xr, Yr, Xg,Yg)>distance_tolerance);
00173 cout<<"end move goal"<<endl;
00174 vel_msg.linear.x =0;
00175 vel_msg.angular.z = 0;
00176 velocity_publisher.publish(vel_msg);
00177 return true;
00178
00179 }
00180
00181 void hardSwitches(nav_msgs::Odometry goal_pose){
00182
00183
00184 bool destinationReached=false;
00185 do{
00186 ROS_INFO("Enter GoToGoal avoid mode\n");
00187 destinationReached=GoToGoal(goal_pose, 0.3);
00188 if(!destinationReached){
00189 ROS_INFO("The robot did reach its destination. Enter ObstacleAvoidance mode\n");
00190 avoidObstacle(-1, 1.0);
00191 ROS_INFO("Obstacle avoided\n");
00192 }
00193 }while(!destinationReached);
00194
00195 ROS_INFO("The robot reached its destination\n");
00196
00197 }
00198
00199 nav_msgs::Odometry setGoalPosition(double x, double y){
00200 nav_msgs::Odometry goal_pose;
00201 goal_pose.pose.pose.position.x=0.45;
00202 goal_pose.pose.pose.position.y=2.55;
00203
00204 goal_pose.pose.pose.orientation.w=0;
00205 goal_pose.pose.pose.orientation.x=0;
00206 goal_pose.pose.pose.orientation.y=0;
00207 goal_pose.pose.pose.orientation.z=1;
00208
00209 return goal_pose;
00210 }
00211
00212 void poseCallback(const nav_msgs::Odometry::ConstPtr & pose_message){
00213 turtlebot_odom_pose.pose.pose.position.x=pose_message->pose.pose.position.x;
00214 turtlebot_odom_pose.pose.pose.position.y=pose_message->pose.pose.position.y;
00215 turtlebot_odom_pose.pose.pose.position.z=pose_message->pose.pose.position.z;
00216
00217 turtlebot_odom_pose.pose.pose.orientation.w=pose_message->pose.pose.orientation.w;
00218 turtlebot_odom_pose.pose.pose.orientation.x=pose_message->pose.pose.orientation.x;
00219 turtlebot_odom_pose.pose.pose.orientation.y=pose_message->pose.pose.orientation.y;
00220 turtlebot_odom_pose.pose.pose.orientation.z=pose_message->pose.pose.orientation.z;
00221 }
00222
00223 double getDistance(double x1, double y1, double x2, double y2){
00224 return sqrt(pow((x1-x2),2)+pow((y1-y2),2));
00225 }
00226
00227 void scanCallback (sensor_msgs::LaserScan scanMessage){
00228 _scanMsg = scanMessage;
00229
00230 }
00231
00236 void move(double speed, double distance, bool isForward){
00237 geometry_msgs::Twist vel_msg;
00238
00239 if (isForward)
00240 vel_msg.linear.x =abs(speed);
00241 else
00242 vel_msg.linear.x =-abs(speed);
00243 vel_msg.linear.y =0;
00244 vel_msg.linear.z =0;
00245
00246 vel_msg.angular.x = 0;
00247 vel_msg.angular.y = 0;
00248 vel_msg.angular.z =0;
00249
00250 double t0 = ros::Time::now().toSec();
00251 double current_distance = 0.0;
00252 ros::Rate loop_rate(100);
00253 do{
00254 velocity_publisher.publish(vel_msg);
00255 double t1 = ros::Time::now().toSec();
00256 current_distance = speed * (t1-t0);
00257 ros::spinOnce();
00258 loop_rate.sleep();
00259
00260 }while(current_distance<distance);
00261 vel_msg.linear.x =0;
00262 velocity_publisher.publish(vel_msg);
00263
00264 }
00265
00266 double avoidObstacle(double speed, double desiredSafeDistanceToObstacle){
00267
00270 int start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(20));
00271 int end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(25));
00272 double LR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00273 ROS_INFO("LR: %.2f start %d, end %d", LR, start_index, end_index);
00274
00275
00276 start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-5));
00277 end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(5));
00278 double SR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00279 ROS_INFO("SR: %.2f start %d, end %d", SR, start_index, end_index);
00280
00281 start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-25));
00282 end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-20));
00283 double RR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00284 ROS_INFO("RR: %.2f, start %d, end %d", RR, start_index, end_index);
00285
00286
00287
00288
00289 geometry_msgs::Twist vel_msg;
00290
00291 vel_msg.linear.x =-abs(speed);
00292 vel_msg.linear.y =0;
00293 vel_msg.linear.z =0;
00294
00295 vel_msg.angular.x = 0;
00296 vel_msg.angular.y = 0;
00297 if (RR<LR){
00298 vel_msg.angular.z =1.0;
00299 }
00300 else if (RR>LR){
00301 vel_msg.angular.z =-1.0;
00302 }
00303 else
00304 vel_msg.angular.z =0.0;
00305
00306 double t0 = ros::Time::now().toSec();
00307 double current_distance = 0.0;
00308 ros::Rate loop_rate(100);
00309 do{
00310 velocity_publisher.publish(vel_msg);
00311 double t1 = ros::Time::now().toSec();
00312 current_distance = speed * (t1-t0);
00313 ros::spinOnce();
00314 loop_rate.sleep();
00315
00316 }while(minDistanceToObstacle()<desiredSafeDistanceToObstacle);
00317 vel_msg.linear.x =0;
00318 velocity_publisher.publish(vel_msg);
00319 ros::spinOnce();
00320
00321 return minDistanceToObstacle();
00322
00323 }
00324
00325 bool GoToGoal(nav_msgs::Odometry goal_pose, double distance_tolerance){
00326
00327 geometry_msgs::Twist vel_msg;
00328
00329 ros::Rate loop_rate(100);
00330 double E = 0.0;
00331 double Xr=0.0;
00332 double Yr=0.0;
00333 double Xg=0.0;
00334 double Yg=0.0;
00335 ofstream outfile;
00336 outfile.open("distancelog.cvs");
00337 do{
00338
00339
00340 double Kp_v=1.0;
00341 double Kp_w=4.0;
00342
00343
00344 Xr = turtlebot_odom_pose.pose.pose.position.x;
00345 Yr = turtlebot_odom_pose.pose.pose.position.y;
00346
00347
00348 Xg = goal_pose.pose.pose.position.x;
00349 Yg = goal_pose.pose.pose.position.y;
00350
00351 double e = getDistance(Xr, Yr, Xg,Yg);
00352
00353 double theta_robot = tf::getYaw(turtlebot_odom_pose.pose.pose.orientation);
00354 double theta_goal = atan2(Yg-Yr, Xg-Xr);
00355
00356
00357
00358 vel_msg.linear.x = (Kp_v*e)/abs(Kp_w*(theta_goal-theta_robot));
00359 vel_msg.linear.y =0;
00360 vel_msg.linear.z =0;
00361
00362
00363 vel_msg.angular.x = 0;
00364 vel_msg.angular.y = 0;
00365 vel_msg.angular.z =Kp_w*(theta_goal-theta_robot);
00366
00367
00368 velocity_publisher.publish(vel_msg);
00369
00370 ros::spinOnce();
00371
00372 loop_rate.sleep();
00373
00374 if (minDistanceToObstacle()<0.7){
00375 ROS_INFO("Goal could not be reached. Stopped because of an obstacle\n");
00376 vel_msg.linear.x =0;
00377 vel_msg.angular.z = 0;
00378 velocity_publisher.publish(vel_msg);
00379 ros::spinOnce();
00380 return false;
00381 }
00382
00383
00384
00385
00386 outfile << e << endl;
00387
00388
00389 }while(getDistance(Xr, Yr, Xg,Yg)>distance_tolerance);
00390 outfile.close();
00391 ROS_INFO("Goal is reached. Mission completed\n");
00392 vel_msg.linear.x =0;
00393 vel_msg.angular.z = 0;
00394 velocity_publisher.publish(vel_msg);
00395 return true;
00396 }
00397
00398 double minDistanceToObstacle(){
00399
00400 return LaserScanner::getMinimumRange(_scanMsg);
00401
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475