laser_stop.cpp
Go to the documentation of this file.
00001 /*
00002  *  Gaitech Educational Portal
00003  *
00004  * Copyright (c) 2016
00005  * All rights reserved.
00006  *
00007  * License Type: GNU GPL
00008  *
00009  *   This program is free software: you can redistribute it and/or modify
00010  *   it under the terms of the GNU General Public License as published by
00011  *   the Free Software Foundation, either version 3 of the License, or
00012  *   (at your option) any later version.
00013  *   This program is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 //void reactive_navigation();
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         //initialize the ROS node
00056         ros::init(argc, argv, "laser_stopper_node");
00057         ros::NodeHandle n;
00058 
00059         //subscribe to the laser scanner topic
00060         scanSubscriber = n.subscribe("/scan", 10, scanCallback);
00061         //subscribe to the odometry topic to get the position of the robot
00062         pose_subscriber = n.subscribe("/odom", 10, poseCallback);
00063         //register the velocity publisher
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         //hardSwitches(goal_pose);
00073         blendedBehavior(goal_pose, 0.75);
00074         //GoToGoal(goal_pose, 0.4);
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                 /****** Proportional Controller ******/
00098                 //linear velocity in the x-axis
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                 //double Ki=0.02;
00104                 //double v0 = 2.0;
00105                 //double alpha = 0.5;
00106 
00107                 //robot pose
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                 //goal pose
00113                 Xg = goal_pose.pose.pose.position.x;
00114                 Yg = goal_pose.pose.pose.position.y;
00115 
00116                 //obstacle pose
00117                 double distObst = LaserScanner::getFrontRange(_scanMsg);
00118                 //distObst = LaserScanner::getFrontRange(_scanMsg);
00119                 //double angle_to_obstacle = 0;
00120                 Xo=Xr+(distObst*cos(theta));
00121                 Yo=Yr+(distObst*sin(theta));
00122 
00123                 //opposite obstacle pose
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                 //blended goal position
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                 //double E = E+e;
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                 //angular velocity in the z-axis
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                 //vel_msg.angular.z = Kp_gtg_angvel*(atan2(Yg-Yr, Xg-Xr)-theta);
00148                 //Kp = v0 * (exp(-alpha)*error*error)/(error*error);
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                 //vel_msg.linear.x = Kp_gtg*e_gtg;
00153                 vel_msg.linear.y =0;
00154                 vel_msg.linear.z =0;
00155 
00156                 //ROS_INFO("e= %.2f, angle_error= %.2f ", e, vel_msg.angular.z/4.0);
00157                 velocity_publisher.publish(vel_msg);
00158 
00159 
00160                 ros::spinOnce();
00161 
00162                 loop_rate.sleep();
00163                 /*if (minDistanceToObstacle()<0.7){
00164                         cout<<"end move goal"<<endl;
00165                         vel_msg.linear.x =0;
00166                         vel_msg.angular.z = 0;
00167                         velocity_publisher.publish(vel_msg);
00168                         ros::spinOnce();
00169                         return false;
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         //reactive_navigation ();
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         //cout<<scanMessage.ranges[0]<<endl;
00230 }
00231 
00236 void move(double speed, double distance, bool isForward){
00237         geometry_msgs::Twist vel_msg;
00238         //set a random linear velocity in the x-axis
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         //set a random angular velocity in the y-axis
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                 //cout<<(t1-t0)<<", "<<current_distance <<", "<<distance<<endl;
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         //set a random linear velocity in the x-axis
00291         vel_msg.linear.x =-abs(speed);
00292         vel_msg.linear.y =0;
00293         vel_msg.linear.z =0;
00294         //set a random angular velocity in the y-axis
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                 //cout<<(t1-t0)<<", "<<current_distance <<", "<<distance<<endl;
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                 /****** Proportional Controller ******/
00339                 //gains of the proportional controllers
00340                 double Kp_v=1.0;
00341                 double Kp_w=4.0;
00342 
00343                 //get coordinates of the robot
00344                 Xr = turtlebot_odom_pose.pose.pose.position.x;
00345                 Yr = turtlebot_odom_pose.pose.pose.position.y;
00346 
00347                 //get the coordinates of the goal location
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                 //double E = E+e;
00353                 double theta_robot = tf::getYaw(turtlebot_odom_pose.pose.pose.orientation);
00354                 double theta_goal = atan2(Yg-Yr, Xg-Xr);
00355                 //Kp = v0 * (exp(-alpha)*error*error)/(error*error);
00356 
00357                 //linear velocity control
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                 //angular velocity control
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                 //publish the velocity message
00368                 velocity_publisher.publish(vel_msg);
00369 
00370                 ros::spinOnce();
00371 
00372                 loop_rate.sleep();
00373                 //watch dog
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                 //Statistics
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 void reactive_navigation(){
00406 
00407         geometry_msgs::Twist velocity_message;
00408 
00409         ros::Rate loop_rate(10); //in hertz
00410         loop_rate.sleep();
00411         ros::spinOnce();
00412         double last_velocity=0.0;
00413         while (ros::ok()){
00414                 loop_rate.sleep();
00415                 ros::spinOnce();
00416                 int start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(20));
00417                 int end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(25));
00418                 double LR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00419                 ROS_INFO("LR: %.2f start %d, end %d", LR, start_index, end_index);
00420 
00421 
00422                 start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-5));
00423                 end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(5));
00424                 double SR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00425                 ROS_INFO("SR: %.2f start %d, end %d", SR, start_index, end_index);
00426 
00427                 start_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-25));
00428                 end_index = LaserScanner::Angle2Index(_scanMsg, degree2radian(-20));
00429                 double RR = LaserScanner::getAverageRange(_scanMsg, start_index, end_index);
00430                 ROS_INFO("RR: %.2f, start %d, end %d", RR, start_index, end_index);
00431 
00432 
00433                 ROS_INFO("min_range:");
00434                 double w = 2.0;
00435                 if (LaserScanner::getMinimumRange(_scanMsg)<0.7){
00436                         velocity_message.linear.x=-1.0;
00437                         last_velocity = -1.0;
00438                         //velocity_message.angular.z=2*w;
00439                 }else  if (LaserScanner::getMinimumRange(_scanMsg)>1.5){
00440                         velocity_message.linear.x=1.0;
00441                         last_velocity = 1.0;
00442                         //velocity_message.angular.z=2*w;
00443                 }else{
00444                         velocity_message.linear.x=last_velocity;
00445                 }
00446 
00447 
00448                 velocity_message.linear.y=0;
00449                 velocity_message.linear.z=0;
00450                 velocity_message.angular.x=0;
00451                 velocity_message.angular.y=0;
00452 
00453 
00454                 if (SR<1.0){
00455                         velocity_message.angular.z=2*w/SR;
00456                 }
00457                 if(LR-RR>1.0){
00458                         ROS_INFO("turn left");
00459                         velocity_message.angular.z=w;
00460                 }else if(LR-RR<1.0){
00461                         ROS_INFO("turn right");
00462                         velocity_message.angular.z=-w;
00463                 }else{
00464                         velocity_message.angular.z=0;
00465                 }
00466 
00467                 velocity_publisher.publish(velocity_message);
00468 
00469                 loop_rate.sleep();
00470                 ros::spinOnce();
00471         }
00472 
00473 
00474 }
00475  */


gapter
Author(s):
autogenerated on Thu Jun 6 2019 22:05:13