traxbot_stageSimulation.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2012, ISR University of Coimbra.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the ISR University of Coimbra nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: André Araújo, 2012
00036 *********************************************************************/
00037 
00038 
00039 
00040 // STD LIB
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044 #include <string.h>
00045 #include <unistd.h>
00046 //#include <time.h>
00047 //#include "traxbot/traxbot.h"
00048 
00049 
00050 // ROS LIB
00051 #include <ros/ros.h>                            // Includes all the headers necessary to use the most common public pieces of the ROS system.
00052 #include <ros/time.h>
00053 #include <std_msgs/String.h>
00054 #include <std_msgs/Float32.h>
00055 #include <std_msgs/Int8.h>
00056 #include <std_msgs/Int16.h>
00057 #include <std_msgs/Bool.h>
00058 #include <std_msgs/Empty.h>
00059 #include <geometry_msgs/Point32.h>
00060 #include <geometry_msgs/Twist.h>
00061 #include <nav_msgs/Odometry.h>
00062 #include <sensor_msgs/LaserScan.h>
00063 
00064 #define PI 3.14159265
00065 
00066 #define sonarSamples 4
00067 #define maxRange 1.5
00068 #define rotateSpeed 0.4
00069 #define moveSpeed 0.3
00070 #define reactiveRange 0.5
00071 
00072 #define navigation REACTIVE             // COGNITIVE
00073 
00074 ros::Publisher cmd_velocidade;
00075 
00076 ros::Subscriber odm_stage;
00077 ros::Subscriber sonarsRange_stage;
00078 
00079 
00080 sensor_msgs::LaserScan sonarsRange;
00081 // nav_msgs::Odometry odometry;
00082 
00083 // Global odometry from stage
00084 float leftSonar, rightSonar, centerSonar;
00085 float x=0, y=0;         // Global position
00086 double theta=0;         // Global orientation
00087 double thetaPol=0;      // Global angle polarization in stage
00088 
00089 // Global odometry from goTo()
00090 float x_goTo=0, y_goTo=0, theta_goTo=0;         // Global position
00091 
00092 
00093 
00094 void odom_readCB(const nav_msgs::Odometry::ConstPtr& odom) {    
00095   
00096   x = odom->pose.pose.position.x;
00097   y = odom->pose.pose.position.y;
00098   theta = odom->pose.pose.orientation.w;       // This represents an orientation in free space in quaternion form.  alfa=2*(acos(w)) in degrees
00099   thetaPol = odom->pose.pose.orientation.z;       // Theta polarization
00100 
00101 
00102 //   printf("theta real %f\n", theta);
00103   
00104 }
00105 
00106 
00107 float minValue(int ini_idx, int final_idx, float tab[], float maxValue ) {       // return min value from each samples array range from sonar
00108   
00109   int idx;
00110   float min= tab[ini_idx];
00111 
00112   for (idx=ini_idx; idx < final_idx; idx++) {
00113     
00114     if (tab[idx] < maxValue && tab[idx] < min) {
00115       
00116        min = tab[idx];
00117     }
00118   }
00119   return min;
00120 }
00121 
00122 
00123 
00124 void sonars_readCB(const sensor_msgs::LaserScan::ConstPtr& range) {             // Read 4 samples from laser, and calculate min read value
00125   
00126   float tab[3*sonarSamples];
00127   
00128   for (int i=0; i<3*sonarSamples; i++){
00129     tab[i]=range->ranges[i];
00130   }
00131   
00132   rightSonar = minValue(0, sonarSamples, tab, maxRange);
00133   centerSonar = minValue(sonarSamples, 2*sonarSamples, tab, maxRange);
00134   leftSonar = minValue(2*sonarSamples, 3*sonarSamples, tab, maxRange);
00135   
00136 //   printf("right %f, center %f, left %f \n", rightSonar, centerSonar, leftSonar );
00137 
00138 }
00139 
00140 
00141 double quaternion2degrees(double angle, double polarization) {          // convert quaternion value to degrees, 
00142                                                                         // angle in quaternion value in nav_msgs::Odometry at pose.pose.orientation.w 
00143                                                                         // angle polarization in nav_msgs::Odometry at pose.pose.orientation.z 
00144                                                                         
00145   double angle_degrees;
00146   int fact=0;
00147   
00148   angle_degrees=2*( (acos (angle) * 180) / PI );
00149   
00150   if (polarization < 0) {
00151     fact=-1;
00152   } else {
00153     fact=1;
00154   }
00155   
00156   return angle_degrees=fact*angle_degrees;
00157 }
00158 
00159 
00160 
00161 void move(float distance, float speed){ // Stage linear move speed  0.1 to 0.5, distance in meters
00162   
00163    printf("START MOVE()\n");
00164    printf("Goal distance %f\n", distance);
00165    
00166    float calDist, x0 , y0;
00167    
00168    x0= x;
00169    y0= y;
00170    calDist= 0;
00171    
00172    geometry_msgs::Twist speedM;
00173    
00174    speedM.linear.x= speed;
00175    
00176    distance=distance-(moveSpeed/10); // offset
00177    
00178    while( calDist < distance ){                       // Start loop to turn motors
00179      
00180       calDist=sqrt( pow(x-x0,2) + pow(y-y0,2) );
00181 
00182       cmd_velocidade.publish(speedM);
00183       ros::spinOnce(); 
00184 
00185       printf("Actual distance %f\n", calDist);
00186   }
00187   
00188   // Stop
00189   speedM.linear.x= 0;
00190   cmd_velocidade.publish(speedM);
00191   ros::spinOnce(); 
00192   
00193   printf("FINISH MOVE()\n");
00194 }
00195 
00196 
00197 
00198 void rotate(float angle_deg, float speed){      // Stage rotation angle in degres between 180 to -180 , speed  0.1 to 0.5
00199   
00200    printf("START ROTATE()\n");
00201    
00202    double ang=0;
00203    float finalAng=0;
00204    int direction=0;
00205 
00206  //  printf("Rotate %f degrees. Goal position %f degrees\n", angle_deg, finalAng);      ////////////////////////////////////////////////
00207    
00208    
00209    geometry_msgs::Twist speedR;
00210    
00211    if (angle_deg < 0 ){
00212      angle_deg=angle_deg+(rotateSpeed*10); // offset because the time to stop in  while loop
00213      speedR.angular.z= -speed;
00214      direction = -1;
00215      printf("Rotate to right.");
00216    } else {
00217      angle_deg=angle_deg-(rotateSpeed*10); // offset because the time to stop in  while loop
00218      speedR.angular.z= speed;
00219      direction = 1;
00220      printf("Rotate to left.");
00221    }
00222    
00223    
00224    finalAng = quaternion2degrees( theta, thetaPol ) + angle_deg;
00225    
00226    if ( finalAng > 180 ) {              // only accept values between -180 and 180
00227      
00228      finalAng = finalAng - 360;
00229    
00230     } else if ( finalAng < (-180) ) { 
00231       
00232       finalAng = finalAng + 360;
00233     }
00234    
00235    
00236    ang = quaternion2degrees( theta , thetaPol);         // Update actual angle 
00237    
00238 
00239    
00241   if( direction > 0 ) {
00242     
00243     if ( ang > 0 && finalAng < 0 ) {                    // In case of trasition 180 to -180
00244       
00245       while (ang > finalAng){
00246         cmd_velocidade.publish(speedR);
00247         ros::spinOnce();
00248         ang= quaternion2degrees( theta , thetaPol);
00249         printf("Actual angle %f\n", ang);
00250         printf("final ang %f\n", finalAng);
00251        
00252         if (ang < 0 ) {                                 // In transition when go from positive to negavite: (ang > finalAng) -> (ang < finalAng)
00253          
00254           while (ang < finalAng){
00255               cmd_velocidade.publish(speedR);
00256               ros::spinOnce();
00257               ang= quaternion2degrees( theta , thetaPol);
00258               printf("Actual angle %f\n", ang);
00259               printf("final ang %f\n", finalAng);
00260           }
00261          break;
00262          }
00263        }
00264       
00265       } else {            // Rotate to reach is goal 
00266 
00267         while( ang < finalAng ){                       
00268           cmd_velocidade.publish(speedR);
00269           ros::spinOnce(); 
00270           ang= quaternion2degrees( theta , thetaPol);
00271           printf("Actual angle %f\n", ang);
00272           printf("final ang %f\n", finalAng);
00273         }
00274       }
00275     
00276   } else {
00277   
00279   
00280    if ( ang < 0 && finalAng > 0 ) {                     // In case of trasition 180 to -180
00281 
00282      while (ang < finalAng){
00283        cmd_velocidade.publish(speedR);
00284        ros::spinOnce();
00285        ang= quaternion2degrees( theta , thetaPol);
00286        printf("Actual angle %f\n", ang);
00287        printf("final ang %f\n", finalAng);
00288      }
00289       
00290     } else {                                            // Rotate to reach is goal 
00291               
00292       while( ang > finalAng ){                       
00293         cmd_velocidade.publish(speedR);
00294         ros::spinOnce(); 
00295         ang= quaternion2degrees( theta , thetaPol);
00296         printf("Actual angle %f\n", ang);
00297         printf("final ang %f\n", finalAng);
00298        }
00299     }  
00300   
00301 }
00302 
00303   // Stop rotation
00304   speedR.angular.z= 0;
00305   cmd_velocidade.publish(speedR);
00306   ros::spinOnce(); 
00307   
00308   printf("FINISH ROTATE()\n");
00309 }
00310 
00311 
00312 void reactiveNavigation() {
00313 
00314   int cnt=0;
00315   
00316  geometry_msgs::Twist speedM;
00317  
00318  speedM.linear.x= moveSpeed ;
00319  
00320   while (cnt < 1000) {
00321 
00322       usleep(100000);
00323 
00324       printf("Moving....\n");
00325       cmd_velocidade.publish(speedM);
00326       ros::spinOnce();
00327       
00328       while (rightSonar <= reactiveRange || leftSonar<=reactiveRange || centerSonar<=reactiveRange) {           // Stop and rotate
00329         
00330         usleep(100000);
00331        
00332         //rotate(15,rotateSpeed);
00333         
00334         
00335         
00336         if (rightSonar <= leftSonar) {  
00337 
00338           while (centerSonar<=reactiveRange || rightSonar<=reactiveRange) {
00339             usleep(100000);
00340             rotate(10,rotateSpeed);
00341  
00342           }
00343 
00344           
00345         } else  {
00346 
00347           while (centerSonar<=reactiveRange || leftSonar<=reactiveRange) {
00348             usleep(100000);
00349             rotate(-10,rotateSpeed);
00350           }
00351         }
00352 
00353         printf("STOP reaction....\n");
00354       } // end while
00355         
00356         
00357         
00358       ++cnt;
00359     
00360   } // end main while
00361     
00362 
00363 }
00364 
00365 
00366 
00367 //void goTo(float xIni, float yIni, float teta, float xFinal, float yFinal){                    // GoTo modificado para movimentos continuos, ou seja a pose final mantem se para o 
00368 void goTo(float xIni, float yIni, float teta, float xFinal, float yFinal, float tetaFinal){     // para o ponto seguinte. Declarar globalmente x_goTo=0 ,y_goTo=0, theta_goTo=0; 
00369                                                                                                 // tetaFinal só é ajustado quando x e y iguais
00370   
00371   float dist=0, alfa=0, phi=0;
00372   
00373   printf("START GO TO()\n");
00374   
00375   
00376   
00377   if ( xIni==xFinal && yIni==yFinal) {          //  Quando está na mesma posição x y, está somente a rodar, ATENÇÃO não é pose final do movimento
00378 
00379       phi = tetaFinal - teta;
00380       rotate(phi,rotateSpeed);
00381     
00382      
00383   } else {
00384   
00385   dist=sqrt(pow(xFinal-xIni,2)+pow(yFinal-yIni,2));
00386   alfa=atan2((yFinal-yIni),(xFinal-xIni))*180.0/PI;
00387   phi=alfa-teta;
00388   
00389   //printf("dist:%f alfa:%f phi:%f \n", dist, alfa, phi);
00390               
00391   //1- ROTATE INTO THE FINAL POINT DIRECTION
00392   if (abs(phi)>180)
00393   {
00394    phi=phi-(abs(phi)/phi)*360.0;
00395   }
00396   
00397   printf("PHI ROTATION: %f \n", phi);
00398   rotate(phi,rotateSpeed);
00399 
00400   //2- MOVE IN A STRAIGHT LINE
00401   printf("LINEAR MOVE: %f \n", dist);
00402   move(dist,moveSpeed);
00403 
00404   }
00405 
00406   
00407   // Pose update
00408   x_goTo = xFinal;
00409   y_goTo = yFinal;
00410   theta_goTo = theta_goTo + phi;
00411 
00412   
00413   printf("PHI FINAL: %f \n", theta_goTo);
00414   printf("FINISH GO TO()\n");                   
00415 }
00416 
00417 
00418 int main(int argc, char** argv)
00419 {
00420   ros::init(argc, argv, "Virtual_TraxBot_Stage");
00421   ros::NodeHandle nh;
00422 
00423   ROS_INFO("ROS in TraxBot: Start ROS move in stage...");    // ROS_INFO(), replacement for printf/cout   
00424    
00425   
00426   /* Subscribe topics */
00427   sonarsRange_stage = nh.subscribe("/base_scan", 1, sonars_readCB);
00428   odm_stage = nh.subscribe("/odom", 1, odom_readCB);
00429   
00430   /* Advertise topics */
00431   cmd_velocidade = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
00432 
00433 
00434   ros::Rate loop_rate(10); //0.01 segundos 
00435   
00436   int count=0;
00437  
00438   
00439   
00440   while( ros::ok()){
00441   
00442     
00443     if (count == 10) {
00444       
00445       reactiveNavigation();
00446 
00447       
00448       
00449     }
00450   
00451     printf("count: %d\n",count);
00452     ++count;
00453     ros::spinOnce();
00454     loop_rate.sleep();
00455     
00456   }
00457    
00458 
00459 
00460     ROS_INFO("DONE");
00461 
00462 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


traxbot_robot
Author(s): André Gonçalves Araújo
autogenerated on Fri Feb 1 2013 13:21:12