explorer.cpp
Go to the documentation of this file.
00001 #include "ros/ros.h"
00002 #include "ExplorationPlanner.h"
00003 #include <ros/console.h>
00004 #include <ExplorationPlanner.h>
00005 #include <boost/lexical_cast.hpp>
00006 #include <move_base/MoveBaseConfig.h>
00007 #include <move_base_msgs/MoveBaseAction.h>
00008 #include <move_base_msgs/MoveBaseActionFeedback.h>
00009 #include <costmap_2d/costmap_2d_ros.h>
00010 #include <costmap_2d/costmap_2d.h>
00011 #include <costmap_2d/cost_values.h>
00012 #include <costmap_2d/costmap_2d_publisher.h>
00013 #include <costmap_2d/observation.h>
00014 #include <costmap_2d/observation_buffer.h>
00015 #include <tf/transform_listener.h>
00016 #include <std_msgs/String.h>
00017 //#include <costmap_2d/voxel_costmap_2d.h>
00018 #include <actionlib/client/simple_action_client.h>
00019 #include <boost/thread.hpp>
00020 #include <boost/thread/mutex.hpp>
00021 #include <iostream>
00022 #include <navfn/navfn_ros.h>
00023 //#include <sound_play/sound_play.h>
00024 #include <boost/filesystem.hpp>
00025 #include <map_merger/LogMaps.h>
00026 
00027 
00028 //#define PROFILE
00029 //#ifdef PROFILE
00030 //#include <google/profiler.h>
00031 //#include <google/heap-profiler.h>
00032 //#endif
00033 boost::mutex costmap_mutex;
00034 
00035 
00036 #define OPERATE_ON_GLOBAL_MAP true
00037 #define OPERATE_WITH_GOAL_BACKOFF false
00038 
00039 void sleepok(int t, ros::NodeHandle &nh)
00040 {
00041     if (nh.ok())
00042     ros::Duration(1.0).sleep();
00043 }
00044 
00045 class Explorer {
00046 
00047 public:
00048 
00049         Explorer(tf::TransformListener& tf) :
00050         counter(0), rotation_counter(0), nh("~"), exploration_finished(false), number_of_robots(1), accessing_cluster(0), cluster_element_size(0),
00051         cluster_flag(false), cluster_element(-1), cluster_initialize_flag(false), global_iterattions(0), global_iterations_counter(0), 
00052         counter_waiting_for_clusters(0), global_costmap_iteration(0), robot_prefix_empty(false), robot_id(0){
00053 
00054         
00055                 nh.param("frontier_selection",frontier_selection,1); 
00056                 nh.param("local_costmap/width",costmap_width,0); 
00057                 nh.param("number_unreachable_for_cluster", number_unreachable_frontiers_for_cluster,3);
00058                 
00059                 ROS_INFO("Costmap width: %d", costmap_width);
00060 //                frontier_selection = atoi(param.c_str());
00061                 ROS_INFO("Frontier selection is set to: %d", frontier_selection);
00062                 //frontier_selection = 3;
00063                 Simulation = false;      
00064                 
00065 //#ifdef PROFILE
00066 //const char  fname[3] = "TS";
00067 //ProfilerStart(fname);
00068 //HeapProfilerStart(fname);
00069 //#endif
00070 
00071                 srand((unsigned)time(0));
00072                 
00073 //              sound_play::SoundClient sc;
00074 //              sleepok(0.5, nh);
00075 //              sc.say("Hello    World   I    am    Turtlebot");
00076                 
00077                 nh.param<std::string>("move_base_frame",move_base_frame,"map");  
00078                 nh.param<int>("wait_for_planner_result",waitForResult,3);
00079                 // determine host name
00080                 nh.param<std::string>("robot_prefix",robot_prefix,"");
00081                 ROS_INFO("robot prefix: \"%s\"", robot_prefix.c_str());
00082 
00083                 //char hostname_c[1024];
00084                 //hostname_c[1023] = '\0';
00085                 //gethostname(hostname_c, 1023);
00086                 //robot_name = std::string(hostname_c);
00087                
00088                 // create map_merger service
00089                 std::string service = robot_prefix + std::string("/map_merger/logOutput");
00090                 mm_log_client = nh.serviceClient<map_merger::LogMaps>(service.c_str());
00091                 
00092                 if(robot_prefix.empty())
00093                 {
00094                     char hostname_c[1024];
00095                     hostname_c[1023] = '\0';
00096                     gethostname(hostname_c, 1023);
00097                     robot_name = std::string(hostname_c);
00098                     ROS_INFO("NO SIMULATION! Robot name: %s", robot_name.c_str());
00099                                         
00100                     /*
00101                      * THIS IS REQUIRED TO PERFORM COORDINATED EXPLORATION
00102                      * Assign numbers to robot host names in order to make
00103                      * auctioning and frontier selection UNIQUE !!!!!
00104                      * To use explorer node on a real robot system, add your robot names 
00105                      * here and at ExplorationPlanner::lookupRobotName function ... 
00106                      */
00107                     std::string bob = "bob";
00108                     std::string marley = "marley";
00109                     std::string turtlebot = "turtlebot";
00110                     std::string joy = "joy";
00111                     std::string hans = "hans";
00112                     
00113                     if(robot_name.compare(turtlebot) == 0)
00114                         robot_id = 0;
00115                     if(robot_name.compare(joy) == 0)
00116                         robot_id = 1;
00117                     if(robot_name.compare(marley) == 0)
00118                         robot_id = 2;
00119                     if(robot_name.compare(bob) == 0)
00120                         robot_id = 3;
00121                     if(robot_name.compare(hans) == 0)
00122                         robot_id = 4;
00123                
00124                     robot_prefix_empty = true;
00125                     ROS_INFO("Robot name: %s    robot_id: %d", robot_name.c_str(), robot_id);
00126                 }else
00127                 {
00128                     robot_name = robot_prefix;
00129                     ROS_INFO("Move_base_frame: %s",move_base_frame.c_str());               
00130                     robot_id = atoi(move_base_frame.substr(7,1).c_str());
00131 
00132                     ROS_INFO("Robot: %d", robot_id);
00133                 } 
00134                 /*
00135                  * If you want to operate only 1 robot but stage is operating 2
00136                  * then simply kill one of them.
00137                  */
00138 //                if(robot_name == 1)
00139 //                {
00140 //                    ROS_ERROR("Shutting down ROBOT 1");
00141 //                    ros::shutdown();
00142 //                }
00143                 
00144                 
00145                /*
00146                 *  CREATE LOG PATH
00147                 * Following code enables to write the output to a file
00148                 * which is localized at the log_path
00149                 */
00150                 initLogPath();
00151                 csv_file = log_path + std::string("periodical.log");
00152                 log_file = log_path + std::string("exploration.log"); 
00153                 
00154                 ROS_DEBUG("*********************************************");
00155                 ROS_INFO("******* Initializing Simple Navigation ******");
00156                 ROS_DEBUG("                                             ");
00157 
00158                 ROS_DEBUG("Creating global costmap ...");
00159                 costmap2d_global = new costmap_2d::Costmap2DROS("global_costmap", tf);
00160                 ROS_DEBUG("Global costmap created ... now performing costmap -> pause");
00161                 costmap2d_global->pause();
00162                 ROS_DEBUG("Pausing performed");
00163 
00164                 ROS_DEBUG("                                             ");
00165 
00166                 if(OPERATE_ON_GLOBAL_MAP == true)
00167                 {
00168                     costmap2d_local_size = new costmap_2d::Costmap2DROS("local_costmap", tf);
00169                     costmap2d_local_size->pause();
00170                     ROS_DEBUG("Starting Global costmap ...");
00171                     costmap2d_global->start();
00172                     costmap2d_local_size->start();
00173                     
00174                     costmap2d_local = costmap2d_global;                   
00175                 }
00176                 else
00177                 {
00178                     ROS_INFO("Creating local costmap ...");
00179                     costmap2d_local = new costmap_2d::Costmap2DROS("local_costmap", tf);
00180                     ROS_INFO("Local costmap created ... now performing costmap -> pause");
00181                     costmap2d_local->pause();
00182                     ROS_INFO("Pausing performed");
00183                     ROS_INFO("Cost maps created");
00184 
00185                     ROS_INFO("                                             ");
00186 
00187                     ROS_INFO("Starting Global costmap ...");
00188                     costmap2d_global->start();
00189                     ROS_INFO("Starting Local costmap ... ");
00190                     costmap2d_local->start();
00191                     ROS_INFO("BOTH COSTMAPS STARTED AND RUNNING ...");
00192                 }
00193                 ROS_INFO("---------------- COSTMAP DONE ---------------");
00194 
00195                 /*
00196                  * Set the first goal as PointStamped message to visualize in RVIZ.
00197                  * RVIZ requires a minimal history length of 1, which means that at least
00198                  * one entry has to be buffered, before the first Goal is able to be
00199                  * visualized. Therefore set the "first" goal to the point of origin
00200                  * (home position).
00201                  */
00202  
00203                 if (!costmap2d_local->getRobotPose(robotPose)) {
00204                         ROS_ERROR("Failed to get RobotPose");
00205                 }
00206                 visualize_goal_point(robotPose.getOrigin().getX(),
00207                                 robotPose.getOrigin().getY());
00208 
00209                 // transmit three times, since rviz need at least 1 to buffer before visualizing the point
00210                 for (int i = 0; i <= 2; i++) {
00211                         visualize_home_point();
00212                 }
00213 
00214                 ROS_INFO("---------- SET HOME/ GOAL POINT DONE --------");
00215 
00216                 // instantiate the planner
00217                 exploration = new explorationPlanner::ExplorationPlanner(robot_id, robot_prefix_empty, robot_name);
00218                 
00219                 /*
00220                  * Define the first Goal. This is required to have at least one entry
00221                  * within the vector. Therefore set it to the home position.
00222                  */
00223                                
00224                 robot_home_position_x = robotPose.getOrigin().getX();
00225                 robot_home_position_y = robotPose.getOrigin().getY();
00226                
00227                 exploration->next_auction_position_x = robotPose.getOrigin().getX();
00228                 exploration->next_auction_position_y = robotPose.getOrigin().getY();
00229                 
00230                 exploration->storeVisitedFrontier(robot_home_position_x,robot_home_position_y, robot_id, robot_name, -1);                            
00231                 exploration->storeFrontier(robot_home_position_x,robot_home_position_y, robot_id, robot_name, -1);           
00232                
00233                 exploration->setRobotConfig(robot_id, robot_home_position_x, robot_home_position_y, move_base_frame);
00234                 
00235                 ROS_INFO("                                             ");
00236                 ROS_INFO("************* INITIALIZING DONE *************");
00237                 
00238         }
00239 
00240 
00241         void explore() 
00242         {
00243                 /*
00244                  * Sleep is required to get the actual 
00245                  * costmap updated with obstacle and inflated 
00246                  * obstacle information. This is rquired for the
00247                  * first time explore() is called.
00248                  */
00249                 ROS_DEBUG("Sleeping 5s for costmaps to be updated.");
00250                 geometry_msgs::Twist twi;
00251                 //should be a parameter!! only for testing on Wed/17/9/14
00252                 ros::Publisher twi_publisher = nh.advertise<geometry_msgs::Twist>("/Rosaria/cmd_vel",3);
00253                 twi.angular.z = 0.75;
00254                 twi_publisher.publish(twi);
00255                 ros::Duration(5.0).sleep();
00256                 twi_publisher.publish(twi);
00257                 /*
00258                  * START TAKING THE TIME DURING EXPLORATION     
00259                  */
00260                 time_start = ros::Time::now();
00261                 
00262                 
00263                 while (exploration_finished == false) 
00264                 {
00265                     Simulation == false; 
00266                     if(Simulation == false)
00267                     {
00268                         /*
00269                          * *****************************************************
00270                          * FRONTIER DETERMINATION
00271                          * *****************************************************
00272                          */
00273 
00274                             std::vector<double> final_goal;
00275                             std::vector<double> backoffGoal;
00276                             std::vector<std::string> robot_str;
00277                             
00278                             bool backoff_sucessfull = false, navigate_to_goal = false;
00279                             bool negotiation;
00280                             int count = 0;
00281 
00282                             ROS_INFO("****************** EXPLORE ******************");
00283 
00284                             /*
00285                              * Use mutex to lock the critical section (access to the costmap)
00286                              * since rosspin tries to update the costmap continuously
00287                              */
00288                             costmap_mutex.lock();
00289 
00290                             exploration->transformToOwnCoordinates_frontiers();
00291                             exploration->transformToOwnCoordinates_visited_frontiers();
00292 
00293 //                          ros::Duration(1.0).sleep();
00294                             exploration->initialize_planner("exploration planner", costmap2d_local, costmap2d_global);
00295                             exploration->findFrontiers();
00296 //                            exploration->printFrontiers();
00297                           
00298                             exploration->clearVisitedFrontiers();                       
00299                             exploration->clearUnreachableFrontiers();
00300                             exploration->clearSeenFrontiers(costmap2d_global);       
00301 
00302                             costmap_mutex.unlock();
00303 
00304                             exploration->publish_frontier_list();  
00305                             exploration->publish_visited_frontier_list();  
00306 
00307                             ros::Duration(1).sleep();
00308                             exploration->publish_frontier_list();  
00309                             exploration->publish_visited_frontier_list();  
00310 
00311                             /*
00312                              * Sleep to ensure that frontiers are exchanged
00313                              */
00314                             ros::Duration(1).sleep();
00315                            
00316                             /*
00317                              * *****************************************************
00318                              * FRONTIER SELECTION
00319                              * *****************************************************
00320                              */
00321  
00322                             /*********** EXPLORATION STRATEGY ************
00323                              * 0 ... Navigate to nearest frontier TRAVEL PATH
00324                              * 1 ... Navigate using auctioning with cluster selection using 
00325                              *       NEAREST selection (Kuhn-Munkres)
00326                              * 2 ... Navigate to furthest frontier
00327                              * 3 ... Navigate to nearest frontier EUCLIDEAN DISTANCE
00328                              * 4 ... Navigate to random Frontier
00329                              * 5 ... Cluster frontiers, then navigate to nearest cluster 
00330                              *       using EUCLIDEAN DISTANCE (with and without
00331                              *       negotiation)
00332                              * 6 ... Cluster frontiers, then navigate to random cluster
00333                              *       (with and without negotiation)
00334                              */
00335 
00336                             /******************** SORT *******************
00337                             * Choose which strategy to take.
00338                             * 1 ... Sort the buffer from furthest to nearest frontier
00339                             * 2 ... Sort the buffer from nearest to furthest frontier, normalized to the
00340                             *       robots actual position (EUCLIDEAN DISTANCE)
00341                             * 3 ... Sort the last 10 entries to shortest TRAVEL PATH
00342                             * 4 ... Sort all cluster elements from nearest to furthest (EUCLIDEAN DISTANCE)
00343                             */
00344                             if(frontier_selection == 2)
00345                             {
00346 
00347                                 exploration->sort(1); 
00348 
00349                                 /* 
00350                                  * Choose which strategy to take.
00351                                  * 1 ... least to first goal in list
00352                                  * 2 ... first to last goal in list
00353                                  *
00354                                  * Determine_goal() takes world coordinates stored in
00355                                  * the frontiers list(which contain every found frontier with sufficient
00356                                  * spacing in between) and returns the most attractive one, based on the
00357                                  * above defined strategies.
00358                                  */    
00359                                 while(true)
00360                                 {   
00361                                     goal_determined = exploration->determine_goal(1, &final_goal, count, 0, &robot_str);
00362                                     if(goal_determined == false)
00363                                     {
00364                                         break;
00365                                     }
00366                                     else
00367                                     {   
00368                                         //negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),-1);
00369                                         negotiation = true; 
00370                                         if(negotiation == true)
00371                                         {
00372                                             break;
00373                                         }
00374                                         count++;
00375                                     }
00376                                 }
00377                             }    
00378                             else if(frontier_selection == 3)
00379                             {                           
00380                                 exploration->sort(2);
00381 
00382                                 while(true)
00383                                 {   
00384                                     goal_determined = exploration->determine_goal(2, &final_goal, count, 0, &robot_str);
00385                                     if(goal_determined == false)
00386                                     {
00387                                         break;
00388                                     }
00389                                     else
00390                                     {
00391                                         //negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),-1);
00392                                         negotiation = true; 
00393                                         if(negotiation == true)
00394                                         {
00395                                             break;
00396                                         }
00397                                         count++;
00398                                     }
00399                                 }
00400                             }        
00401                             else if(frontier_selection == 0)
00402                             {
00403                                 exploration->sort(2);
00404                                 exploration->sort(3);
00405 
00406                                 while(true)
00407                                 {   
00408                                     goal_determined = exploration->determine_goal(2, &final_goal, count, 0, &robot_str);
00409                                     ROS_DEBUG("Goal_determined: %d   counter: %d",goal_determined, count);
00410                                     if(goal_determined == false)
00411                                     {
00412                                         break;
00413                                     }
00414                                     else
00415                                     {                        
00416                                         //negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),-1);
00417                                         negotiation = true;
00418                                         if(negotiation == true)
00419                                         {
00420                                             break;
00421                                         }
00422                                         count++;
00423                                     }
00424                                 }
00425 
00426                             }
00427                             else if(frontier_selection == 4)
00428                             {
00429                                 while(true)
00430                                 {   
00431                                     goal_determined = exploration->determine_goal(3, &final_goal, count, 0, &robot_str);
00432                                     ROS_DEBUG("Goal_determined: %d   counter: %d",goal_determined, count);
00433                                     if(goal_determined == false)
00434                                     {
00435                                         break;
00436                                     }
00437                                     else
00438                                     {
00439                                         //negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),-1);
00440                                         negotiation = true; 
00441                                         if(negotiation == true)
00442                                         {
00443                                             break;
00444                                         }
00445                                         count++;
00446                                     }
00447                                 }
00448 
00449                             }
00450                             else if(frontier_selection == 5)
00451                             {                            
00452                                 if(cluster_initialize_flag == true)
00453                                 {
00454                                     exploration->clearVisitedAndSeenFrontiersFromClusters();
00455                                 }
00456                                 else
00457                                 {
00458                                     /*
00459                                      * This is necessary for the first run 
00460                                      */
00461                                     if(robot_id == 0)
00462                                         ros::Duration(10).sleep();
00463 
00464                                     exploration->sort(2); 
00465                                 }
00466 
00467                                 exploration->clusterFrontiers();                 
00468                                 exploration->sort(4);      
00469                                 exploration->sort(5);
00470 
00471     //                            exploration->visualizeClustersConsole();
00472 
00473                                 clusters_available_in_pool.clear();
00474                                 while(true)
00475                                 {                             
00476                                     final_goal.clear();
00477                                     goal_determined = exploration->determine_goal(4, &final_goal, count, cluster_element, &robot_str);
00478 
00479                                     if(goal_determined == false)
00480                                     {
00481                                         ROS_INFO("Another cluster is not available, no cluster determined");                                    
00482                                         break;
00483                                     }
00484                                     else
00485                                     {
00486                                         if(cluster_initialize_flag == false)
00487                                         {
00488                                             /*
00489                                             *  TODO ... just to reduce the selection of the same 
00490                                             * clusters since no auctioning is implemented jet.
00491                                             */
00492                                            if(robot_id == 1)  
00493                                            {
00494                                                ros::Duration(5).sleep();
00495                                            }
00496 
00497                                            cluster_initialize_flag = true;
00498                                         }
00499 
00500                                         /*
00501                                          * If negotiation is not needed, simply uncomment
00502                                          * and set the negotiation to TRUE.
00503                                          */
00504                                         negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),final_goal.at(4));
00505 //                                        negotiation = true; 
00506                                         if(negotiation == true)
00507                                         {
00508                                             ROS_DEBUG("Negotiation was successful");
00509                                             cluster_element = final_goal.at(4);
00510                                             counter_waiting_for_clusters = 0;
00511                                             break;
00512                                         }
00513                                         else
00514                                         {
00515                                             cluster_element = final_goal.at(4);
00516                                             counter_waiting_for_clusters++;
00517                                             ROS_ERROR("Negotiation was not successful, try next cluster");
00518                                         }
00519                                         count++;
00520                                         /*
00521                                          * In order to make one robot wait until the other finds
00522                                          * another cluster to operate in, one have to fill the clusters_available_in_pool
00523                                          * vector if count is increased at least once which determines
00524                                          * that at least one cluster
00525                                          */
00526                                         clusters_available_in_pool.push_back(1);
00527                                     }
00528                                 }
00529 
00530                             } 
00531                             else if(frontier_selection == 6)
00532                             {                            
00533                                 if(cluster_initialize_flag == true)
00534                                 {
00535                                     exploration->clearVisitedAndSeenFrontiersFromClusters();
00536                                 }
00537 
00538                                 exploration->clusterFrontiers();   
00539                                 exploration->sort(6);
00540                                 exploration->visualizeClustersConsole();
00541 
00542                                 if(cluster_initialize_flag == false)
00543                                 {
00544                                     ros::Duration(2).sleep();
00545                                 }
00546                                 cluster_initialize_flag = true;
00547 
00548                                 while(true)
00549                                 {             
00550                                     goal_determined = exploration->determine_goal(4, &final_goal, count, cluster_element, &robot_str);
00551 
00552                                     if(goal_determined == false)
00553                                     {
00554                                         break;
00555                                     }
00556                                     else
00557                                     {   
00558                                         /*
00559                                          * If negotiation is not needed, simply uncomment
00560                                          * and set the negotiation to TRUE.
00561                                          */
00562                                         negotiation = exploration->negotiate_Frontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),final_goal.at(3),final_goal.at(4));
00563 //                                        negotiation = true; 
00564 
00565                                         if(negotiation == true)
00566                                         {
00567                                             cluster_element = final_goal.at(4);
00568                                             break;
00569                                         }
00570                                         else
00571                                         {
00572                                             cluster_element = int(exploration->clusters.size()*rand()/(RAND_MAX));
00573                                             ROS_INFO("Random cluster_element: %d  from available %lu clusters", cluster_element, exploration->clusters.size());
00574                                         }
00575                                         count++;
00576                                     }
00577                                 }
00578                             } 
00579                             else if(frontier_selection == 1)
00580                             {     
00581                                 costmap_mutex.lock();
00582                                 if(cluster_initialize_flag == true)
00583                                 {
00584                                      exploration->clearVisitedAndSeenFrontiersFromClusters();
00585                                 }
00586                                 else
00587                                 {                              
00588                                     /*
00589                                      * This is only necessary for the first run 
00590                                      */
00591 
00592                                     exploration->sort(2); 
00593                                     cluster_initialize_flag = true;
00594                                 }
00595 
00596                                 exploration->clusterFrontiers();                 
00597                                 exploration->sort(4);      
00598                                 exploration->sort(5);
00599 
00600                                 costmap_mutex.unlock();
00601 
00602                                 exploration->visualizeClustersConsole();
00603 
00604                                 while(true)
00605                                 {                             
00606                                     final_goal.clear();
00607                                     robot_str.clear();
00608                                     goal_determined = exploration->determine_goal(5, &final_goal, 0, cluster_element, &robot_str);
00609                                     
00610                                     ROS_ERROR("Cluster element: %d", cluster_element);
00611                                     
00612                                     int cluster_vector_position = -1;
00613  
00614                                     if(cluster_element != -1)
00615                                     {
00616                                         if(exploration->clusters.size() > 0)
00617                                         {                   
00618                                             for (int i = 0; i < exploration->clusters.size(); i++)
00619                                             {
00620                                                 if(exploration->clusters.at(i).id == cluster_element)
00621                                                 {
00622                                                     if(exploration->clusters.at(i).cluster_element.size() > 0)
00623                                                     {
00624                                                         cluster_vector_position = i; 
00625                                                     }
00626                                                     break;
00627                                                 }
00628                                             }
00629                                         }
00630                                     }
00631                                     ROS_ERROR("Cluster vector position: %d", cluster_vector_position);
00632                                     
00633                                     if(cluster_vector_position >= 0)
00634                                     {
00635                                         if(exploration->clusters.at(cluster_vector_position).unreachable_frontier_count >= number_unreachable_frontiers_for_cluster)
00636                                         {
00637                                             goal_determined = false;
00638                                             ROS_ERROR("Cluster inoperateable");
00639                                         }else
00640                                         {
00641                                             ROS_ERROR("Cluster operateable");
00642                                         }
00643                                     }
00644                                     
00645                                     if(goal_determined == false)
00646                                     {  
00647                                         
00648                                         ROS_INFO("No goal was determined, cluster is empty. Bid for another one");
00649 
00650                                         final_goal.clear();
00651                                         robot_str.clear();
00652                                         clusters_available_in_pool.clear();
00653 
00654                                         bool auctioning = exploration->auctioning(&final_goal, &clusters_available_in_pool, &robot_str);
00655                                         if(auctioning == true)
00656                                         {
00657                                             goal_determined = true; 
00658                                             cluster_element = final_goal.at(4);
00659                                             counter_waiting_for_clusters = 0;
00660                                             break;
00661                                         }
00662                                         else
00663                                         {
00664                                             if(exploration->clusters.size() > 0) //clusters_available_in_pool.size() > 0)
00665                                             {
00666                                                 ROS_INFO("No cluster was selected but other robots are operating ... waiting for new clusters");
00667                                                 counter_waiting_for_clusters++;
00668                                                 break;
00669                                             }else
00670                                             {
00671                                                 /*
00672                                                  * If NO goals are selected at all, iterate over the global
00673                                                  * map to find some goals. 
00674                                                  */
00675                                                 ROS_ERROR("No goals are available at all");
00676                                                 cluster_element = -1;
00677                                                 break;
00678                                             }
00679                                         }
00680                                     }
00681                                     else
00682                                     {
00683                                         ROS_INFO("Still some goals in current cluster, finish this job first");
00684                                         break;
00685                                     }
00686                                 }
00687 
00688                             } 
00689 
00690 
00691                              /*
00692                              * *****************************************************
00693                              * FRONTIER COORDINATION
00694                              * *****************************************************
00695                              */
00696 
00697 
00698     //                        exploration->visualize_Clusters();
00699                             exploration->visualize_Cluster_Cells();
00700                             exploration->visualize_Frontiers();
00701     //                        exploration->visualize_visited_Frontiers();
00702 
00703                        
00704 //                            if (Simulation == false)//cluster_element_size != 0) 
00705 //                            {
00706                                 ROS_INFO("Navigating to Goal");
00707 
00708                                 if(goal_determined == true)
00709                                 {
00710                                     if(OPERATE_WITH_GOAL_BACKOFF == true)
00711                                     {
00712                                         ROS_DEBUG("Doing smartGoalBackoff");
00713                                         backoff_sucessfull = exploration->smartGoalBackoff(final_goal.at(0),final_goal.at(1), costmap2d_global, &backoffGoal);   
00714                                     }
00715                                     else
00716                                     {
00717                                         backoff_sucessfull = true;
00718                                     }
00719                                 }
00720 
00721                                 if(backoff_sucessfull == true)
00722                                 {
00723                                     if(OPERATE_WITH_GOAL_BACKOFF == true)
00724                                     {
00725                                         ROS_INFO("Doing navigation to backoff goal");
00726                                         navigate_to_goal = navigate(backoffGoal);
00727                                     }else
00728                                     {
00729                                         ROS_INFO("Doing navigation to goal");
00730                                         navigate_to_goal = navigate(final_goal);
00731                                     }
00732                                 }
00733                                 else if(backoff_sucessfull == false && goal_determined == false)
00734                                 {
00735                                     navigate_to_goal = navigate(final_goal);
00736                                     goal_determined = false;
00737                                 }
00738 
00739 
00740                                 if(navigate_to_goal == true && goal_determined == true)
00741                                 {
00742                                     exploration->calculate_travel_path(exploration->visited_frontiers.at(exploration->visited_frontiers.size()-1).x_coordinate, exploration->visited_frontiers.at(exploration->visited_frontiers.size()-1).y_coordinate);
00743 
00744                                     ROS_DEBUG("Storeing visited...");
00745                                     exploration->storeVisitedFrontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),robot_str.at(0),final_goal.at(3)); 
00746                                     ROS_DEBUG("Stored Visited frontier");
00747                                    
00748                                 }   
00749                                 else if(navigate_to_goal == false && goal_determined == true)
00750                                 {
00751                                     ROS_DEBUG("Storeing unreachable...");
00752                                     exploration->storeUnreachableFrontier(final_goal.at(0),final_goal.at(1),final_goal.at(2),robot_str.at(0),final_goal.at(3));                            
00753                                     ROS_DEBUG("Stored unreachable frontier");
00754                                 } 
00755 
00756     //                            exploration->clearVisitedFrontiers();
00757     //                            exploration->clearUnreachableFrontiers();  
00758 
00759     //                            exploration->publish_frontier_list();  
00760     //                            exploration->publish_visited_frontier_list();                           
00761 //                            }
00762                         }
00763                         else
00764                         {
00765                                 ROS_ERROR("No navigation performed");                           
00766                         }               
00767                         ROS_DEBUG("                                             ");
00768                         ROS_DEBUG("                                             ");
00769                 }
00770         }         
00771            
00772         void frontiers()
00773         {
00774             ros::Rate r(5);
00775             while(ros::ok())
00776             {
00777                 
00778                 costmap_mutex.lock();
00779                 
00780                 exploration->clearSeenFrontiers(costmap2d_global);
00781                 exploration->clearVisitedFrontiers();
00782                 exploration->clearUnreachableFrontiers(); 
00783                 
00784                 exploration->publish_frontier_list();  
00785                 exploration->publish_visited_frontier_list();  
00786                 
00787                 costmap_mutex.unlock();
00788                 
00789                 r.sleep();
00790             }
00791         }
00792         
00793         
00794         void map_info()
00795         {       
00796             fs_csv.open(csv_file.c_str(), std::fstream::in | std::fstream::app | std::fstream::out);
00797             fs_csv << "#time,exploration_travel_path_global,exploration_travel_path_average,global_map_progress,local_map_progress,number_of_completed_auctions, number_of_uncompleted_auctions, frontier_selection_strategy, costmap_size, unreachable_frontiers" << std::endl;
00798             fs_csv.close();
00799             
00800             while(ros::ok() && exploration_finished != true)
00801             {
00802                 costmap_mutex.lock();
00803 
00804                 ros::Duration time = ros::Time::now() - time_start;
00805                 double exploration_time = time.toSec();  
00806 
00807                 map_progress.global_freespace = global_costmap_size();
00808                 map_progress.local_freespace = local_costmap_size();
00809                 map_progress.time = exploration_time;               
00810                 map_progress_during_exploration.push_back(map_progress);
00811 
00812 
00813                 double exploration_travel_path_global = (double)exploration->exploration_travel_path_global * 0.02;
00814                 double exploration_travel_path_average = 0;
00815                 if(counter != 0)
00816                 {
00817                     exploration_travel_path_average = (exploration->exploration_travel_path_global) / counter;
00818                 }
00819 
00820 //                ROS_INFO("global map size: %f   at time: %f", map_progress.global_freespace, map_progress.time);
00821 //                ROS_INFO("local map size : %f   at time: %f", map_progress.local_freespace, map_progress.time);
00822 //                ROS_INFO("travel path glo: %d   at time: %f", exploration_travel_path_global, map_progress.time);
00823 //                ROS_INFO("travel path ave: %d   at time: %f", exploration_travel_path_average, map_progress.time);
00824 
00825                 fs_csv.open(csv_file.c_str(), std::fstream::in | std::fstream::app | std::fstream::out);
00826 
00827                 fs_csv << map_progress.time << "," << exploration_travel_path_global << "," << exploration_travel_path_average << "," << map_progress.global_freespace << "," << map_progress.local_freespace << "," << global_iterattions <<  "," << exploration->number_of_completed_auctions << "," << exploration->number_of_uncompleted_auctions << "," << frontier_selection << "," <<  costmap_width << "," << exploration->unreachable_frontiers.size() <<  std::endl;
00828 //                fs_csv << "travel_path_global   = " << exploration_travel_path_global << std::endl;
00829 //                fs_csv << "travel_path_average  = " << exploration_travel_path_average << std::endl;             
00830 //                fs_csv << "map_progress_global  = " << map_progress.global_freespace << std::endl;
00831 //                fs_csv << "map_progress_average = " << map_progress.local_freespace << std::endl;
00832 //                fs_csv << "time                 = " << map_progress.time << std::endl;
00833 //                fs_csv << "                       " << std::endl;
00834 
00835                 fs_csv.close();
00836 
00837                 costmap_mutex.unlock();    
00838 
00839                 // call map_merger to log data
00840                 map_merger::LogMaps log;
00841                 log.request.log = 12;    
00842                 ROS_DEBUG("Calling map_merger service logOutput");
00843                 if(!mm_log_client.call(log))
00844                     ROS_WARN("Could not call map_merger service to store log.");
00845                 ROS_DEBUG("Finished service call.");
00846 
00847                 save_progress();
00848                 
00849                 ros::Duration(10.0).sleep();
00850             }
00851         }
00852         
00853         int global_costmap_size()
00854         {
00855            occupancy_grid_global = costmap2d_global->getCostmap()->getCharMap();
00856            int num_map_cells_ = costmap2d_global->getCostmap()->getSizeInCellsX() * costmap2d_global->getCostmap()->getSizeInCellsY();
00857            int free = 0;
00858            
00859            for (unsigned int i = 0; i < num_map_cells_; i++) 
00860            {
00861                 if ((int) occupancy_grid_global[i] == costmap_2d::FREE_SPACE) 
00862                 {
00863                      free++;
00864                 }
00865             }   
00866            return free;
00867         }
00868         
00869         int local_costmap_size()
00870         {   
00871             if(OPERATE_ON_GLOBAL_MAP == false)
00872             {
00873                 occupancy_grid_local = costmap2d_local->getCostmap()->getCharMap();
00874                 int num_map_cells_ = costmap2d_local->getCostmap()->getSizeInCellsX() * costmap2d_local->getCostmap()->getSizeInCellsY();
00875                 int free = 0;
00876 
00877                 for (unsigned int i = 0; i < num_map_cells_; i++) 
00878                 {
00879                      if ((int) occupancy_grid_local[i] == costmap_2d::FREE_SPACE) 
00880                      {
00881                           free++;
00882                      }
00883                  }   
00884                 return free;
00885             }else
00886             {
00887                 occupancy_grid_local = costmap2d_local_size->getCostmap()->getCharMap();
00888                 int num_map_cells_ = costmap2d_local_size->getCostmap()->getSizeInCellsX() * costmap2d_local_size->getCostmap()->getSizeInCellsY();
00889                 int free = 0;
00890 
00891                 for (unsigned int i = 0; i < num_map_cells_; i++) 
00892                 {
00893                      if ((int) occupancy_grid_local[i] == costmap_2d::FREE_SPACE) 
00894                      {
00895                           free++;
00896                      }
00897                  }   
00898                 return free;
00899             }
00900         }
00901         
00902         void initLogPath()
00903         {
00904            /*
00905             *  CREATE LOG PATH
00906             * Following code enables to write the output to a file
00907             * which is localized at the log_path
00908             */
00909             
00910             nh.param<std::string>("log_path",log_path,"");           
00911 
00912             std::stringstream robot_number;
00913             robot_number << robot_id;
00914             std::string prefix = "/robot_";
00915             std::string robo_name = prefix.append(robot_number.str());    
00916 
00917             log_path = log_path.append("/explorer");
00918             log_path = log_path.append(robo_name);
00919             log_path = log_path.append("/");
00920             ROS_INFO("Logging files to %s", log_path.c_str());
00921 
00922             boost::filesystem::path boost_log_path(log_path.c_str());
00923             if(!boost::filesystem::exists(boost_log_path))
00924                 if(!boost::filesystem::create_directories(boost_log_path))
00925                     ROS_ERROR("Cannot create directory %s.", log_path.c_str());
00926              
00927         }
00928         
00929         void save_progress(bool final=false)
00930         {
00931             ros::Duration ros_time = ros::Time::now() - time_start;
00932             
00933             double exploration_time = ros_time.toSec();           
00934             int navigation_goals_required = counter;        
00935             double exploration_travel_path = (double)exploration->exploration_travel_path_global * 0.02;
00936             double size_global_map = map_progress_during_exploration.at(map_progress_during_exploration.size()-1).global_freespace;
00937                     
00938             double efficiency_value = (exploration_time) / (number_of_robots * navigation_goals_required);
00939 
00940             std::string tmp_log;
00941             if(!final) 
00942             {
00943                 tmp_log = log_file + std::string(".tmp");
00944                 fs.open(tmp_log.c_str(), std::fstream::in | std::fstream::trunc | std::fstream::out);
00945             }
00946             else
00947             {
00948                 tmp_log = log_file;
00949                 fs.open(tmp_log.c_str(), std::fstream::in | std::fstream::trunc | std::fstream::out);
00950             }
00951 
00952             /*
00953              *  WRITE LOG FILE
00954              * Write all the output to the log file
00955              */
00956             time_t raw_time;
00957             struct tm* timeinfo;
00958             time (&raw_time);
00959             timeinfo = localtime (&raw_time);
00960 
00961             fs << "[Exploration]" << std::endl;
00962             fs << "time_file_written                            = " << asctime(timeinfo); // << std::endl;
00963             fs << "start_time                                   = " << time_start << std::endl;
00964             fs << "end_time                                     = " << ros::Time::now() << std::endl;
00965             fs << "exploration_time                             = " << exploration_time << std::endl;
00966             fs << "required_goals                               = " << navigation_goals_required << std::endl;  
00967             fs << "unreachable_goals                            = " << exploration->unreachable_frontiers.size() << std::endl;
00968             fs << "travel_path_overall                          = " << exploration_travel_path << std::endl;
00969             fs << "number_of_completed_auctions                 = " << exploration->number_of_completed_auctions << std::endl;
00970             fs << "number_of_uncompleted_auctions               = " << exploration->number_of_uncompleted_auctions << std::endl;
00971             fs << "frontier_selection_strategy                  = " << frontier_selection << std::endl;
00972             fs << "costmap_size                                 = " << costmap_width << std::endl;
00973             fs << "global costmap iterations                    = " << global_costmap_iteration << std::endl;
00974             
00975             double param_double;
00976         int param_int;
00977             std::string param;
00978         /*param = robot_prefix + "/explorer/local_costmap/height";
00979             ros::param::get(param,param_double);*/
00980         nh.param<int>("local_costmap/height",param_int,-1);
00981         fs << "explorer_local_costmap_height            = " << param_int << std::endl;
00982 
00983         /*param = robot_prefix + "/explorer/local_costmap/width";
00984             ros::param::get(param,param_double);*/
00985         nh.param<int>("local_costmap/width",param_int,-1);
00986         fs << "explorer_local_costmap_width             = " << param_int << std::endl;
00987 
00988             param = robot_prefix + "/move_base/local_costmap/height";
00989             ros::param::get(param,param_double);
00990             fs << "move_base_local_costmap_height               = " << param_double << std::endl;
00991 
00992             param = robot_prefix + "/move_base/local_costmap/width";
00993             ros::param::get(param,param_double);
00994             fs << "move_base_local_costmap_width                = " << param_double << std::endl;
00995 
00996             param = robot_prefix + "/move_base/global_costmap/obstacle_layer/raytrace_range";
00997             ros::param::get(param,param_double);
00998             fs << "move_base_raytrace_range             = " << param_double << std::endl;
00999 
01000             param = robot_prefix + "/move_base/global_costmap/obstacle_layer/obstacle_range";
01001             ros::param::get(param,param_double);
01002             fs << "move_base_obstacle_range             = " << param_double << std::endl;
01003 
01004 //          param = robot_prefix + "/navigation/global_costmap/obstacle_layer/raytrace_range";
01005         nh.getParam("/global_costmap/obstacle_layer/raytrace_range",param_double);
01006         ros::param::get(param,param_double);
01007             fs << "explorer_raytrace_range              = " << param_double << std::endl;
01008 
01009         //param = robot_prefix + "/navigation/global_costmap/obstacle_layer/obstacle_range";
01010         //    ros::param::get(param,param_double);
01011         nh.getParam("/global_costmap/obstacle_layer/obstacle_range",param_double);
01012             fs << "explorer_obstacle_range              = " << param_double << std::endl;
01013 
01014             if(final)
01015                 fs << "complete                                 = " << "1" << std::endl;
01016             else
01017                 fs << "complete                                 = " << "0" << std::endl;
01018             
01019             fs.close();
01020 //            ROS_INFO("Wrote file %s\n", log_file.c_str());                    
01021             
01022             
01023             /*
01024              * Inform map_merger to save maps
01025              */
01026             
01027            if(final)
01028             {
01029                     map_merger::LogMaps log;
01030                     log.request.log = 3;    
01031                     if(!mm_log_client.call(log))
01032                         ROS_WARN("Could not call map_merger service to store log.");
01033             }
01034     
01035         }
01036         
01037         void exploration_has_finished()
01038         {
01039             ros::Duration ros_time = ros::Time::now() - time_start;
01040             
01041             double exploration_time = ros_time.toSec();           
01042             int navigation_goals_required = counter;        
01043             double exploration_travel_path = (double)exploration->exploration_travel_path_global * 0.02;
01044             double size_global_map = map_progress_during_exploration.at(map_progress_during_exploration.size()-1).global_freespace;
01045             ROS_INFO("overall freespace in the global map: %f", size_global_map);
01046             
01047             for(int i = 0; i< map_progress_during_exploration.size(); i++)
01048             {
01049                 ROS_INFO("map progress: %f",(map_progress_during_exploration.at(i).global_freespace/size_global_map)*100);
01050             }
01051            
01052             ROS_DEBUG("******************************************");
01053             ROS_DEBUG("******************************************");
01054             ROS_DEBUG("TIME: %f sec  GOALS: %d  PATH: %f  COMPLETED AUCTIONS: %d  UNCOMPLETED AUCTIONS: %d", exploration_time, navigation_goals_required, exploration_travel_path, exploration->number_of_completed_auctions, exploration->number_of_uncompleted_auctions);
01055             ROS_DEBUG("******************************************");
01056             ROS_DEBUG("******************************************");
01057             
01058                   
01059             double efficiency_value = (exploration_time) / (number_of_robots * navigation_goals_required);
01060                     
01061             /*
01062              *  WRITE LOG FILE
01063              * Write all the output to the log file
01064              */
01065            save_progress(true);
01066             ROS_INFO("Wrote file %s\n", log_file.c_str());                    
01067             
01068             
01069             /*
01070              * Inform map_merger to save maps
01071              */
01072             
01073             map_merger::LogMaps log;
01074             log.request.log = 3;    
01075             if(!mm_log_client.call(log))
01076                 ROS_WARN("Could not call map_merger service to store log.");
01077 
01078                 
01079             // Indicte end of simulation for this robot
01080             this->indicateSimulationEnd();
01081    
01082 //#ifdef PROFILE
01083 //HeapProfilerStop();
01084 //ProfilerStop();
01085 //#endif
01086         }
01087         
01088         void indicateSimulationEnd()
01089         {
01091             std::stringstream robot_number;
01092             robot_number << robot_id;
01093             
01094             std::string prefix = "/robot_";
01095             std::string status_directory = "/simulation_status";
01096             std::string robo_name = prefix.append(robot_number.str());    
01097             std::string file_suffix(".finished");
01098 
01099             std::string ros_package_path = ros::package::getPath("multi_robot_analyzer");
01100             std::string status_path = ros_package_path + status_directory;
01101             std::string status_file = status_path + robo_name + file_suffix;
01102 
01104             boost::filesystem::path boost_status_path(status_path.c_str());
01105             if(!boost::filesystem::exists(boost_status_path))
01106                 if(!boost::filesystem::create_directories(boost_status_path))
01107                     ROS_ERROR("Cannot create directory %s.", status_path.c_str());
01108             std::ofstream outfile(status_file.c_str());
01109             outfile.close();
01110             ROS_INFO("Creating file %s to indicate end of exploration.", status_file.c_str());
01111 
01112 
01113         }
01114         
01115         
01116         bool iterate_global_costmap(std::vector<double> *global_goal, std::vector<std::string> *robot_str)
01117         {
01118             global_costmap_iteration++;
01119             int counter = 0;
01120             bool exploration_flag;
01121             
01122             costmap_mutex.lock();
01123 
01124             exploration->transformToOwnCoordinates_frontiers();
01125             exploration->transformToOwnCoordinates_visited_frontiers();
01126 
01127 //                          ros::Duration(1.0).sleep();
01128             exploration->initialize_planner("exploration planner", costmap2d_global, costmap2d_global);
01129             exploration->findFrontiers();
01130 //            exploration->printFrontiers();
01131 
01132             exploration->clearVisitedFrontiers();                       
01133             exploration->clearUnreachableFrontiers();
01134             exploration->clearSeenFrontiers(costmap2d_global);       
01135 
01136            costmap_mutex.unlock();
01137                             
01138            exploration->visualize_Frontiers();
01139            
01140                 if(frontier_selection < 5 && frontier_selection != 1)
01141                 {
01142                    exploration->sort(2);
01143                    
01144                     while(true)
01145                     {   
01146                         exploration_flag = exploration->determine_goal(2, global_goal, counter, -1, robot_str);
01147                         
01148                        
01149                         if(exploration_flag == false)
01150                         {
01151                            break;
01152                         }
01153                         else
01154                         {    
01155                             bool negotiation = true; 
01156                             negotiation = exploration->negotiate_Frontier(global_goal->at(0),global_goal->at(1),global_goal->at(2),global_goal->at(3), -1);
01157                             
01158                             if(negotiation == true)
01159                             {     
01160                                 return true;
01161                                 break;
01162                             }           
01163                             counter++;
01164                         }
01165                     }    
01166                 }else if(frontier_selection == 1 || frontier_selection == 6 || frontier_selection == 5)
01167                 {
01168                     costmap_mutex.lock();
01169                     exploration->clearVisitedAndSeenFrontiersFromClusters();
01170     
01171                     exploration->clusterFrontiers(); 
01172                     
01173                     exploration->sort(4);      
01174                     exploration->sort(5);
01175 
01176                     costmap_mutex.unlock(); 
01177                     
01178 //                    exploration->visualizeClustersConsole();
01179 
01180                     cluster_element = -1;
01181                     
01182                     while(true)
01183                     {                             
01184                         std::vector<double> goal_vector;
01185                         std::vector<std::string> robot_str_name;
01186                         std::vector<int> clusters_used_by_others; 
01187                         
01188                         goal_determined = exploration->determine_goal(5, &goal_vector, 0, cluster_element, robot_str);
01189 
01190                         if(goal_determined == false)
01191                         {  
01192                             ROS_INFO("No goal was determined, cluster is empty. Bid for another one");
01193 
01194                             goal_vector.clear();
01195                             bool auctioning = exploration->auctioning(&goal_vector, &clusters_used_by_others, &robot_str_name);
01196                             if(auctioning == true)
01197                             {                               
01198                                 goal_determined = true; 
01199                                 cluster_element = goal_vector.at(4);
01200                                 
01201                                 global_goal->push_back(goal_vector.at(0));
01202                                 global_goal->push_back(goal_vector.at(1));
01203                                 global_goal->push_back(goal_vector.at(2));
01204                                 global_goal->push_back(goal_vector.at(3));
01205                                 global_goal->push_back(goal_vector.at(4));
01206                                 
01207                                 robot_str->push_back(robot_str_name.at(0));
01208                                 return true; 
01209                             }
01210                             else
01211                             {
01212                                 /*
01213                                  * If NO goals are selected at all, iterate over the global
01214                                  * map to find some goals. 
01215                                  */
01216                                 ROS_ERROR("No goals are available at all");
01217                                 cluster_element = -1;
01218                                 break;
01219                             }
01220                         }
01221                         else
01222                         {
01223                             ROS_INFO("Still some goals in current cluster, finish this job first");
01224                             break;
01225                         }
01226                     }
01227 //                    while(true)
01228 //                    {                            
01229 //                        std::vector<double> goal_vector;
01230 //                        goal_determined = exploration->determine_goal(4, &goal_vector, counter, cluster_element);
01231 //
01232 //                        if(goal_determined == false)
01233 //                        {
01234 //                            ROS_INFO("Another cluster is not available, no cluster determined");
01235 //                            return false;
01236 //                        }
01237 //                        else
01238 //                        {
01239 //                             /*
01240 //                             * If negotiation is not needed, simply uncomment
01241 //                             * and set the negotiation to TRUE.
01242 //                             */
01243 //                            bool negotiation = exploration->negotiate_Frontier(goal_vector.at(0),goal_vector.at(1),goal_vector.at(2),goal_vector.at(3),goal_vector.at(4));
01244 //                            if(negotiation == true)
01245 //                            {
01246 //                                ROS_INFO("Negotiation was successful");
01247 //                                cluster_element = goal_vector.at(4);
01248 //
01249 //                                global_goal->push_back(goal_vector.at(0));
01250 //                                global_goal->push_back(goal_vector.at(1));
01251 //                                global_goal->push_back(goal_vector.at(2));
01252 //                                global_goal->push_back(goal_vector.at(3));
01253 //                                global_goal->push_back(goal_vector.at(4));
01254 //                                                              
01255 //                                return true;
01256 //                            }
01257 //                            else
01258 //                            {              
01259 //                                cluster_element = goal_vector.at(4);
01260 //                                ROS_ERROR("Negotiation was not successful, try next cluster");
01261 //                            }
01262 //                            counter++;
01263 //                        }
01264 //                    }  
01265                     exploration->visualize_Cluster_Cells();
01266             }
01267               
01268 //            exploration->visualize_Clusters();
01269 //            exploration->visualize_visited_Frontiers();
01270 
01271             global_iterattions++;
01272             return false;              
01273         }
01274 
01275         
01276         bool navigate(std::vector<double> goal) {
01277                 
01278                 /*
01279                  * If received goal is not empty (x=0 y=0), drive the robot to this point
01280                  * and mark that goal as seen in the last_goal_position vector!!!
01281                  * Otherwise turn the robot by 90° to the right and search again for a better
01282                  * frontier.
01283                  */
01284                 bool completed_navigation = false;
01285                 if (goal_determined == true)
01286                 {
01287                         visualize_goal_point(goal.at(0), goal.at(1));
01288                         
01289                         counter++;
01290                         ROS_INFO("GOAL %d:  x: %f      y: %f", counter, goal.at(0), goal.at(1));
01291                         completed_navigation = move_robot(counter, goal.at(0), goal.at(1));
01292                         rotation_counter = 0;
01293                 }
01294                 else
01295                 {
01296                         rotation_counter++;
01297 //                        ROS_INFO("In navigation .... cluster_available: %lu     counter: %d", clusters_available_in_pool.size(), counter_waiting_for_clusters);
01298                          ROS_INFO("In navigation .... cluster_available: %lu     counter: %d", exploration->clusters.size(), counter_waiting_for_clusters);                     
01299 //                        if(clusters_available_in_pool.size() <= 0 || counter_waiting_for_clusters > 10) //(rotation_counter >= 2)
01300                         if(exploration->clusters.size() == 0 || counter_waiting_for_clusters > 10) //(rotation_counter >= 2)
01301                         {
01302                             ROS_INFO("Iterating over GLOBAL COSTMAP to find a goal!!!!");
01303                             std::vector<double> global_goal;
01304                             std::vector<std::string> robot_str;
01305                             bool global_costmap_goal = iterate_global_costmap(&global_goal, &robot_str);
01306                                  
01307                             if(global_costmap_goal == false)
01308                             {
01309 //                                global_iterations_counter++;
01310 //                                if(global_iterations_counter >= 5)
01311 //                                {
01312                                     counter++;
01313                                     ROS_INFO("GOAL %d: BACK TO HOME   x: %f    y: %f", counter, home_point_x, home_point_y);
01314                                     
01315                                     /*
01316                                      * If the robot should drive to the home position
01317                                      * exploration_has_finished() has to be uncommented. 
01318                                      * It creates a file which is the immediate trigger to 
01319                                      * shut down the ros_node. Therefore the navigation process
01320                                      * is canceled . 
01321                                      */
01322                                     exploration_has_finished();
01323                                     visualize_goal_point(home_point_x, home_point_y);
01324                                     completed_navigation = false;
01325                                     for(int i = 0; i< 5; i++)
01326                                     {
01327                                         if(completed_navigation == false)
01328                                         {
01329                                            completed_navigation = move_robot(counter, home_point_x, home_point_y); 
01330                                         }
01331                                         else
01332                                         {
01333                                             break;
01334                                         }                                       
01335                                     }
01336                                     
01337                                     exploration_finished = true;
01338 //                                }else
01339 //                                {
01340 //                                    ROS_INFO("No Goal determined on GLOBAL COSTMAP for the %d time. Still wait ...", global_iterations_counter);
01341 //                                }
01342                             }else
01343                             {
01344                                     counter++;
01345                                     ROS_INFO("GOAL %d:  x: %f      y: %f", counter, global_goal.at(0), global_goal.at(1));
01346                                     std::vector<double> backoffGoal;
01347                                     bool backoff_sucessfull = exploration->smartGoalBackoff(global_goal.at(0),global_goal.at(1), costmap2d_global, &backoffGoal);
01348                                     
01349                                     if(backoff_sucessfull == true)
01350                                     {
01351                                         ROS_DEBUG("doing navigation to back-off goal");
01352                                         visualize_goal_point(backoffGoal.at(0), backoffGoal.at(1));
01353                                         completed_navigation = move_robot(counter, backoffGoal.at(0), backoffGoal.at(1));
01354                                         rotation_counter = 0;
01355                                         if(completed_navigation == true)
01356                                         {
01357                                             exploration->calculate_travel_path(exploration->visited_frontiers.at(exploration->visited_frontiers.size()-1).x_coordinate, exploration->visited_frontiers.at(exploration->visited_frontiers.size()-1).y_coordinate);
01358                                 
01359                                             ROS_INFO("Storing visited...");
01360                                             exploration->storeVisitedFrontier(global_goal.at(0),global_goal.at(1),global_goal.at(2),robot_str.at(0), global_goal.at(3)); 
01361                                             ROS_INFO("Stored Visited frontier");
01362                                         }   
01363                                         else
01364                                         {
01365                                             ROS_INFO("Storing unreachable...");
01366                                             exploration->storeUnreachableFrontier(global_goal.at(0),global_goal.at(1),global_goal.at(2),robot_str.at(0), global_goal.at(3));
01367                                             ROS_INFO("Stored unreachable frontier");
01368                                         }                          
01369                                     }
01370                                     else if(backoff_sucessfull == false)
01371                                     {
01372                                         ROS_ERROR("Navigation to global costmap back-off goal not possible"); 
01373                                         ROS_INFO("Storing as unreachable...");
01374                                         exploration->storeUnreachableFrontier(global_goal.at(0),global_goal.at(1),global_goal.at(2), robot_str.at(0), global_goal.at(3));
01375                                         ROS_INFO("Stored unreachable frontier");
01376                                     }
01377                             }
01378                         }else
01379                         {
01380                                 counter++;
01381                                 ROS_INFO("GOAL %d:  rotation", counter);
01382                                 completed_navigation = turn_robot(counter);
01383                         }
01384                 }      
01385                 return(completed_navigation);
01386         }
01387 
01388         void visualize_goal_point(double x, double y) {
01389 
01390                 goalPoint.header.seq = goal_point_message++;
01391                 goalPoint.header.stamp = ros::Time::now();
01392                 goalPoint.header.frame_id = move_base_frame; //"map"
01393                 goalPoint.point.x = x;// - robotPose.getOrigin().getX();
01394                 goalPoint.point.y = y;// - robotPose.getOrigin().getY();
01395 
01396                 ros::NodeHandle nh_Point("goalPoint");
01397                 pub_Point = nh_Point.advertise < geometry_msgs::PointStamped
01398                                 > ("goalPoint", 100, true);
01399                 pub_Point.publish < geometry_msgs::PointStamped > (goalPoint);
01400         }
01401 
01402         void visualize_home_point() {
01403 
01404                 homePoint.header.seq = home_point_message++;
01405                 homePoint.header.stamp = ros::Time::now();
01406                 homePoint.header.frame_id = move_base_frame; //"map";
01407                 home_point_x = robotPose.getOrigin().getX();
01408                 home_point_y = robotPose.getOrigin().getY();
01409                 homePoint.point.x = home_point_x;
01410                 homePoint.point.y = home_point_y;
01411 
01412                 ros::NodeHandle nh("homePoint");
01413                 pub_home_Point = nh.advertise < geometry_msgs::PointStamped
01414                                 > ("homePoint", 100, true);
01415                 pub_home_Point.publish < geometry_msgs::PointStamped > (homePoint);
01416 
01417         }
01418 
01419         bool move_robot(int seq, double position_x, double position_y) {
01420             
01421             exploration->next_auction_position_x = position_x;
01422             exploration->next_auction_position_y = position_y;
01423             
01424                 /*
01425                  * Move the robot with the help of an action client. Goal positions are
01426                  * transmitted to the robot and feedback is given about the actual
01427                  * driving state of the robot.
01428                  */
01429                 if (!costmap2d_local->getRobotPose(robotPose)) {
01430                         ROS_ERROR("Failed to get RobotPose");
01431                 }
01432                 
01433                 actionlib::SimpleActionClient < move_base_msgs::MoveBaseAction
01434                                 > ac("move_base", true);
01435 
01436                 while (!ac.waitForServer(ros::Duration(10.0)))
01437                         ;
01438            
01439                 move_base_msgs::MoveBaseGoal goal_msgs;
01440 
01441                 goal_msgs.target_pose.header.seq = seq; // increase the sequence number
01442 //              goal_msgs.target_pose.header.stamp = ros::Time::now();
01443                 goal_msgs.target_pose.header.frame_id = move_base_frame; //"map";
01444                 goal_msgs.target_pose.pose.position.x = position_x;// - robotPose.getOrigin().getX(); //goals[0].pose.position.x;
01445                 goal_msgs.target_pose.pose.position.y = position_y;// - robotPose.getOrigin().getY();
01446                 goal_msgs.target_pose.pose.position.z = 0;
01447                 goal_msgs.target_pose.pose.orientation.x = 0; //sin(angle/2); // goals[0].pose.orientation.x;
01448                 goal_msgs.target_pose.pose.orientation.y = 0;
01449                 goal_msgs.target_pose.pose.orientation.z = 0;
01450                 goal_msgs.target_pose.pose.orientation.w = 1;
01451 
01452                 ac.sendGoal(goal_msgs);
01453                
01454         //ac.waitForResult(ros::Duration(20)); EDIT Peter: Test if it also works with smaller value!
01455         ac.waitForResult(ros::Duration(waitForResult)); //here Parameter!
01456         while (ac.getState() == actionlib::SimpleClientGoalState::PENDING)
01457         {
01458             ros::Duration(0.5).sleep();
01459         }
01460                 ROS_INFO("Not longer PENDING");
01461 
01462         while (ac.getState() == actionlib::SimpleClientGoalState::ACTIVE)
01463         {
01464             ros::Duration(0.5).sleep();
01465         }
01466                 ROS_INFO("Not longer ACTIVE");
01467 
01468                 while (ac.getState() != actionlib::SimpleClientGoalState::SUCCEEDED) {
01469                         if (ac.getState() == actionlib::SimpleClientGoalState::ABORTED) {
01470                                 ROS_INFO("ABORTED");
01471                                 
01472                                 exploration->next_auction_position_x = robotPose.getOrigin().getX();
01473                                 exploration->next_auction_position_y = robotPose.getOrigin().getY();
01474                                 return false;
01475                         }
01476                         /*
01477                          double my_time = ros::Time::now().toSec();
01478                          //ROS_ERROR("my_time: %f     timeout: %f",my_time,timeout);
01479                          if(my_time >= timeout)
01480                          {
01481                          ROS_ERROR("Timeout exceeded");
01482                          break;
01483                          }
01484                          if(ac.getState() == actionlib::SimpleClientGoalState::PREEMPTED){ROS_ERROR("PREEMPTED");}
01485                          if(ac.getState() == actionlib::SimpleClientGoalState::ABORTED){ROS_ERROR("ABORTED");}
01486                          if(ac.getState() == actionlib::SimpleClientGoalState::REJECTED){ROS_ERROR("REJECTED");}
01487                          if(ac.getState() == actionlib::SimpleClientGoalState::RECALLED){ROS_ERROR("RECALLED");}
01488                          */
01489                 }
01490                 ROS_INFO("TARGET REACHED");
01491                 
01492                 exploration->next_auction_position_x = robotPose.getOrigin().getX();
01493                 exploration->next_auction_position_y = robotPose.getOrigin().getY();
01494                 return true;
01495         }
01496 
01497         bool turn_robot(int seq) {
01498                 
01499                 double angle = 45;
01500 
01501                 if (!costmap2d_local->getRobotPose(robotPose)) {
01502                         ROS_ERROR("Failed to get RobotPose");
01503                 }
01504                 
01505                 actionlib::SimpleActionClient < move_base_msgs::MoveBaseAction
01506                                 > ac("move_base", true);
01507                 while (!ac.waitForServer(ros::Duration(10.0)))
01508                         ;
01509 
01510                 move_base_msgs::MoveBaseGoal goal_msgs;
01511 
01512                 goal_msgs.target_pose.header.seq = seq; // increase the sequence number
01513                 goal_msgs.target_pose.header.stamp = ros::Time::now();
01514 
01515                 goal_msgs.target_pose.header.frame_id = move_base_frame;//"map";
01516                 goal_msgs.target_pose.pose.position.x = robotPose.getOrigin().getX();
01517                 goal_msgs.target_pose.pose.position.y = robotPose.getOrigin().getY();
01518                 goal_msgs.target_pose.pose.position.z = 0;
01519                 goal_msgs.target_pose.pose.orientation.x = 0; //sin(angle/2); // goals[0].pose.orientation.x;
01520                 goal_msgs.target_pose.pose.orientation.y = 0;
01521                 goal_msgs.target_pose.pose.orientation.z = sin(angle / 2);
01522                 goal_msgs.target_pose.pose.orientation.w = cos(angle / 2);
01523 
01524                 ac.sendGoal(goal_msgs);
01525                 ac.waitForResult(ros::Duration(waitForResult));
01526 
01527                 while (ac.getState() == actionlib::SimpleClientGoalState::PENDING)
01528                 {
01529                     ros::Duration(0.5).sleep();
01530                 }
01531                 ROS_INFO("Not longer PENDING");
01532 
01533                 while (ac.getState() == actionlib::SimpleClientGoalState::ACTIVE)
01534                 {
01535                     ros::Duration(0.5).sleep();
01536                 }
01537                 ROS_INFO("Not longer ACTIVE");
01538 
01539                 while (ac.getState() != actionlib::SimpleClientGoalState::SUCCEEDED) {
01540                         if (ac.getState() == actionlib::SimpleClientGoalState::ABORTED) {
01541                                 ROS_INFO("ABORTED");                                
01542                                 return false;
01543                         }
01544                 }
01545                 ROS_INFO("ROTATION ACCOMBLISHED");
01546                 return true;
01547         }
01548 
01549         void feedbackCallback(
01550                         const move_base_msgs::MoveBaseActionFeedback::ConstPtr& msg) {
01551                 feedback_value = msg.get()->status.status;
01552                 feedback_succeed_value =
01553                                 msg.get()->feedback.base_position.pose.orientation.w;
01554 
01555         }
01556 
01557         bool target_reached(void) {
01558 
01559                 ros::NodeHandle nh_sub_move_base;
01560                 sub_move_base = nh_sub_move_base.subscribe("feedback", 1000,
01561                                 &Explorer::feedbackCallback, this);
01562 
01563                 while (feedback_value != feedback_succeed_value)
01564                         ;
01565 
01566                 return true;
01567         }
01568 
01569 public:
01570 
01571         struct map_progress_t
01572         {
01573             double local_freespace;
01574             double global_freespace;
01575             double time;
01576         } map_progress;
01577         
01578         ros::Subscriber sub_move_base, sub_obstacle;    
01579         
01580         // create a costmap
01581         costmap_2d::Costmap2DROS* costmap2d_local;
01582         costmap_2d::Costmap2DROS* costmap2d_local_size;
01583         costmap_2d::Costmap2DROS* costmap2d_global;
01584         costmap_2d::Costmap2D costmap;
01585 
01586         std::vector<map_progress_t> map_progress_during_exploration;
01587         
01588         std::vector<int> clusters_available_in_pool;
01589         
01590         int home_position_x, home_position_y;
01591         int robot_id, number_of_robots;
01592         int frontier_selection, costmap_width, global_costmap_iteration, number_unreachable_frontiers_for_cluster;
01593         int counter_waiting_for_clusters;
01594         
01595         double robot_home_position_x, robot_home_position_y;
01596         bool Simulation, goal_determined;
01597         bool robot_prefix_empty;
01598         int accessing_cluster, cluster_element_size, cluster_element;
01599         int global_iterattions;
01600         bool cluster_flag, cluster_initialize_flag;
01601         int global_iterations_counter; 
01602         int waitForResult;
01603         std::string move_base_frame;
01604         std::string robot_prefix;               
01605         std::string robot_name;
01606         const unsigned char* occupancy_grid_global;
01607         const unsigned char* occupancy_grid_local;
01608         
01609         std::string csv_file, log_file;
01610         std::string log_path;
01611         std::fstream fs_csv, fs;
01612                 
01613 private:
01614         
01615         ros::Publisher pub_move_base;
01616         ros::Publisher pub_Point;
01617         ros::Publisher pub_home_Point;
01618         ros::Publisher pub_frontiers;
01619 
01620         ros::ServiceClient mm_log_client;
01621         
01622         ros::NodeHandle nh;
01623         ros::Time time_start;
01624 
01625         //Create a move_base_msgs to define a goal to steer the robot to
01626         move_base_msgs::MoveBaseActionGoal action_goal_msg;
01627         move_base_msgs::MoveBaseActionFeedback feedback_msgs;
01628 
01629         //move_base::MoveBase simple_move_base;
01630         geometry_msgs::PointStamped goalPoint;
01631         geometry_msgs::PointStamped homePoint;
01632 
01633         std::vector<geometry_msgs::PoseStamped> goals;
01634         tf::Stamped<tf::Pose> robotPose;
01635 
01636         explorationPlanner::ExplorationPlanner *exploration;       
01637         
01638         double x_val, y_val, home_point_x, home_point_y;
01639         int seq, feedback_value, feedback_succeed_value, rotation_counter,
01640                         home_point_message, goal_point_message;
01641         int counter;
01642         bool pioneer, exploration_finished;
01643 };
01644 
01645 int main(int argc, char **argv) {
01646         /*
01647          * ROS::init() function needs argc and argv to perform
01648          * any argument and remapping that is provided by the
01649          * command line. The third argument is the name of the node
01650          */
01651         ros::init(argc, argv, "simple_navigation");
01652         /*
01653          * Create instance of Simple Navigation
01654          */
01655         tf::TransformListener tf(ros::Duration(10));
01656         Explorer simple(tf);
01657 
01658         /*
01659          * The ros::spin command is needed to wait for any call-back. This could for
01660          * example be a subscription on another topic. Do this to be able to receive a
01661          * message.
01662          */
01663 
01664         boost::thread thr_explore(boost::bind(&Explorer::explore, &simple));    
01665 //        boost::thread thr_frontiers(boost::bind(&SimpleNavigation::frontiers, &simple));
01666         /*
01667          * The following thread is only necessary to log simulation results.
01668          * Otherwise it produces unused output.
01669          */
01670         boost::thread thr_map(boost::bind(&Explorer::map_info, &simple));
01671         
01672         /*
01673          * FIXME
01674          * Which rate is required in order not to oversee
01675          * any callback data (frontiers, negotiation ...)
01676          */
01677 //        ros::Rate r(5); // FIXME 30
01678         while (ros::ok()) {
01679            
01680             costmap_mutex.lock(); 
01681             ros::spinOnce();
01682             costmap_mutex.unlock();
01683            
01684 //            r.sleep();
01685             ros::Duration(0.1).sleep();
01686         }
01687 
01688         thr_explore.interrupt();
01689         thr_map.interrupt();
01690 //      thr_frontiers.interrupt();
01691         
01692         thr_explore.join();
01693         thr_map.join();
01694 //        thr_frontiers.interrupt();
01695         
01696         return 0;
01697 }


explorer
Author(s): Daniel Neuhold , Torsten Andre
autogenerated on Thu Aug 27 2015 11:56:52