PatrolAgent.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2014, 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: David Portugal (2011-2014), and Luca Iocchi (2014-2016)
00036 *********************************************************************/
00037 
00038 #include <sstream>
00039 #include <string>
00040 #include <ros/ros.h>
00041 #include <ros/package.h> //to get pkg path
00042 #include <move_base_msgs/MoveBaseAction.h>
00043 #include <actionlib/client/simple_action_client.h>
00044 #include <tf/transform_broadcaster.h>
00045 #include <tf/transform_listener.h>
00046 #include <nav_msgs/Odometry.h>
00047 #include <std_srvs/Empty.h>
00048 
00049 #include "PatrolAgent.h"
00050 
00051 using namespace std;
00052 
00053 #define DELTA_TIME_SEQUENTIAL_START 15
00054 #define SIMULATE_FOREVER true //WARNING: Set this to false, if you want a finishing condition.
00055 
00056 const std::string PS_path = ros::package::getPath("patrolling_sim");    //D.Portugal => get pkg path
00057 
00058 
00059 void PatrolAgent::init(int argc, char** argv) {
00060         /*
00061             argv[0]=/.../patrolling_sim/bin/GBS
00062             argv[1]=__name:=XXXXXX
00063             argv[2]=grid
00064             argv[3]=ID_ROBOT
00065         */
00066     
00067     srand ( time(NULL) );
00068     
00069     //More than One robot (ID between 0 and 99)
00070     if ( atoi(argv[3])>NUM_MAX_ROBOTS || atoi(argv[3])<-1 ){
00071         ROS_INFO("The Robot's ID must be an integer number between 0 an 99"); //max 100 robots 
00072         return;
00073     }else{
00074         ID_ROBOT = atoi(argv[3]); 
00075         //printf("ID_ROBOT = %d\n",ID_ROBOT); //-1 for 1 robot without prefix (robot_0)
00076     }
00077     
00079     chdir(PS_path.c_str());
00080                 
00081     mapname = string(argv[2]);
00082     graph_file = "maps/"+mapname+"/"+mapname+".graph";
00083     
00084     //Check Graph Dimension:
00085     dimension = GetGraphDimension(graph_file.c_str());
00086     
00087     //Create Structure to save the Graph Info;
00088     vertex_web = new vertex[dimension];
00089     
00090     //Get the Graph info from the Graph File
00091     GetGraphInfo(vertex_web, dimension, graph_file.c_str());
00092     
00093     
00094     uint nedges = GetNumberEdges(vertex_web,dimension);
00095     
00096     printf("Loaded graph %s with %d nodes and %d edges\n",mapname.c_str(),dimension,nedges);
00097 
00098 #if 0
00099     /* Output Graph Data */   
00100     for (i=0;i<dimension;i++){
00101         printf ("ID= %u\n", vertex_web[i].id);
00102         printf ("X= %f, Y= %f\n", vertex_web[i].x, vertex_web[i].y);
00103         printf ("#Neigh= %u\n", vertex_web[i].num_neigh);
00104         
00105         for (j=0;j<vertex_web[i].num_neigh; j++){
00106         printf("\tID = %u, DIR = %s, COST = %u\n", vertex_web[i].id_neigh[j], vertex_web[i].dir[j], vertex_web[i].cost[j]);
00107         }
00108         
00109         printf("\n");   
00110     }
00111 #endif
00112       
00113     interference = false;
00114     ResendGoal = false;
00115     goal_complete = true;
00116     last_interference = 0;
00117     goal_canceled_by_user = false;
00118     aborted_count = 0;
00119     resend_goal_count = 0;
00120     communication_delay = 0.0;
00121     lost_message_rate = 0.0;
00122     goal_reached_wait = 0.0;
00123     /* Define Starting Vertex/Position (Launch File Parameters) */
00124 
00125     ros::init(argc, argv, "patrol_agent");  // will be replaced by __name:=XXXXXX
00126     ros::NodeHandle nh;
00127     
00128     // wait a random time (avoid conflicts with other robots starting at the same time...)
00129     double r = 3.0 * ((rand() % 1000)/1000.0);
00130     ros::Duration wait(r); // seconds
00131     wait.sleep();
00132     
00133     double initial_x, initial_y;
00134     std::vector<double> list;
00135     nh.getParam("initial_pos", list);
00136     
00137     if (list.empty()){
00138      ROS_ERROR("No initial positions given: check \"initial_pos\" parameter.");
00139      ros::shutdown();
00140      exit(-1);
00141     }
00142        
00143     int value = ID_ROBOT;
00144     if (value == -1){value = 0;}
00145     
00146     initial_x = list[2*value];
00147     initial_y = list[2*value+1];
00148     
00149     //   printf("initial position: x = %f, y = %f\n", initial_x, initial_y);
00150     current_vertex = IdentifyVertex(vertex_web, dimension, initial_x, initial_y);
00151     //   printf("initial vertex = %d\n\n",current_vertex);  
00152     
00153     
00154     //instantaneous idleness and last visit initialized with zeros:
00155     instantaneous_idleness = new double[dimension];
00156     last_visit = new double[dimension];
00157     for(size_t i=0; i<dimension; i++){ 
00158         instantaneous_idleness[i]= 0.0; 
00159         last_visit[i]= 0.0; 
00160         
00161         if (i==current_vertex){
00162             last_visit[i]= 0.1; //Avoids getting back at the initial vertex
00163         }
00164         //ROS_INFO("last_visit[%d]=%f", i, last_visit[i]);
00165     }
00166         
00167     //Publicar dados de "odom" para nó de posições
00168     positions_pub = nh.advertise<nav_msgs::Odometry>("positions", 1); //only concerned about the most recent
00169         
00170     //Subscrever posições de outros robots
00171     positions_sub = nh.subscribe<nav_msgs::Odometry>("positions", 10, boost::bind(&PatrolAgent::positionsCB, this, _1));  
00172     
00173     char string1[40];
00174     char string2[40];
00175     
00176     if(ID_ROBOT==-1){ 
00177         strcpy (string1,"odom"); //string = "odom"
00178         strcpy (string2,"cmd_vel"); //string = "cmd_vel"
00179         TEAMSIZE = 1;
00180     }else{ 
00181         sprintf(string1,"robot_%d/odom",ID_ROBOT);
00182         sprintf(string2,"robot_%d/cmd_vel",ID_ROBOT);
00183         TEAMSIZE = ID_ROBOT + 1;
00184     }   
00185 
00186     /* Set up listener for global coordinates of robots */
00187     listener = new tf::TransformListener();
00188 
00189     //Cmd_vel to backup:
00190     cmd_vel_pub  = nh.advertise<geometry_msgs::Twist>(string2, 1);
00191     
00192     //Subscrever para obter dados de "odom" do robot corrente
00193     odom_sub = nh.subscribe<nav_msgs::Odometry>(string1, 1, boost::bind(&PatrolAgent::odomCB, this, _1)); //size of the buffer = 1 (?)
00194     
00195     ros::spinOnce(); 
00196     
00197     //Publicar dados para "results"
00198     results_pub = nh.advertise<std_msgs::Int16MultiArray>("results", 100);
00199     // results_sub = nh.subscribe("results", 10, resultsCB); //Subscrever "results" vindo dos robots
00200     results_sub = nh.subscribe<std_msgs::Int16MultiArray>("results", 100, boost::bind(&PatrolAgent::resultsCB, this, _1) ); //Subscrever "results" vindo dos robots
00201 
00202     // last time comm delay has been applied
00203     last_communication_delay_time = ros::Time::now().toSec();   
00204 
00205     readParams();
00206 }
00207     
00208 void PatrolAgent::ready() {
00209     
00210     char move_string[40];
00211     
00212     /* Define Goal */
00213     if(ID_ROBOT==-1){ 
00214         strcpy (move_string,"move_base"); //string = "move_base
00215     }else{
00216         sprintf(move_string,"robot_%d/move_base",ID_ROBOT);
00217     }
00218     
00219     ac = new MoveBaseClient(move_string, true); 
00220     
00221     //wait for the action server to come up
00222     while(!ac->waitForServer(ros::Duration(5.0))){
00223         ROS_INFO("Waiting for the move_base action server to come up");
00224     } 
00225     ROS_INFO("Connected with move_base action server");    
00226     
00227     initialize_node(); //announce that agent is alive
00228     
00229     ros::Rate loop_rate(1); //1 sec
00230     
00231     /* Wait until all nodes are ready.. */
00232     while(initialize){
00233         ros::spinOnce();
00234         loop_rate.sleep();
00235     }    
00236 
00237 }
00238 
00239 
00240 void PatrolAgent::readParams() {
00241 
00242     if (! ros::param::get("/goal_reached_wait", goal_reached_wait)) {
00243       //goal_reached_wait = 0.0;
00244       ROS_WARN("Cannot read parameter /goal_reached_wait. Using default value!");
00245       //ros::param::set("/goal_reached_wait", goal_reached_wait);
00246     }
00247 
00248     if (! ros::param::get("/communication_delay", communication_delay)) {
00249       //communication_delay = 0.0;
00250       ROS_WARN("Cannot read parameter /communication_delay. Using default value!");
00251       //ros::param::set("/communication_delay", communication_delay);
00252     } 
00253 
00254     if (! ros::param::get("/lost_message_rate", lost_message_rate)) {
00255       //lost_message_rate = 0.0;
00256       ROS_WARN("Cannot read parameter /lost_message_rate. Using default value!");
00257       //ros::param::set("/lost_message_rate", lost_message_rate);
00258     }
00259 
00260     if (! ros::param::get("/initial_positions", initial_positions)) {
00261       //initial_positions = "default";
00262       ROS_WARN("Cannot read parameter /initial_positions. Using default value '%s'!", initial_positions.c_str());
00263       //ros::param::set("/initial_pos", initial_positions);
00264     }
00265 
00266 }
00267 
00268 void PatrolAgent::run() {
00269     
00270     // get ready
00271     ready();
00272     
00273     //initially clear the costmap (to make sure the robot is not trapped):
00274     std_srvs::Empty srv;
00275     std::string mb_string;
00276      
00277      if (ID_ROBOT>-1){
00278              std::ostringstream id_string;
00279              id_string << ID_ROBOT;
00280              mb_string = "robot_" + id_string.str() + "/";
00281     }
00282     mb_string += "move_base/clear_costmaps";
00283     
00284     if (ros::service::call(mb_string.c_str(), srv)){
00285     //if (ros::service::call("move_base/clear_costmaps", srv)){
00286         ROS_INFO("Costmap correctly cleared before patrolling task.");
00287     }else{
00288         ROS_WARN("Was not able to clear costmap (%s) before patrolling...", mb_string.c_str());
00289     }
00290     
00291     // Asynch spinner (non-blocking)
00292     ros::AsyncSpinner spinner(2); // Use n threads
00293     spinner.start();
00294 //     ros::waitForShutdown();
00295 
00296     /* Run Algorithm */ 
00297     
00298     ros::Rate loop_rate(30); //0.033 seconds or 30Hz
00299     
00300     while(ros::ok()){
00301         
00302         if (goal_complete) {
00303             onGoalComplete();  // can be redefined
00304             resend_goal_count=0;
00305         }
00306         else { // goal not complete (active)
00307             if (interference) {
00308                 do_interference_behavior();
00309             }       
00310             
00311             if (ResendGoal) {
00312                 //Send the goal to the robot (Global Map)
00313                 if (resend_goal_count<3) {
00314                     resend_goal_count++;
00315                     ROS_INFO("Re-Sending goal (%d) - Vertex %d (%f,%f)", resend_goal_count, next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00316                     sendGoal(next_vertex);
00317                 }
00318                 else {
00319                     resend_goal_count=0;
00320                     onGoalNotComplete();
00321                 }
00322                 ResendGoal = false; //para nao voltar a entrar (envia goal so uma vez)
00323             }
00324             
00325             processEvents();
00326             
00327             if (end_simulation) {
00328                 return;
00329             }   
00330         
00331         } // if (goal_complete)
00332         
00333                 loop_rate.sleep(); 
00334 
00335     } // while ros.ok    
00336 }
00337 
00338 
00339 void PatrolAgent::onGoalComplete()
00340 {
00341     if(next_vertex>-1) {
00342         //Update Idleness Table:
00343         update_idleness();
00344         current_vertex = next_vertex;       
00345     }
00346     
00347     //devolver proximo vertex tendo em conta apenas as idlenesses;
00348     next_vertex = compute_next_vertex();
00349     //printf("Move Robot to Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00350 
00352     send_goal_reached(); // Send TARGET to monitor
00353     send_results();  // Algorithm specific function
00354 
00355     //Send the goal to the robot (Global Map)
00356     ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00357     //sendGoal(vertex_web[next_vertex].x, vertex_web[next_vertex].y);  
00358     sendGoal(next_vertex);  // send to move_base
00359     
00360     goal_complete = false;    
00361 }
00362 
00363 void PatrolAgent::onGoalNotComplete()
00364 {   
00365     int prev_vertex = next_vertex;
00366     
00367     ROS_INFO("Goal not complete - From vertex %d to vertex %d\n", current_vertex, next_vertex);   
00368     
00369     //devolver proximo vertex tendo em conta apenas as idlenesses;
00370     next_vertex = compute_next_vertex();
00371     //printf("Move Robot to Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00372 
00373     // Look for a random adjacent vertex different from the previous one
00374     int random_cnt=0;
00375     while (next_vertex == prev_vertex && random_cnt++<10) {
00376         int num_neighs = vertex_web[current_vertex].num_neigh;
00377         int i = rand() % num_neighs;
00378         next_vertex = vertex_web[current_vertex].id_neigh[i];
00379         ROS_INFO("Choosing another random vertex %d\n", next_vertex);
00380     }
00381     
00382     // Look for any random vertex different from the previous one
00383     while (next_vertex == prev_vertex && next_vertex == current_vertex) {
00384         int i = rand() % dimension;
00385         next_vertex = i;
00386         ROS_INFO("Choosing another random vertex %d\n", next_vertex);
00387     }
00388 
00389     //Send the goal to the robot (Global Map)
00390     ROS_INFO("Re-Sending NEW goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00391     //sendGoal(vertex_web[next_vertex].x, vertex_web[next_vertex].y);  
00392     sendGoal(next_vertex);  // send to move_base
00393     
00394     goal_complete = false;    
00395 }
00396 
00397 
00398 void PatrolAgent::processEvents() {
00399     
00400 }
00401 
00402 void PatrolAgent::update_idleness() {
00403     double now = ros::Time::now().toSec();
00404         
00405     for(size_t i=0; i<dimension; i++){
00406         if ((int)i == next_vertex){
00407             last_visit[i] = now;    
00408         }
00409         instantaneous_idleness[i] = now - last_visit[i];           
00410         
00411         //Show Idleness Table:
00412         //ROS_INFO("idleness[%u] = %f",i,instantaneous_idleness[i]);
00413     }
00414 }
00415 
00416 void PatrolAgent::initialize_node (){ //ID,msg_type,1
00417     
00418     int value = ID_ROBOT;
00419     if (value==-1){value=0;}
00420     ROS_INFO("Initialize Node: Robot %d",value); 
00421     
00422     std_msgs::Int16MultiArray msg;   
00423     msg.data.clear();
00424     msg.data.push_back(value);
00425     msg.data.push_back(INITIALIZE_MSG_TYPE);
00426     msg.data.push_back(1);  // Robot initialized
00427     
00428     int count = 0;
00429     
00430     //ATENÇÃO ao PUBLICADOR!
00431     ros::Rate loop_rate(0.5); //meio segundo
00432     
00433     while (count<3){ //send activation msg 3times
00434         results_pub.publish(msg);
00435         //ROS_INFO("publiquei msg: %s\n", msg.data.c_str());
00436         ros::spinOnce();
00437         loop_rate.sleep();
00438         count++;
00439     }
00440 }
00441 
00442 void PatrolAgent::getRobotPose(int robotid, float &x, float &y, float &theta) {
00443     
00444     if (listener==NULL) {
00445         ROS_ERROR("TF listener null");
00446         return;
00447     }
00448     
00449     std::stringstream ss; ss << "robot_" << robotid;
00450     std::string robotname = ss.str();
00451     std::string sframe = "/map";                //Patch David Portugal: Remember that the global map frame is "/map"
00452     std::string dframe;
00453     if(ID_ROBOT>-1){
00454         dframe = "/" + robotname + "/base_link";
00455     }else{
00456         dframe = "/base_link";
00457     }
00458     
00459     tf::StampedTransform transform;
00460 
00461     try {
00462         listener->waitForTransform(sframe, dframe, ros::Time(0), ros::Duration(3));
00463         listener->lookupTransform(sframe, dframe, ros::Time(0), transform);
00464     }
00465     catch(tf::TransformException ex) {
00466         ROS_ERROR("Cannot transform from %s to %s\n",sframe.c_str(),dframe.c_str());
00467         ROS_ERROR("%s", ex.what());
00468     }
00469 
00470     x = transform.getOrigin().x();
00471     y = transform.getOrigin().y();
00472     theta = tf::getYaw(transform.getRotation());
00473     // printf("Robot %d pose : %.1f %.1f \n",robotid,x,y);
00474 }
00475 
00476 void PatrolAgent::odomCB(const nav_msgs::Odometry::ConstPtr& msg) { //colocar propria posicao na tabela
00477     
00478 //  printf("Colocar Propria posição na tabela, ID_ROBOT = %d\n",ID_ROBOT);
00479     int idx = ID_ROBOT;
00480     
00481     if (ID_ROBOT<=-1){
00482         idx = 0;
00483     }
00484     
00485     float x,y,th;
00486     getRobotPose(idx,x,y,th);
00487     
00488     xPos[idx]=x; // msg->pose.pose.position.x;
00489     yPos[idx]=y; // msg->pose.pose.position.y;
00490     
00491 //  printf("Posicao colocada em Pos[%d]\n",idx);
00492 }
00493 
00494 
00495 
00496 void PatrolAgent::sendGoal(int next_vertex) 
00497 {
00498     goal_canceled_by_user = false;
00499     
00500     double target_x = vertex_web[next_vertex].x, 
00501            target_y = vertex_web[next_vertex].y;
00502     
00503     //Define Goal:
00504     move_base_msgs::MoveBaseGoal goal;
00505     //Send the goal to the robot (Global Map)
00506     geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);     
00507     goal.target_pose.header.frame_id = "map"; 
00508     goal.target_pose.header.stamp = ros::Time::now();    
00509     goal.target_pose.pose.position.x = target_x; // vertex_web[current_vertex].x;
00510     goal.target_pose.pose.position.y = target_y; // vertex_web[current_vertex].y;  
00511     goal.target_pose.pose.orientation = angle_quat; //doesn't matter really.
00512     ac->sendGoal(goal, boost::bind(&PatrolAgent::goalDoneCallback, this, _1, _2), boost::bind(&PatrolAgent::goalActiveCallback,this), boost::bind(&PatrolAgent::goalFeedbackCallback, this,_1));  
00513 }
00514 
00515 void PatrolAgent::cancelGoal() 
00516 {
00517     goal_canceled_by_user = true;
00518     ac->cancelAllGoals();
00519 }
00520 
00521 
00522 void PatrolAgent::goalDoneCallback(const actionlib::SimpleClientGoalState &state, const move_base_msgs::MoveBaseResultConstPtr &result){ //goal terminado (completo ou cancelado)
00523 //  ROS_INFO("Goal is complete (suceeded, aborted or cancelled).");
00524     // If the goal succeeded send a new one!
00525     //if(state.state_ == actionlib::SimpleClientGoalState::SUCCEEDED) sendNewGoal = true;
00526     // If it was aborted time to back up!
00527     //if(state.state_ == actionlib::SimpleClientGoalState::ABORTED) needToBackUp = true;    
00528     
00529     if(state.state_ == actionlib::SimpleClientGoalState::SUCCEEDED){
00530         ROS_INFO("Goal reached ... WAITING %.2f sec",goal_reached_wait);
00531         ros::Duration delay(goal_reached_wait); // wait after goal is reached
00532         delay.sleep();
00533         ROS_INFO("Goal reached ... DONE");
00534         goal_complete = true;
00535     }else{
00536         aborted_count++;
00537         ROS_INFO("CANCELLED or ABORTED... %d",aborted_count);   //tentar voltar a enviar goal..
00538         if (!goal_canceled_by_user) {
00539             ROS_INFO("Goal not cancelled by the interference...");
00540 
00541             //ROS_INFO("Backup");
00542             backup();
00543 
00544             ROS_INFO("Clear costmap!");
00545 
00546             char srvname[80];
00547             
00548             if(ID_ROBOT<=-1){
00549                 sprintf(srvname,"/move_base/clear_costmaps");
00550             }else{
00551                 sprintf(srvname,"/robot_%d/move_base/clear_costmaps",ID_ROBOT);
00552             }
00553             
00554             ros::NodeHandle n;
00555             ros::ServiceClient client = n.serviceClient<std_srvs::Empty>(srvname);
00556             std_srvs::Empty srv;
00557             if (client.call(srv)) {
00558                 ROS_INFO("Costmaps cleared.\n");
00559             }
00560             else {
00561                 ROS_ERROR("Failed to call service move_base/clear_costmaps");
00562             }
00563 
00564             ROS_INFO("Resend Goal!");
00565             ResendGoal = true;
00566         }
00567     }
00568 }
00569 
00570 void PatrolAgent::goalActiveCallback(){  //enquanto o robot esta a andar para o goal...
00571     goal_complete = false;
00572 //      ROS_INFO("Goal is active.");
00573 }
00574 
00575 void PatrolAgent::goalFeedbackCallback(const move_base_msgs::MoveBaseFeedbackConstPtr &feedback){    //publicar posições
00576 
00577     send_positions();
00578     
00579     int value = ID_ROBOT;
00580     if (value==-1){ value = 0;}
00581     interference = check_interference(value);    
00582 }
00583 
00584 void PatrolAgent::send_goal_reached() {
00585     
00586     int value = ID_ROBOT;
00587     if (value==-1){ value = 0;}
00588     
00589     // [ID,msg_type,vertex,intention,0]
00590     std_msgs::Int16MultiArray msg;   
00591     msg.data.clear();
00592     msg.data.push_back(value);
00593     msg.data.push_back(TARGET_REACHED_MSG_TYPE);
00594     msg.data.push_back(current_vertex);
00595     //msg.data.push_back(next_vertex);
00596     //msg.data.push_back(0); //David Portugal: is this necessary?
00597     
00598     results_pub.publish(msg);   
00599     ros::spinOnce();  
00600 }
00601 
00602 bool PatrolAgent::check_interference (int robot_id){ //verificar se os robots estao proximos
00603     
00604     int i;
00605     double dist_quad;
00606     
00607     if (ros::Time::now().toSec()-last_interference<10)  // seconds
00608         return false; // false if within 10 seconds from the last one
00609     
00610     /* Poderei usar TEAMSIZE para afinar */
00611     for (i=0; i<robot_id; i++){ //percorrer vizinhos (assim asseguro q cada interferencia é so encontrada 1 vez)
00612         
00613         dist_quad = (xPos[i] - xPos[robot_id])*(xPos[i] - xPos[robot_id]) + (yPos[i] - yPos[robot_id])*(yPos[i] - yPos[robot_id]);
00614         
00615         if (dist_quad <= INTERFERENCE_DISTANCE*INTERFERENCE_DISTANCE){    //robots are ... meter or less apart
00616 //          ROS_INFO("Feedback: Robots are close. INTERFERENCE! Dist_Quad = %f", dist_quad);
00617             last_interference = ros::Time::now().toSec();
00618             return true;
00619         }       
00620     }
00621     return false;
00622     
00623 }
00624 
00625 void PatrolAgent::backup(){
00626     
00627     ros::Rate loop_rate(100); // 100Hz
00628     
00629     int backUpCounter = 0;
00630     while (backUpCounter<=100){
00631     
00632       if(backUpCounter==0){
00633           ROS_INFO("The wall is too close! I need to do some backing up...");
00634           // Move the robot back...
00635           geometry_msgs::Twist cmd_vel;
00636           cmd_vel.linear.x = -0.1;
00637           cmd_vel.angular.z = 0.0;
00638           cmd_vel_pub.publish(cmd_vel);
00639       }
00640               
00641       if(backUpCounter==20){
00642           // Turn the robot around...
00643           geometry_msgs::Twist cmd_vel;
00644           cmd_vel.linear.x = 0.0;
00645           cmd_vel.angular.z = 0.5;
00646           cmd_vel_pub.publish(cmd_vel);
00647       }
00648               
00649       if(backUpCounter==100){
00650           // Stop the robot...
00651           geometry_msgs::Twist cmd_vel;
00652           cmd_vel.linear.x = 0.0;
00653           cmd_vel.angular.z = 0.0;
00654           cmd_vel_pub.publish(cmd_vel);
00655               
00656           // ROS_INFO("Done backing up, now on with my life!");      
00657       }
00658 
00659       ros::spinOnce();
00660       loop_rate.sleep();
00661       backUpCounter++;
00662     
00663     }
00664     
00665 }
00666 
00667 void PatrolAgent::do_interference_behavior()
00668 {
00669     ROS_INFO("Interference detected! Executing interference behavior...\n");   
00670     send_interference();  // send interference to monitor for counting
00671     
00672 #if 1
00673     // Stop the robot..         
00674     cancelGoal();
00675     ROS_INFO("Robot stopped");
00676     ros::Duration delay(3); // seconds
00677     delay.sleep();
00678     ResendGoal = true;
00679 #else    
00680     //get own "odom" positions...
00681     ros::spinOnce();        
00682                 
00683     //Waiting until conflict is solved...
00684     int value = ID_ROBOT;
00685     if (value == -1){ value = 0;}
00686     while(interference){
00687         interference = check_interference(value);
00688         if (goal_complete || ResendGoal){
00689             interference = false;
00690         }
00691     }
00692 #endif
00693 }
00694 
00695 
00696 
00697 
00698 // ROBOT-ROBOT COMMUNICATION
00699 
00700 
00701 
00702 void PatrolAgent::send_positions()
00703 {
00704     //Publish Position to common node:
00705     nav_msgs::Odometry msg; 
00706     
00707     int idx = ID_ROBOT;
00708 
00709     if (ID_ROBOT <= -1){
00710         msg.header.frame_id = "map";    //identificador do robot q publicou
00711         idx = 0;
00712     }else{
00713         char string[20];
00714         sprintf(string,"robot_%d/map",ID_ROBOT);
00715         msg.header.frame_id = string;
00716     }
00717 
00718     msg.pose.pose.position.x = xPos[idx]; //send odometry.x
00719     msg.pose.pose.position.y = yPos[idx]; //send odometry.y
00720   
00721     positions_pub.publish(msg);
00722     ros::spinOnce();
00723 }
00724 
00725 
00726 void PatrolAgent::receive_positions()
00727 {
00728     
00729 }
00730 
00731 void PatrolAgent::positionsCB(const nav_msgs::Odometry::ConstPtr& msg) { //construir tabelas de posições
00732         
00733 //     printf("Construir tabela de posicoes (receber posicoes), ID_ROBOT = %d\n",ID_ROBOT);    
00734         
00735     char id[20]; //identificador do robot q enviou a msg d posição...
00736     strcpy( id, msg->header.frame_id.c_str() );
00737     //int stamp = msg->header.seq;
00738 //     printf("robot q mandou msg = %s\n", id);
00739     
00740     // Build Positions Table
00741     
00742     if (ID_ROBOT>-1){
00743     //verify id "XX" of robot: (string: "robot_XX/map")
00744     
00745         char str_idx[4];
00746         uint i;
00747         
00748         for (i=6; i<10; i++){
00749             if (id[i]=='/'){
00750                 str_idx[i-6] = '\0';
00751                 break;
00752             }else{
00753                 str_idx[i-6] = id[i];
00754             }
00755         }
00756         
00757         int idx = atoi (str_idx);
00758     //  printf("id robot q mandou msg = %d\n",idx);
00759         
00760         if (idx >= TEAMSIZE && TEAMSIZE <= NUM_MAX_ROBOTS){
00761             //update teamsize:
00762             TEAMSIZE = idx+1;
00763         }
00764         
00765         if (ID_ROBOT != idx){  //Ignore own positions   
00766             xPos[idx]=msg->pose.pose.position.x;
00767             yPos[idx]=msg->pose.pose.position.y;        
00768         }   
00769 //      printf ("Position Table:\n frame.id = %s\n id_robot = %d\n xPos[%d] = %f\n yPos[%d] = %f\n\n", id, idx, idx, xPos[idx], idx, yPos[idx] );       
00770     }
00771     
00772     receive_positions();
00773 }
00774 
00775 
00776 void PatrolAgent::send_results() { 
00777 
00778 }
00779 
00780 // simulates blocking send operation with delay in communication
00781 void PatrolAgent::do_send_message(std_msgs::Int16MultiArray &msg) {
00782         if (communication_delay>0.001) {
00783         //double current_time = ros::Time::now().toSec();
00784         //if (current_time-last_communication_delay_time>1.0) { 
00785                 //ROS_INFO("Communication delay %.1f",communication_delay);
00786                 ros::Duration delay(communication_delay); // seconds
00787                 delay.sleep();
00788                 //last_communication_delay_time = current_time;
00789         //}
00790     }    
00791     results_pub.publish(msg);
00792     ros::spinOnce();
00793 }
00794 
00795 
00796 void PatrolAgent::receive_results() {
00797 
00798 }
00799 
00800 void PatrolAgent::send_interference(){
00801     //interference: [ID,msg_type]
00802     
00803     int value = ID_ROBOT;
00804     if (value==-1){value=0;}
00805     printf("Send Interference: Robot %d\n",value);   
00806     
00807     std_msgs::Int16MultiArray msg;   
00808     msg.data.clear();
00809     msg.data.push_back(value);
00810     msg.data.push_back(INTERFERENCE_MSG_TYPE);
00811     
00812     results_pub.publish(msg);   
00813     ros::spinOnce();
00814 }
00815 
00816 
00817 
00818 
00819 void PatrolAgent::resultsCB(const std_msgs::Int16MultiArray::ConstPtr& msg) { 
00820     
00821     std::vector<signed short>::const_iterator it = msg->data.begin();    
00822     
00823     vresults.clear();
00824     
00825     for (size_t k=0; k<msg->data.size(); k++) {
00826         vresults.push_back(*it); it++;
00827     } 
00828 
00829     int id_sender = vresults[0];
00830     int msg_type = vresults[1];
00831     
00832     //printf(" MESSAGE FROM %d TYPE %d ...\n",id_sender, msg_type);
00833     
00834     // messages coming from the monitor
00835     if (id_sender==-1 && msg_type==INITIALIZE_MSG_TYPE) {
00836         if (initialize==true && vresults[2]==100) {   //"-1,msg_type,100,seq_flag" (BEGINNING)
00837             ROS_INFO("Let's Patrol!\n");
00838             double r = 1.0 * ((rand() % 1000)/1000.0);
00839 
00840             //TODO if sequential start
00841             //r = DELTA_TIME_SEQUENTIAL_START * ID_ROBOT;
00842 
00843             ros::Duration wait(r); // seconds
00844 
00845             printf("Wait %.1f seconds (init pos:%s)\n",r,initial_positions.c_str());
00846 
00847             wait.sleep();
00848             initialize = false;
00849         }
00850 
00851 #if SIMULATE_FOREVER == false
00852         if (initialize==false && vresults[2]==999) {   //"-1,msg_type,999" (END)
00853             ROS_INFO("The simulation is over. Let's leave");
00854             end_simulation = true;     
00855         }
00856 #endif        
00857     }
00858     
00859     if (!initialize) {
00860 #if 0
00861         // communication delay
00862         if(ID_ROBOT>-1){
00863             if ((communication_delay>0.001) && (id_sender!=ID_ROBOT)) {
00864                     double current_time = ros::Time::now().toSec();
00865                     if (current_time-last_communication_delay_time>1.0) { 
00866                             ROS_INFO("Communication delay %.1f",communication_delay);
00867                             ros::Duration delay(communication_delay); // seconds
00868                             delay.sleep();
00869                             last_communication_delay_time = current_time;
00870                 }
00871             }
00872             bool lost_message = false;
00873             if ((lost_message_rate>0.0001)&& (id_sender!=ID_ROBOT)) {
00874                 double r = (rand() % 1000)/1000.0;
00875                 lost_message = r < lost_message_rate;
00876             }
00877             if (lost_message) {
00878                 ROS_INFO("Lost message");
00879             }
00880         }
00881 #endif
00882             receive_results();
00883     }
00884 
00885     ros::spinOnce();
00886   
00887 }


patrolling_sim
Author(s):
autogenerated on Thu Jun 6 2019 20:27:09