monitor.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 <sys/stat.h>
00039 #include <sys/types.h>
00040 #include <stdlib.h>
00041 #include <unistd.h>
00042 #include <time.h>
00043 #include <float.h>
00044 #include <fstream>
00045 #include <iostream>
00046 #include <string>
00047 
00048 #include <ros/ros.h>
00049 #include <ros/package.h> //to get pkg path
00050 #include <move_base_msgs/MoveBaseAction.h>
00051 #include <actionlib/client/simple_action_client.h>
00052 #include <tf/transform_broadcaster.h>
00053 #include <tf/transform_listener.h>
00054 #include <std_msgs/Int16MultiArray.h>
00055 #include <std_msgs/String.h>
00056 
00057 using namespace std;
00058 
00059 #include "getgraph.h"
00060 #include "message_types.h"
00061 #include "patrolling_sim/GoToStartPosSrv.h"
00062 
00063 #define NUM_MAX_ROBOTS 32
00064 #define DEAD_ROBOT_TIME 300.0 // (seconds) time from last goal reached after which a robot is considered dead
00065 #define TIMEOUT_WRITE_RESULTS 180.0 // (seconds) timeout for writing results to file 
00066 // For hystograms
00067 #define RESOLUTION 1.0 // seconds
00068 #define MAXIDLENESS 500.0 // seconds
00069 
00070 #define LOG_MONITOR 0
00071 #define SAVE_HYSTOGRAMS 0
00072 #define EXTENDED_STAGE 0
00073 
00074 #define SIMULATE_FOREVER true                   //WARNING: Set this to false, if you want a finishing condition.
00075 #define TIMEOUT_WRITE_RESULTS_FOREVER 900.0     // timeout for writing results to file when simulating forever
00076 
00077 using std::string;
00078 using std::cout;
00079 using std::endl;
00080 
00081 typedef unsigned int uint;
00082 
00083 ros::Subscriber results_sub;
00084 ros::Publisher results_pub, screenshot_pub;
00085 ros::ServiceServer GotoStartPosMethod;
00086 
00087 //Initialization:
00088 bool initialize = true; // Initialization flag
00089 bool goto_start_pos = false; //default: robots already start in right position
00090 uint cnt=0;  // Count number of robots connected
00091 uint teamsize;
00092 bool init_robots[NUM_MAX_ROBOTS];
00093 double last_goal_reached[NUM_MAX_ROBOTS];
00094 
00095 // mutex for accessing last_goal_reached vector
00096 pthread_mutex_t lock_last_goal_reached;
00097 
00098 //State Variables:
00099 bool goal_reached = false;
00100 
00101 int goal;
00102 double time_zero, last_report_time;
00103 time_t real_time_zero;
00104 double goal_reached_wait,comm_delay,lost_message_rate;
00105 string algorithm, algparams, nav_mod, initial_positions;
00106 
00107 const std::string PS_path = ros::package::getPath("patrolling_sim");    //D.Portugal => get pkg path
00108 
00109 
00110 #define MAX_DIMENSION 200
00111 
00112 /* ESTRUTURAS DE DADOS A CALCULAR */
00113 double last_visit [MAX_DIMENSION], current_idleness [MAX_DIMENSION], avg_idleness [MAX_DIMENSION], stddev_idleness [MAX_DIMENSION];
00114 double total_0 [MAX_DIMENSION], total_1 [MAX_DIMENSION],  total_2[MAX_DIMENSION];
00115 int number_of_visits [MAX_DIMENSION];
00116 size_t dimension; // graph size
00117 
00118 double worst_avg_idleness, avg_graph_idl, median_graph_idl, stddev_graph_idl, avg_stddev_graph_idl, previous_avg_graph_idl = DBL_MAX;
00119 // global measures
00120 double min_idleness = 0.0, max_idleness = 0.0;
00121 double gavg, gstddev;
00122 double gT0=0.0, gT1=0.0, gT2=0.0;
00123 
00124 uint interference_cnt = 0;
00125 uint complete_patrol = 0;
00126 uint patrol_cnt = 1;
00127 
00128 
00129 
00130 #if SAVE_HYSTOGRAMS
00131 #define hn ((int)(MAXIDLENESS/RESOLUTION)+1)
00132 int hsum;
00133 int hv[hn];
00134 #endif
00135 
00136 // Idleness file
00137 FILE *idlfile;
00138 
00139 // log file
00140 FILE *logfile = NULL;
00141 
00142 void dolog(const char *str) {
00143   if (logfile) {
00144     fprintf(logfile,"%s\n",str);
00145     fflush(logfile);
00146   }
00147 }
00148 
00149 void update_stats(int id_robot, int goal);
00150 
00151 
00152 double get_last_goal_reached(int k)
00153 {
00154   pthread_mutex_lock(&lock_last_goal_reached);
00155   double r = last_goal_reached[k];
00156   pthread_mutex_unlock(&lock_last_goal_reached);
00157   return r;
00158 }
00159 
00160 void set_last_goal_reached(int k, double val)
00161 {
00162   pthread_mutex_lock(&lock_last_goal_reached);
00163   last_goal_reached[k] = val;
00164   pthread_mutex_unlock(&lock_last_goal_reached);
00165 }
00166 
00167 
00168 void resultsCB(const std_msgs::Int16MultiArray::ConstPtr& msg) 
00169 {
00170     dolog("resultsCB - begin");
00171 
00172     std::vector<signed short>::const_iterator it = msg->data.begin();    
00173     
00174     std::vector<int> vresults;
00175     
00176     vresults.clear();
00177     
00178     for (size_t k=0; k<msg->data.size(); k++) {
00179         vresults.push_back(*it); it++;
00180     }
00181 
00182     int id_robot = vresults[0];  // robot sending the message
00183     int msg_type = vresults[1];  // message type
00184 
00185     switch(msg_type) {
00186         case INITIALIZE_MSG_TYPE:
00187         {
00188         if (initialize && vresults[2]==1){ 
00189             if (init_robots[id_robot] == false){   //receive init msg: "ID,msg_type,1"
00190                 printf("Robot [ID = %d] is Active!\n", id_robot);
00191                 init_robots[id_robot] = true;
00192                 
00193                 //Patch D.Portugal (needed to support other simulators besides Stage):
00194                 double current_time = ros::Time::now().toSec();
00195                 //initialize last_goal_reached:
00196                 set_last_goal_reached(id_robot,current_time);
00197                 
00198                 cnt++;
00199             } 
00200             if (cnt==teamsize){
00201                 
00202                 // check if robots need to travel to starting positions
00203                 while(goto_start_pos){ //if or while (?)
00204                     
00205                     patrolling_sim::GoToStartPosSrv::Request Req;
00206                     Req.teamsize.data = teamsize;
00207                     Req.sleep_between_goals.data = 20; //time in secs to wait before sending goals to each different robot
00208                     patrolling_sim::GoToStartPosSrv::Response Rep;      
00209                     
00210                     ROS_INFO("Sending all robots to starting position.");
00211                     
00212                     if (!ros::service::call("/GotoStartPosSrv", Req, Rep)){ //blocking call
00213                         ROS_ERROR("Error invoking /GotoStartPosSrv.");  
00214                         ROS_ERROR("Sending robots to initial position failed.");
00215                         ros::shutdown(); //make sense for while implementation
00216                         return;
00217                         
00218                     }else{
00219                         goto_start_pos = false;
00220                         system("rosnode kill GoToStartPos &");  //we don't need the service anymore.
00221                     }               
00222                     
00223                 }
00224                     
00225                 printf("All Robots GO!\n");
00226                 initialize = false;
00227                     
00228                 //Clock Reset:
00229                 time_zero = ros::Time::now().toSec();
00230                 last_report_time = time_zero; 
00231                                     
00232                 time (&real_time_zero);
00233                 printf("Time zero = %.1f (sim) = %lu (real) \n", time_zero,(long)real_time_zero);
00234 
00235                 std_msgs::Int16MultiArray msg;  // -1,msg_type,100,0,0
00236                 msg.data.clear();
00237                 msg.data.push_back(-1);
00238                 msg.data.push_back(INITIALIZE_MSG_TYPE);
00239                 msg.data.push_back(100);  // Go !!!
00240                 results_pub.publish(msg);
00241                 ros::spinOnce();      
00242                 
00243                 }
00244             }
00245             
00246         //}
00247         break;
00248         }
00249         
00250         case TARGET_REACHED_MSG_TYPE:
00251         {
00252             //goal sent by a robot during the experiment [ID,msg_type,vertex,intention,0]
00253             if (initialize==false){ 
00254                 goal = vresults[2];
00255                 ROS_INFO("Robot %d reached Goal %d.\n", id_robot, goal); 
00256                 fflush(stdout);
00257                 goal_reached = true;
00258                 update_stats(id_robot, goal);
00259                 ros::spinOnce();
00260             }
00261             break;
00262         }
00263          
00264         case INTERFERENCE_MSG_TYPE:
00265         {
00266             //interference: [ID,msg_type]
00267             if (initialize==false){
00268                 ROS_INFO("Robot %d sent interference.\n", id_robot); 
00269                 interference_cnt++;
00270                 ros::spinOnce();
00271             }
00272             break;
00273         }
00274     }
00275 
00276     dolog("resultsCB - end");
00277 
00278 }
00279 
00280 void finish_simulation (){ //-1,msg_type,999,0,0
00281   ROS_INFO("Sending stop signal to patrol agents.");
00282   std_msgs::Int16MultiArray msg;  
00283   msg.data.clear();
00284   msg.data.push_back(-1);
00285   msg.data.push_back(INITIALIZE_MSG_TYPE);
00286   msg.data.push_back(999);  // end of the simulation
00287   results_pub.publish(msg);
00288   ros::spinOnce();  
00289 
00290 #if EXTENDED_STAGE  
00291   ROS_INFO("Taking a screenshot of the simulator...");
00292   std_msgs::String ss;
00293   ss.data = "screenshot";
00294   screenshot_pub.publish(ss);
00295 #endif
00296   
00297   ros::spinOnce();  
00298 }
00299 
00300 // return the median value in a vector of size "dimension" floats pointed to by a
00301 double Median( double *a, uint dimension )
00302 {
00303    uint table_size = dimension/2;   
00304    if(dimension % 2 != 0){ //odd
00305    table_size++; 
00306    }   
00307    if (table_size==0) {table_size = 1;}
00308    
00309    double left[table_size], right[table_size], median, *p;
00310    unsigned char nLeft, nRight;
00311 
00312    // pick first value as median candidate
00313    p = a;
00314    median = *p++;
00315    nLeft = nRight = 1;
00316 
00317    for(;;)
00318    {
00319        // get next value
00320        double val = *p++;
00321 
00322        // if value is smaller than median, append to left heap
00323        if( val < median )
00324        {
00325            // move biggest value to the heap top
00326            unsigned char child = nLeft++, parent = (child - 1) / 2;
00327            while( parent && val > left[parent] )
00328            {
00329                left[child] = left[parent];
00330                child = parent;
00331                parent = (parent - 1) / 2;
00332            }
00333            left[child] = val;
00334 
00335            // if left heap is full
00336            if( nLeft == table_size )
00337            {
00338                // for each remaining value
00339                for( unsigned char nVal = dimension - (p - a); nVal; --nVal )
00340                {
00341                    // get next value
00342                    val = *p++;
00343 
00344                    // if value is to be inserted in the left heap
00345                    if( val < median )
00346                    {
00347                        child = left[2] > left[1] ? 2 : 1;
00348                        if( val >= left[child] )
00349                            median = val;
00350                        else
00351                        {
00352                            median = left[child];
00353                            parent = child;
00354                            child = parent*2 + 1;
00355                            while( child < table_size )
00356                            {
00357                                if( child < table_size-1 && left[child+1] > left[child] )
00358                                    ++child;
00359                                if( val >= left[child] )
00360                                    break;
00361                                left[parent] = left[child];
00362                                parent = child;
00363                                child = parent*2 + 1;
00364                            }
00365                            left[parent] = val;
00366                        }
00367                    }
00368                }
00369                return median;
00370            }
00371        }
00372 
00373        // else append to right heap
00374        else
00375        {
00376            // move smallest value to the heap top
00377            unsigned char child = nRight++, parent = (child - 1) / 2;
00378            while( parent && val < right[parent] )
00379            {
00380                right[child] = right[parent];
00381                child = parent;
00382                parent = (parent - 1) / 2;
00383            }
00384            right[child] = val;
00385 
00386            // if right heap is full
00387            if( nRight == 14 )
00388            {
00389                // for each remaining value
00390                for( unsigned char nVal = dimension - (p - a); nVal; --nVal )
00391                {
00392                    // get next value
00393                    val = *p++;
00394 
00395                    // if value is to be inserted in the right heap
00396                    if( val > median )
00397                    {
00398                        child = right[2] < right[1] ? 2 : 1;
00399                        if( val <= right[child] )
00400                            median = val;
00401                        else
00402                        {
00403                            median = right[child];
00404                            parent = child;
00405                            child = parent*2 + 1;
00406                            while( child < table_size )
00407                            {
00408                                if( child < 13 && right[child+1] < right[child] )
00409                                    ++child;
00410                                if( val <= right[child] )
00411                                    break;
00412                                right[parent] = right[child];
00413                                parent = child;
00414                                child = parent*2 + 1;
00415                            }
00416                            right[parent] = val;
00417                        }
00418                    }
00419                }
00420                return median;
00421            }
00422        }
00423    }
00424 }
00425 
00426 
00427 uint calculate_patrol_cycle ( int *nr_visits, uint dimension ){
00428   dolog("    calculate_patrol_cycle - begin");
00429   uint result = INT_MAX;
00430   uint imin=0;
00431   for (uint i=0; i<dimension; i++){
00432     if ((uint)nr_visits[i] < result){
00433       result = nr_visits[i]; imin=i;
00434     }
00435   }
00436   //printf("  --- complete patrol: visits of %d : %d\n",imin,result);
00437   dolog("    calculate_patrol_cycle - end");
00438   return result;  
00439 }
00440 
00441 void scenario_name(char* name, const char* graph_file, const char* teamsize_str)
00442 {
00443     uint i, start_char=0, end_char = strlen(graph_file)-1;
00444     
00445     for (i=0; i<strlen(graph_file); i++){
00446         if(graph_file[i]=='/' && i < strlen(graph_file)-1){
00447             start_char = i+1;
00448         }
00449         
00450         if(graph_file[i]=='.' && i>0){
00451             end_char = i-1;
00452             break;
00453         }
00454     }
00455     
00456     for (i=start_char; i<=end_char; i++){
00457         name [i-start_char] = graph_file [i];
00458         if (i==end_char){
00459             name[i-start_char+1] = '\0';
00460         }
00461     }
00462     
00463     strcat(name,"_");
00464     strcat(name,teamsize_str);
00465 }
00466 
00467 //write_results to file
00468 void write_results (double *avg_idleness, double *stddev_idleness, int *number_of_visits, uint complete_patrol, uint dimension, 
00469                     double worst_avg_idleness, double avg_graph_idl, double median_graph_idl, double stddev_graph_idl, 
00470                     double min_idleness, double gavg, double gstddev, double max_idleness,
00471                     uint interference_cnt, uint tot_visits, float avg_visits,
00472                     const char* graph_file, const char* teamsize_str, 
00473                     double duration, double real_duration, double comm_delay,
00474                             string filename) {
00475 
00476     dolog("write_results - begin");
00477 
00478     FILE *file;
00479   
00480     printf("writing to file %s\n",filename.c_str());
00481     // printf("graph file %s\n",graph_file);
00482         
00483     file = fopen (filename.c_str(),"a");
00484     
00485     //fprintf(file,"%i\n%i\n%i\n\n",num_nos,largura(),altura());
00486     fprintf(file, "\nComplete Patrol Cycles:\t%u\n\n", complete_patrol);
00487     fprintf(file, "Vertex\tAvg Idl\tStdDev Idl\t#Visits\n");
00488     for (uint i=0; i<dimension; i++){
00489         fprintf(file, "%u\t%.1f\t%.1f\t%d\n", i, avg_idleness[i], stddev_idleness[i], number_of_visits[i] );
00490     }
00491 
00492         fprintf(file,"\nNode idleness\n");
00493         fprintf(file,"   worst_avg_idleness (graph) = %.1f\n", worst_avg_idleness);
00494         fprintf(file,"   avg_idleness (graph) = %.1f\n", avg_graph_idl);
00495         fprintf(file,"   median_idleness (graph) = %.1f\n", median_graph_idl);
00496         fprintf(file,"   stddev_idleness (graph) = %.1f\n", stddev_graph_idl);
00497 
00498         fprintf(file,"\nGlobal idleness\n");
00499         fprintf(file,"   min = %.1f\n", min_idleness);
00500         fprintf(file,"   avg = %.1f\n", gavg);
00501         fprintf(file,"   stddev = %.1f\n", gstddev);
00502         fprintf(file,"   max = %.1f\n", max_idleness);
00503 
00504         fprintf(file,"\nInterferences\t%u\nInterference rate\t%.2f\nVisits\t%u\nAvg visits per node\t%.1f\nTime Elapsed\t%.1f\nReal Time Elapsed\t%.1f\nComm delay: %.2f\n",
00505                 interference_cnt,(float)interference_cnt/duration*60,tot_visits,avg_visits,duration,real_duration,comm_delay);
00506     
00507     fprintf(file,"----------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n\n");    
00508     
00509     
00510     fclose(file); /*done!*/  
00511 
00512     dolog("write_results - end");
00513 
00514 }
00515 
00516 bool check_dead_robots() {
00517 
00518     dolog("  check_dead_robots - begin");
00519 
00520     double current_time = ros::Time::now().toSec();
00521     bool r=false;
00522     for (size_t i=0; i<teamsize; i++) {
00523       double l = get_last_goal_reached(i);
00524       double delta = current_time - l;
00525       // printf("DEBUG dead robot: %d   %.1f - %.1f = %.1f\n",i,current_time,l,delta);
00526       if (delta>DEAD_ROBOT_TIME*0.75) {
00527         printf("Robot %lu: dead robot - delta = %.1f / %.1f \n",i,delta,DEAD_ROBOT_TIME);
00528         system("play -q beep.wav");
00529       }
00530       if (delta>DEAD_ROBOT_TIME) {
00531           // printf("Dead robot %d. Time from last goal reached = %.1f\n",i,delta);
00532           r=true;
00533           break;
00534       }
00535     }
00536 
00537     dolog("  check_dead_robots - end");
00538 
00539     return r;
00540 }
00541 
00542 
00543 // update stats after robot 'id_robot' visits node 'goal'
00544 void update_stats(int id_robot, int goal) {
00545 
00546     dolog("  update_stats - begin");
00547 
00548     
00549 //   printf("last_visit [%d] = %.1f\n", goal, last_visit [goal]);
00550      double current_time = ros::Time::now().toSec();
00551 
00552     printf("Robot %d reached goal %d (current time: %.2f, alg: %s, nav: %s)\n", id_robot, goal, current_time, algorithm.c_str(), nav_mod.c_str());
00553             
00554     double last_visit_temp = current_time - time_zero; //guarda o valor corrente
00555     number_of_visits [goal] ++;
00556     
00557     set_last_goal_reached(id_robot,current_time);
00558 
00559     printf("   nr_of_visits = %d -", number_of_visits [goal]);
00560 
00561     if (number_of_visits [goal] == 0) {
00562         avg_idleness [goal] = 0.0; stddev_idleness[goal] = 0.0;
00563         total_0 [goal] = 0.0; total_1 [goal] = 0.0;  total_2 [goal] = 0.0;
00564     }
00565     else { // if (number_of_visits [goal] > 0) {
00566 
00567         current_idleness [goal] = last_visit_temp - last_visit [goal];
00568     
00569         if (current_idleness [goal] > max_idleness)
00570             max_idleness=current_idleness [goal];
00571         if (current_idleness [goal] < min_idleness || min_idleness<0.1)
00572             min_idleness=current_idleness [goal];
00573         
00574         // global stats
00575         gT0++; gT1 += current_idleness[goal]; gT2 += current_idleness[goal]*current_idleness[goal];
00576     
00577         // node stats
00578         total_0 [goal] += 1.0; total_1 [goal] += current_idleness [goal];  total_2 [goal] += current_idleness [goal]*current_idleness [goal];
00579         avg_idleness [goal] = total_1[goal]/total_0[goal]; 
00580         stddev_idleness[goal] = 1.0/total_0[goal] * sqrt(total_0[goal]*total_2[goal]-total_1[goal]*total_1[goal]); 
00581         
00582         printf(" idl current = %.2f, ", current_idleness[goal]);
00583         printf(" avg = %.1f, stddev = %.1f,", avg_idleness [goal], stddev_idleness[goal]);
00584         printf(" max = %.1f - interf = %d\n", max_idleness,interference_cnt);
00585 
00586         // save data in idleness file
00587         fprintf(idlfile,"%.1f;%d;%d;%.1f;%d\n",current_time,id_robot,goal,current_idleness[goal],interference_cnt);
00588         fflush(idlfile);
00589 
00590 #if SAVE_HYSTOGRAMS
00591         // compute values for hystograms
00592         int b = (int)(current_idleness[goal]/RESOLUTION);
00593         if (b<hn) {
00594           hv[b]++; hsum++;
00595         }
00596 #endif
00597 
00598     }
00599 
00600     complete_patrol = calculate_patrol_cycle ( number_of_visits, dimension );                
00601     printf("   complete patrol cycles = %d\n", complete_patrol); 
00602     
00603     // Compute node with highest current idleness
00604     size_t hnode; double hidl=0;
00605     for (size_t i=0; i<dimension; i++) {
00606         double cidl = last_visit_temp - last_visit [i];
00607         if (cidl>hidl) {
00608             hidl=cidl; hnode=i;
00609         }
00610     }
00611     printf("   highest current idleness: node %lu idl %.1f\n\n",hnode,hidl);
00612     
00613     last_visit [goal] = last_visit_temp;
00614     
00615     goal_reached = false;
00616 
00617     dolog("  update_stats - end");
00618 
00619 }
00620 
00621 
00622 int main(int argc, char** argv){  //pass TEAMSIZE GRAPH ALGORITHM
00623   /*
00624   argc=3
00625   argv[0]=/.../patrolling_sim/bin/monitor
00626   argv[1]=grid
00627   argv[2]=ALGORITHM = {MSP,Cyc,CC,CR,HCR}
00628   argv[3]=TEAMSIZE
00629   */
00630   
00631   //ex: "rosrun patrolling_sim monitor maps/example/example.graph MSP 2"
00632   
00633 //   uint teamsize;
00634   char teamsize_str[3];
00635   teamsize = atoi(argv[3]);
00636   
00637   if ( teamsize >= NUM_MAX_ROBOTS || teamsize <1 ){
00638     ROS_INFO("The Teamsize must be an integer number between 1 and %d", NUM_MAX_ROBOTS);
00639     return 0;
00640   }else{
00641     strcpy (teamsize_str, argv[3]); 
00642 //     printf("teamsize: %s\n", teamsize_str);
00643 //     printf("teamsize: %u\n", teamsize);
00644   }
00645   
00646   
00647   algorithm = string(argv[2]);
00648   printf("Algorithm: %s\n",algorithm.c_str());
00649   
00650   string mapname = string(argv[1]);
00651   string graph_file = "maps/"+mapname+"/"+mapname+".graph";
00652 
00653   printf("Graph: %s\n",graph_file.c_str());
00654      
00656   chdir(PS_path.c_str());
00657   
00658   //Check Graph Dimension:
00659   dimension = GetGraphDimension(graph_file.c_str());
00660   if (dimension>MAX_DIMENSION) {
00661     cout << "ERROR!!! dimension > MAX_DIMENSION (static value) !!!" << endl;
00662     abort();
00663   }
00664   printf("Dimension: %u\n",(uint)dimension);
00665    
00666   char hostname[80];
00667     
00668   int r = gethostname(hostname,80);
00669   if (r<0)
00670     strcpy(hostname,"default");
00671     
00672   printf("Host name: %s\n",hostname);
00673        
00674   
00675   
00676   for (size_t i=0; i<dimension; i++){
00677     number_of_visits[i] = -1;  // first visit should not be cnted for avg
00678     current_idleness[i] = 0.0;
00679     last_visit[i] = 0.0;
00680   }
00681   
00682   for (size_t i=0; i<NUM_MAX_ROBOTS; i++){
00683     init_robots[i] = false;
00684     last_goal_reached[i] = 0.0;
00685   }
00686 
00687   bool dead = false; // check if there is a dead robot
00688     
00689     bool simrun, simabort; // check if simulation is running and if it has been aborted by the user
00690 
00691     // Scenario name (to be used in file and directory names)
00692     char sname[80];
00693     scenario_name(sname,graph_file.c_str(),teamsize_str);
00694     
00695 
00696     // Create directory results if does not exist
00697     string path1 = "results";
00698     
00699     string path2,path3,path4;
00700     
00701     path2 = path1 + "/" + string(sname);
00702     path3 = path2 + "/" + algorithm;
00703     path4 = path3 + "/" + hostname;
00704 
00705     
00706     struct stat st;
00707     
00708     if (stat(path1.c_str(), &st) != 0)
00709       mkdir(path1.c_str(), 0777);
00710     if (stat(path2.c_str(), &st) != 0)
00711       mkdir(path2.c_str(), 0777);
00712     if (stat(path3.c_str(), &st) != 0)
00713       mkdir(path3.c_str(), 0777);
00714     if (stat(path4.c_str(), &st) != 0)
00715       mkdir(path4.c_str(), 0777);
00716 
00717     printf("Path experimental results: %s\n",path4.c_str());
00718     
00719     // Local time (real clock time)
00720     time_t rawtime;
00721     struct tm * timeinfo;
00722     char strnow[80];
00723     
00724     time (&rawtime);
00725     timeinfo = localtime(&rawtime);
00726     sprintf(strnow,"%d%02d%02d_%02d%02d%02d",  timeinfo->tm_year+1900,timeinfo->tm_mon+1,timeinfo->tm_mday,timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
00727     printf("Date-time of the experiment: %s\n",strnow);
00728     
00729     // File to log all the idlenesses of an experimental scenario
00730 
00731     string idlfilename,resultsfilename,resultstimecsvfilename,expname; 
00732     expname = path4 + "/" + string(strnow);
00733     idlfilename = expname + "_idleness.csv";
00734     resultsfilename = expname + "_results.txt";
00735     resultstimecsvfilename = expname + "_timeresults.csv";
00736 
00737     FILE *fexplist;
00738     fexplist = fopen("experiments.txt", "a");
00739     fprintf(fexplist,"%s\n",expname.c_str());
00740     fclose(fexplist);
00741 
00742     idlfile = fopen (idlfilename.c_str(),"a");
00743     fprintf(idlfile,"Time;Robot;Node;Idleness;Interferences\n"); // header
00744 
00745     FILE *resultstimecsvfile;
00746     resultstimecsvfile = fopen(resultstimecsvfilename.c_str(), "w");
00747 
00748     fprintf(resultstimecsvfile,"Time;Idleness min;Idleness avg;Idleness stddev;Idleness max;Interferences\n"); // header
00749 
00750 #if LOG_MONITOR
00751     char logfilename[80];
00752     sprintf(logfilename,"monitor_%s.log",strnow);
00753     logfile = fopen(logfilename, "w");
00754 #endif
00755 
00756     dolog("Monitor node starting");
00757     dolog(expname.c_str());
00758 
00759 #if SAVE_HYSTOGRAMS    
00760     // Vectors for hystograms
00761     for (int k=0; k<hn; k++) hv[k]=0;
00762     hsum=0;
00763 #endif
00764     
00765   //Wait for all robots to connect! (Exchange msgs)
00766   ros::init(argc, argv, "monitor");
00767   ros::NodeHandle nh;
00768   
00769   //Subscribe "results" from robots
00770   results_sub = nh.subscribe("results", 100, resultsCB);   
00771   
00772   //Publish data to "results"
00773   results_pub = nh.advertise<std_msgs::Int16MultiArray>("results", 100);
00774   
00775 #if EXTENDED_STAGE  
00776   screenshot_pub = nh.advertise<std_msgs::String>("/stageGUIRequest", 100);
00777 #endif    
00778 
00779   double duration = 0.0, real_duration = 0.0;
00780   
00781   ros::Rate loop_rate(30); //0.033 seconds or 30Hz
00782   
00783   nh.setParam("/simulation_running", "true");
00784   nh.setParam("/simulation_abort", "false");
00785   
00786   if(ros::service::exists("/GotoStartPosSrv", false)){ //see if service has been advertised or not
00787        goto_start_pos = true;  //if service exists: robots need to be sent to starting positions
00788        ROS_INFO("/GotoStartPosSrv is advertised. Robots will be sent to starting positions.");
00789   }else{
00790       ROS_WARN("/GotoStartPosSrv does not exist. Assuming robots are already at starting positions.");
00791   }
00792     
00793   double current_time = ros::Time::now().toSec();
00794   
00795     // read parameters
00796     if (! ros::param::get("/goal_reached_wait", goal_reached_wait)) {
00797       goal_reached_wait = 0.0;
00798       ROS_WARN("Cannot read parameter /goal_reached_wait. Using default value 0.0!");
00799     }
00800 
00801     if (! ros::param::get("/communication_delay", comm_delay)) {
00802       comm_delay = 0.0;
00803       ROS_WARN("Cannot read parameter /communication_delay. Using default value 0.0!");
00804     } 
00805 
00806     if (! ros::param::get("/lost_message_rate", lost_message_rate)) {
00807       lost_message_rate = 0.0;
00808       ROS_WARN("Cannot read parameter /lost_message_rate. Using default value 0.0!");
00809     }
00810 
00811     if (! ros::param::get("/initial_positions", initial_positions)) {
00812       initial_positions = "default";
00813       ROS_WARN("Cannot read parameter /initial_positions. Using default value '%s'!", initial_positions.c_str());
00814     }
00815 
00816     if (! ros::param::get("/navigation_module", nav_mod)) {
00817       ROS_WARN("Cannot read parameter /navigation_module. Using default value 'ros'!");
00818       nav_mod = "ros";
00819     }
00820 
00821 
00822   // mutex for accessing last_goal_reached vector
00823   pthread_mutex_init(&lock_last_goal_reached, NULL);
00824 
00825 
00826 
00827   while( ros::ok() ){
00828     
00829     dolog("main loop - begin");
00830 
00831     if (!initialize){  //check if msg is goal or interference -> compute necessary results.
00832             
00833       // check time
00834       double report_time = ros::Time::now().toSec();
00835       
00836       // printf("### report time=%.1f  last_report_time=%.1f diff = %.1f\n",report_time, last_report_time, report_time - last_report_time);
00837       
00838       // write results every TIMEOUT_WRITE_RESULTS_(FOREVER) seconds anyway
00839       bool timeout_write_results;
00840       
00841 #if SIMULATE_FOREVER
00842       timeout_write_results = (report_time - last_report_time > TIMEOUT_WRITE_RESULTS_FOREVER);
00843 #else
00844       timeout_write_results = (report_time - last_report_time > TIMEOUT_WRITE_RESULTS);
00845 #endif
00846       
00847       if ((patrol_cnt == complete_patrol) || timeout_write_results){ 
00848 
00849         dolog("main loop - write results begin");
00850 
00851         if (complete_patrol==1) {
00852                 ros::param::get("/algorithm_params", algparams);
00853             if (! ros::param::get("/goal_reached_wait", goal_reached_wait))
00854                 goal_reached_wait = 0.0;
00855         }
00856 
00857         // write results every time a patrolling cycle is finished.
00858         // or after some time
00859         previous_avg_graph_idl = avg_graph_idl; //save previous avg idleness graph value
00860 
00861         printf("******************************************\n");
00862         printf("Patrol completed [%d]. Write to File!\n",complete_patrol);
00863 
00864         worst_avg_idleness = 0.0;
00865         avg_graph_idl = 0.0;
00866         stddev_graph_idl = 0.0;
00867         avg_stddev_graph_idl = 0.0;
00868                 
00869         // Compute avg and stddev
00870         double T0=0.0,T1=0.0,T2=0.0,S1=0.0;
00871         for (size_t i=0; i<dimension; i++){
00872             T0++; T1+=avg_idleness[i]; T2+=avg_idleness[i]*avg_idleness[i];
00873             S1+=stddev_idleness[i];
00874             if ( avg_idleness[i] > worst_avg_idleness ){
00875                 worst_avg_idleness = avg_idleness[i];
00876             }
00877         }
00878                 
00879         avg_graph_idl = T1/T0;
00880         stddev_graph_idl = 1.0/T0 * sqrt(T0*T2-T1*T1);
00881         avg_stddev_graph_idl = S1/T0;
00882         // global stats
00883         gavg = gT1/gT0;
00884         gstddev = 1.0/gT0 * sqrt(gT0*gT2-gT1*gT1);
00885 
00886         uint i,tot_visits=0;
00887         for (size_t i=0; i<dimension; i++){
00888             tot_visits += number_of_visits[i];
00889         }
00890         float avg_visits = (float)tot_visits/dimension;
00891 
00892         duration = report_time-time_zero;
00893         time_t real_now; time (&real_now); 
00894         real_duration = (double)real_now - (double)real_time_zero;                              
00895         
00896         printf("Node idleness\n");
00897         printf("   worst_avg_idleness (graph) = %.2f\n", worst_avg_idleness);
00898         printf("   avg_idleness (graph) = %.2f\n", avg_graph_idl);
00899         median_graph_idl = Median (avg_idleness, dimension);
00900         printf("   median_idleness (graph) = %.2f\n", median_graph_idl);
00901         printf("   stddev_idleness (graph) = %.2f\n", stddev_graph_idl);
00902 
00903         printf("Global idleness\n");
00904         printf("   min = %.1f\n", min_idleness);
00905         printf("   avg = %.1f\n", gavg);
00906         printf("   stddev = %.1f\n", gstddev);
00907         printf("   max = %.1f\n", max_idleness);
00908 
00909         printf("\nInterferences\t%u\nInterference rate\t%.2f\nVisits\t%u\nAvg visits per node\t%.1f\nTime Elapsed\t%.1f\nReal Time Elapsed\t%.1f\n",
00910             interference_cnt,(float)interference_cnt/duration*60,tot_visits,avg_visits,duration,real_duration);
00911         
00912         if (timeout_write_results)
00913           last_report_time = report_time;
00914         else
00915           patrol_cnt++;
00916         
00917                 
00918         double tolerance = 0.025 * avg_graph_idl;  //2.5% tolerance
00919         printf ("diff avg_idleness = %.1f\n",fabs(previous_avg_graph_idl - avg_graph_idl));
00920         printf ("tolerance = %.1f\n",tolerance);
00921         
00922         // write results to file
00923         if (!timeout_write_results)
00924             write_results (avg_idleness, stddev_idleness, number_of_visits, complete_patrol, dimension, 
00925                    worst_avg_idleness, avg_graph_idl, median_graph_idl, stddev_graph_idl,
00926                    min_idleness, gavg, gstddev, max_idleness,
00927                    interference_cnt, tot_visits, avg_visits,
00928                    graph_file.c_str(), teamsize_str, duration, real_duration, comm_delay,
00929                    resultsfilename);
00930         else {
00931             /*
00932             write_results (avg_idleness, stddev_idleness, number_of_visits, complete_patrol, dimension, 
00933                    worst_avg_idleness, avg_graph_idl, median_graph_idl, stddev_graph_idl,
00934                    min_idleness, gavg, gstddev, max_idleness,
00935                    interference_cnt, tot_visits, avg_visits,
00936                    graph_file.c_str(), teamsize_str, duration, real_duration, comm_delay,
00937                    resultstimefilename);
00938             */
00939 
00940             fprintf(resultstimecsvfile,"%.1f;%.1f;%.1f;%.1f;%.1f;%d\n", 
00941                                                  duration,min_idleness,gavg,gstddev,max_idleness,interference_cnt);
00942             fflush(resultstimecsvfile);
00943 
00944                 }
00945 
00946         dolog("main loop - write results begin");
00947 
00948       } // if ((patrol_cnt == complete_patrol) || timeout_write_results)
00949       
00950 
00951       dolog("    check - begin");
00952 
00953       // Check if simulation must be terminated
00954 #if SIMULATE_FOREVER == false
00955       dead = check_dead_robots();
00956                 
00957       simrun=true; simabort=false;
00958       std::string psimrun, psimabort; bool bsimabort;
00959       if (nh.getParam("/simulation_running", psimrun))
00960           if (psimrun=="false")
00961               simrun = false;
00962       if (nh.getParam("/simulation_abort", psimabort))
00963           if (psimabort=="true")
00964               simabort = true;
00965       if (nh.getParam("/simulation_abort", bsimabort))
00966           simabort = bsimabort;
00967         
00968       if ( (dead) || (!simrun) || (simabort) ) {
00969           printf ("Simulation is Over\n");                
00970           nh.setParam("/simulation_running", false);
00971           finish_simulation ();
00972           ros::spinOnce();
00973           break;
00974       }
00975 #endif
00976 
00977       dolog("    check - end");
00978 
00979     } // if ! initialize  
00980     
00981     current_time = ros::Time::now().toSec();
00982     ros::spinOnce();
00983     loop_rate.sleep();
00984 
00985     dolog("main loop - end");
00986         
00987   } // while ros ok
00988 
00989   ros::shutdown();
00990 
00991   fclose(idlfile);
00992   fclose(resultstimecsvfile);
00993 
00994 
00995 
00996     
00997     duration = current_time-time_zero;
00998     time_t real_now; time (&real_now); 
00999     real_duration = (double)real_now - (double)real_time_zero;
01000 
01001     uint tot_visits=0;
01002     for (size_t i=0; i<dimension; i++){
01003         tot_visits += number_of_visits[i];
01004     }
01005     float avg_visits = (float)tot_visits/dimension;
01006 
01007 
01008     // Write info file with overall results 
01009     string infofilename;
01010     infofilename = expname + "_info.csv";
01011 
01012     FILE *infofile;
01013     infofile = fopen (infofilename.c_str(),"w");
01014     fprintf(infofile,"%s;%s;%s;%.1f;%.2f;%s;%s;%s;%s;%s;%.1f;%.1f;%d;%s;%.1f;%.1f;%.1f;%.1f;%.2f;%d;%.1f;%d\n",
01015             mapname.c_str(),teamsize_str,initial_positions.c_str(),goal_reached_wait,comm_delay,nav_mod.c_str(),
01016             algorithm.c_str(), algparams.c_str(),hostname,
01017             strnow,duration,real_duration,interference_cnt,(dead?"FAIL":(simabort?"ABORT":"TIMEOUT")),
01018             min_idleness, gavg, gstddev, max_idleness, (float)interference_cnt/duration*60,
01019             tot_visits, avg_visits, complete_patrol
01020     );
01021 
01022     fclose(infofile);
01023     cout << "Info file " << infofilename << " saved." << endl;
01024 
01025 
01026 #if SAVE_HYSTOGRAMS
01027     // Hystogram files
01028     string hfilename,chfilename;
01029     hfilename = expname + ".hist";
01030     chfilename = expname + ".chist";
01031 
01032     cout << "Histogram output files: " << hfilename << endl;
01033     std::ofstream of1; of1.open(hfilename.c_str());
01034     std::ofstream of2; of2.open(chfilename.c_str());
01035     double c=0;
01036     for (int k=0; k<hn; k++) {
01037         of1 << k*RESOLUTION << " " << (double)hv[k]/hsum << endl;
01038         c += (double)hv[k]/hsum;
01039         of2 << k*RESOLUTION << " " << c << endl;
01040     }
01041     of1.close();   of2.close();
01042 #endif
01043     
01044   printf("Monitor closed.\n");
01045 
01046   dolog("Monitor closed");
01047 
01048 #if EXTENDED_STAGE
01049   sleep(5);
01050   char cmd[80];
01051   sprintf(cmd, "mv ~/.ros/stage-000003.png %s/%s_stage.png", path4.c_str(),strnow);
01052   system(cmd);
01053   printf("%s\n",cmd);
01054   printf("Screenshot image copied.\n");
01055   sleep(3);  
01056   dolog("Snapshots done");
01057 #endif
01058   
01059 }
01060 


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