monitor.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2011, 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
00036 *********************************************************************/
00037 
00038 #include <ros/ros.h>
00039 #include <move_base_msgs/MoveBaseAction.h>
00040 #include <actionlib/client/simple_action_client.h>
00041 #include <tf/transform_broadcaster.h>
00042 #include <geometry_msgs/PointStamped.h> 
00043 #include <float.h>
00044 
00045 #include "getgraph.h"
00046 
00047 #define NUM_MAX_ROBOTS 32
00048 
00049 typedef unsigned int uint;
00050 
00051 ros::Subscriber results_sub;
00052 ros::Publisher results_pub;
00053 
00054 //Initialization:
00055 bool initialize = true;
00056 uint count=0;
00057 uint teamsize;
00058 bool init_robots[NUM_MAX_ROBOTS];
00059 
00060 //State Variables:
00061 bool interference = false;
00062 bool goal_reached = false;
00063 int goal;
00064 double time_zero;
00065 
00066 void resultsCB(const geometry_msgs::PointStamped::ConstPtr& msg) {      //Entra aqui sempre que recebe uma msg
00067 /*
00068 Header header
00069     uint32 seq          //msg seq
00070     time stamp          //time
00071     string frame_id     //robot ID
00072 Point point
00073     float64 x           //vertice (X,0,0)
00074     float64 y           //interference (0,Y,0)
00075     float64 z           //initialization (0,0,Z=ID)
00076 */
00077 //      printf("Monitor: Results callback. frame_id = %s (%f,%f,%f)\n",msg->header.frame_id.c_str(),msg->point.x,msg->point.y,msg->point.z);
00078         int id_robot_int;
00079         
00080         if (initialize){
00081                         
00082                 double id_robot_dbl = msg->point.z;
00083                 id_robot_int = (int) id_robot_dbl;
00084                 
00085                 //printf("Dados:\nseq = %d\nframe_id = %s\nx = %f\ny = %f\n",msg->header.seq, msg->header.frame_id.c_str(),msg->point.x,msg->point.y);
00086                 
00087                 if (id_robot_int == -1){id_robot_int = 0;}
00088                 if (init_robots[id_robot_int] == false){
00089                         printf("Robot [ID = %d] is Active!\n",id_robot_int);
00090                         init_robots[id_robot_int] = true;
00091                         count++;
00092                 }
00093                         
00094                 if (count==teamsize){
00095                         printf("All Robots GO!\n");
00096                         initialize = false;
00097                         
00098                         //Clock Reset:
00099                         time_zero = ros::Time::now().toSec();
00100 //                      printf("time_zero é %f (s)\n", time_zero);
00101 
00102                         geometry_msgs::PointStamped msg;        
00103                         msg.header.frame_id = "monitor";
00104                         msg.point.x = 0.0;
00105                         msg.point.y = 0.0; 
00106                         msg.point.z = 0.0;
00107                         results_pub.publish(msg);
00108                         ros::spinOnce();
00109                 }
00110                 
00111         }else{
00112                 //Interferencia ou Goal
00113                 double vertex = msg->point.x;
00114                 double interf = msg->point.y;
00115                 double init = msg->point.z;
00116                 
00117                 if (msg->header.frame_id != "monitor"){
00118                         
00119 //                      printf("Interference or Goal! frame_id = %s (%f,%f)\n",msg->header.frame_id.c_str(),msg->point.x,msg->point.y);
00120                         id_robot_int = atoi( msg->header.frame_id.c_str() ); 
00121                         
00122                         if (interf == 0.0 && init == 0.0){
00123                                 goal = (int) vertex;
00124                                 printf("Robot %d reached Goal %d.\n", id_robot_int, goal);
00125                                 goal_reached = true;
00126                         }
00127                         if (interf == 1.0 ){
00128 //                              printf("Received Interference from Robot %d.\n", id_robot_int);
00129                                 interference = true;
00130                         }
00131                         
00132                 }
00133         }
00134 }
00135 
00136 void finish_simulation (){
00137         geometry_msgs::PointStamped msg;        
00138         msg.header.frame_id = "monitor";
00139         msg.point.x = 1.0;
00140         msg.point.y = 1.0; 
00141         msg.point.z = 1.0;
00142         results_pub.publish(msg);
00143         ros::spinOnce();
00144 }
00145 
00146 // return the median value in a vector of size "dimension" floats pointed to by a
00147 double Median( double *a, uint dimension )
00148 {
00149    uint table_size = dimension/2;   
00150    if(dimension % 2 != 0){ //odd
00151          table_size++; 
00152    }   
00153    if (table_size==0) {table_size = 1;}
00154    
00155    double left[table_size], right[table_size], median, *p;
00156    unsigned char nLeft, nRight;
00157 
00158    // pick first value as median candidate
00159    p = a;
00160    median = *p++;
00161    nLeft = nRight = 1;
00162 
00163    for(;;)
00164    {
00165        // get next value
00166        double val = *p++;
00167 
00168        // if value is smaller than median, append to left heap
00169        if( val < median )
00170        {
00171            // move biggest value to the heap top
00172            unsigned char child = nLeft++, parent = (child - 1) / 2;
00173            while( parent && val > left[parent] )
00174            {
00175                left[child] = left[parent];
00176                child = parent;
00177                parent = (parent - 1) / 2;
00178            }
00179            left[child] = val;
00180 
00181            // if left heap is full
00182            if( nLeft == table_size )
00183            {
00184                // for each remaining value
00185                for( unsigned char nVal = dimension - (p - a); nVal; --nVal )
00186                {
00187                    // get next value
00188                    val = *p++;
00189 
00190                    // if value is to be inserted in the left heap
00191                    if( val < median )
00192                    {
00193                        child = left[2] > left[1] ? 2 : 1;
00194                        if( val >= left[child] )
00195                            median = val;
00196                        else
00197                        {
00198                            median = left[child];
00199                            parent = child;
00200                            child = parent*2 + 1;
00201                            while( child < table_size )
00202                            {
00203                                if( child < table_size-1 && left[child+1] > left[child] )
00204                                    ++child;
00205                                if( val >= left[child] )
00206                                    break;
00207                                left[parent] = left[child];
00208                                parent = child;
00209                                child = parent*2 + 1;
00210                            }
00211                            left[parent] = val;
00212                        }
00213                    }
00214                }
00215                return median;
00216            }
00217        }
00218 
00219        // else append to right heap
00220        else
00221        {
00222            // move smallest value to the heap top
00223            unsigned char child = nRight++, parent = (child - 1) / 2;
00224            while( parent && val < right[parent] )
00225            {
00226                right[child] = right[parent];
00227                child = parent;
00228                parent = (parent - 1) / 2;
00229            }
00230            right[child] = val;
00231 
00232            // if right heap is full
00233            if( nRight == 14 )
00234            {
00235                // for each remaining value
00236                for( unsigned char nVal = dimension - (p - a); nVal; --nVal )
00237                {
00238                    // get next value
00239                    val = *p++;
00240 
00241                    // if value is to be inserted in the right heap
00242                    if( val > median )
00243                    {
00244                        child = right[2] < right[1] ? 2 : 1;
00245                        if( val <= right[child] )
00246                            median = val;
00247                        else
00248                        {
00249                            median = right[child];
00250                            parent = child;
00251                            child = parent*2 + 1;
00252                            while( child < table_size )
00253                            {
00254                                if( child < 13 && right[child+1] < right[child] )
00255                                    ++child;
00256                                if( val <= right[child] )
00257                                    break;
00258                                right[parent] = right[child];
00259                                parent = child;
00260                                child = parent*2 + 1;
00261                            }
00262                            right[parent] = val;
00263                        }
00264                    }
00265                }
00266                return median;
00267            }
00268        }
00269    }
00270 }
00271 
00272 
00273 uint calculate_patrol_cycle ( uint *nr_visits, uint dimension ){
00274         uint result = INT_MAX;
00275         
00276         for (uint i=0; i<dimension; i++){
00277                 if (nr_visits[i] < result){
00278                         result = nr_visits[i];
00279                 }
00280         }
00281         return result;  
00282 }
00283 
00284 //write_results (avg_idleness, number_of_visits, worst_idleness, avg_graph_idl, median_graph_idl, interference_count, graph_file, algorithm, teamsize_str);
00285 void write_results (double *avg_idleness, uint *number_of_visits, uint complete_patrol, uint dimension, double worst_idleness, double avg_graph_idl, double median_graph_idl, uint interference_count, char* graph_file, char* algorithm, char* teamsize_str, double timevalue){
00286         FILE *file;
00287         
00288         char name[30];
00289         uint i, start_char=0, end_char = strlen(graph_file)-1;
00290         
00291         for (i=0; i<strlen(graph_file); i++){
00292                 if(graph_file[i]=='/' && i < strlen(graph_file)-1){
00293                         start_char = i+1;
00294                 }
00295                 
00296                 if(graph_file[i]=='.' && i>0){
00297                         end_char = i-1;
00298                         break;
00299                 }
00300         }
00301         
00302         for (i=start_char; i<=end_char; i++){
00303                 name [i-start_char] = graph_file [i];
00304                 if (i==end_char){
00305                         name[i-start_char+1] = '\0';
00306                 }
00307         }
00308         
00309         strcat(name,"_");
00310         strcat(name,algorithm);
00311         strcat(name,"_");
00312         strcat(name,teamsize_str);
00313         strcat(name,".xls");
00314                 
00315         char file_path[40];
00316         strcpy(file_path,"results/");
00317         strcat(file_path,name);
00318         
00319         printf("FILE: %s\n", file_path);        
00320         file = fopen (file_path,"a");
00321         
00322         //fprintf(file,"%i\n%i\n%i\n\n",num_nos,largura(),altura());
00323         fprintf(file, "\nComplete Patrol Cycles:\t%u\n\n", complete_patrol);
00324         fprintf(file, "Vertex\tAvg Idl\t#Visits\n");
00325         
00326         for (i=0; i<dimension; i++){
00327                 fprintf(file, "%u\t%f\t%u\n", i, avg_idleness[i], number_of_visits[i] );
00328         }
00329         
00330         fprintf(file,"\nWorst Idl\t%f\nAvg Graph Idl\t%f\nMedian Graph Idl\t%f\nInterferences\t%u\nTime Elapsed\t%f\n",worst_idleness,avg_graph_idl,median_graph_idl,interference_count,timevalue);
00331         fprintf(file,"----------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n\n");
00332         fclose(file); /*done!*/ 
00333 }
00334 
00335 
00336 int main(int argc, char** argv){        //pass TEAMSIZE GRAPH ALGORITHM
00337         /*
00338         argc=3
00339         argv[0]=/.../patrolling_sim/bin/monitor
00340         argv[1]=maps/1r-5-map.graph
00341         argv[2]=ALGORITHM = {MSP,Cyc,CC,CR,HCR}
00342         argv[3]=TEAMSIZE
00343         */
00344         
00345         //ex: "rosrun patrolling_sim monitor maps/example/example.graph MSP 2"
00346   
00347 //      uint teamsize;
00348         char teamsize_str[3];
00349         teamsize = atoi(argv[3]);
00350         
00351         if ( teamsize >= NUM_MAX_ROBOTS || teamsize <1 ){
00352                 ROS_INFO("The Teamsize must be an integer number between 1 and %d", NUM_MAX_ROBOTS);
00353                 return 0;
00354         }else{
00355                 strcpy (teamsize_str, argv[3]); 
00356 //              printf("teamsize: %s\n", teamsize_str);
00357 //              printf("teamsize: %u\n", teamsize);
00358         }
00359         
00360         uint i = strlen( argv[2] );
00361         char algorithm[i];
00362         strcpy (algorithm,argv[2]);
00363         printf("Algorithm: %s\n",algorithm);
00364         
00365         i = strlen( argv[1] );
00366         char graph_file[i];
00367         strcpy (graph_file,argv[1]);
00368         printf("Graph: %s\n",graph_file);
00369         
00370         //Check Graph Dimension:
00371         uint dimension = GetGraphDimension(graph_file);
00372         printf("Dimension: %u\n",dimension);
00373    
00374         /* ESTRUTURAS DE DADOS A CALCULAR */
00375         double last_visit [dimension], current_idleness [dimension], avg_idleness [dimension];
00376         uint number_of_visits [dimension];
00377         
00378         double worst_idleness, avg_graph_idl, median_graph_idl, previous_avg_graph_idl = DBL_MAX;
00379         uint interference_count = 0;
00380         uint complete_patrol = 0;
00381         uint patrol_count = 1;
00382         
00383         for (i=0; i<dimension; i++){
00384                 number_of_visits[i] = 0;
00385                 current_idleness[i] = 0.0;
00386                 last_visit[i] = 0.0;
00387         }       
00388         
00389         for (i=0; i<NUM_MAX_ROBOTS; i++){
00390                 init_robots[i] = false;
00391         }
00392         
00393         //Wait for all robots to connect! (Exchange msgs)
00394         ros::init(argc, argv, "monitor");
00395         ros::NodeHandle nh;
00396         
00397         //Subscrever "results" vindo dos robots
00398         results_sub = nh.subscribe("results", 10, resultsCB);   
00399         
00400         //Publicar dados para "results"
00401         results_pub = nh.advertise<geometry_msgs::PointStamped>("results", 1); //only concerned about the most recent
00402         
00403         ros::Rate loop_rate(100); //0.01 segundos 
00404          
00405         while( ros::ok() ){
00406                 
00407                 if (!initialize){       //check if msg is goal or interference -> compute necessary results.
00408                         
00409                         if (interference){
00410                                 interference_count++;
00411                                 interference = false;
00412                         }
00413                         
00414                         if (goal_reached){
00415                                 
00416 //                              printf("last_visit [%d] = %f\n", goal, last_visit [goal]);
00417                                 
00418                                 double last_visit_temp = ros::Time::now().toSec() - time_zero; ; //guarda o valor corrente
00419                                 number_of_visits [goal] ++;
00420                                 
00421 //                              printf("number_of_visits [%d] = %d\n", goal, number_of_visits [goal]);
00422                                 
00423                                 current_idleness [goal] = last_visit_temp - last_visit [goal];
00424 //                              printf("current_idleness [%d] = %f\n", goal, current_idleness [goal]);
00425 
00426                                 if (number_of_visits [goal] <= 1){
00427                                         avg_idleness [goal] = current_idleness [goal];
00428                                         
00429                                 }else{                                  
00430                                         avg_idleness [goal] = ( avg_idleness [goal] * (double) (number_of_visits [goal] - 1)  + current_idleness [goal] ) / ( (double) number_of_visits [goal] );
00431                                 }
00432                                 
00433 //                              printf("avg_idleness [%d] = %f\n", goal, avg_idleness [goal]);
00434                                 last_visit [goal] = last_visit_temp;
00435 //                              printf("last_visit [%d] (UPDATED) = %f\n\n", goal, last_visit [goal]);
00436                                 
00437                                 complete_patrol = calculate_patrol_cycle ( number_of_visits, dimension );
00438                                 
00439                                 goal_reached = false;
00440                         }
00441                         
00442                         if (patrol_count == complete_patrol){ //write results every time a patrolling cycle is finished.
00443                                 
00444                                 previous_avg_graph_idl = avg_graph_idl; //save previous avg idleness graph value
00445 
00446                                 printf("Patrol completed [%d]. Write to File!\n",complete_patrol);
00447                                 worst_idleness = 0.0;
00448                                 avg_graph_idl = 0.0;
00449                                 
00450                                 for (i=0; i<dimension; i++){    //escrever avg_idle[vertex] e #visits
00451                                         
00452                                         if ( avg_idleness[i] > worst_idleness ){
00453                                                 worst_idleness = avg_idleness[i];
00454                                         }
00455                                         
00456                                         avg_graph_idl += avg_idleness[i];
00457 
00458                                 }
00459                                 
00460                                 printf("worst_idleness (graph) = %f\n", worst_idleness);
00461                                 avg_graph_idl = avg_graph_idl / (double) dimension;
00462                                 printf("avg_idleness (graph) = %f\n", avg_graph_idl);
00463                                 median_graph_idl = Median (avg_idleness, dimension);
00464                                 printf("median_idleness (graph) = %f\n", median_graph_idl);
00465                                 printf("interference = %d\n\n", interference_count);
00466                                 
00467                                 patrol_count++;
00468                                 
00469                                 double tolerance = 0.025 * avg_graph_idl;       //2.5% tolerance
00470                                 printf ("tolerance = %f\n",tolerance);
00471                                 
00472                                 //Write to File:
00473                                 write_results (avg_idleness, number_of_visits, complete_patrol, dimension, worst_idleness, avg_graph_idl, median_graph_idl, interference_count, graph_file, algorithm, teamsize_str,ros::Time::now().toSec()-time_zero);
00474                                 
00475                                 if (abs (previous_avg_graph_idl - avg_graph_idl) <= tolerance) {
00476                                         printf ("Simulation is Over\n");
00477                                         finish_simulation ();
00478                                         return 0;
00479                                 }
00480                                 
00481                         }
00482                 }       
00483                 
00484                 ros::spinOnce();
00485                 loop_rate.sleep();
00486         }
00487         
00488 }


patrolling_sim
Author(s): David Portugal
autogenerated on Mon Jan 6 2014 11:26:29