00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <ros/ros.h>
00039 #include <move_base_msgs/MoveBaseAction.h>
00040 #include <actionlib/client/simple_action_client.h>
00041 #include <tf/transform_broadcaster.h>
00042 #include <nav_msgs/Odometry.h>
00043
00044 #include "getgraph.h"
00045 #include "algorithms.h"
00046
00047 #define NUM_MAX_ROBOTS 32
00048
00049 typedef unsigned int uint;
00050 typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
00051
00052 bool ResendGoal;
00053 bool interference;
00054 bool goal_complete;
00055 bool initialize = true;
00056 bool end_simulation = false;
00057 int next_vertex = -1;
00058 uint backUpCounter;
00059
00060
00061 bool arrived = false;
00062 uint vertex_arrived;
00063 int robot_arrived;
00064
00065 int TEAMSIZE;
00066 int ID_ROBOT;
00067
00068 double xPos[NUM_MAX_ROBOTS];
00069 double yPos[NUM_MAX_ROBOTS];
00070
00071 ros::Subscriber odom_sub;
00072 ros::Publisher odom_pub;
00073 ros::Subscriber results_sub;
00074 ros::Publisher results_pub;
00075 ros::Publisher cmd_vel_pub;
00076
00077 void send_goal_result (uint vertex){
00078
00079
00080
00081
00082 printf("Send Vertex %u [Goal] to Results: Robot %d\n",vertex,ID_ROBOT);
00083
00084 geometry_msgs::PointStamped msg;
00085 char id_robot_str[3];
00086 sprintf(id_robot_str, "%d", ID_ROBOT);
00087
00088 msg.header.frame_id = id_robot_str;
00089 msg.point.x = float (vertex);
00090 msg.point.y = 0.0;
00091 msg.point.z = 0.0;
00092
00093 results_pub.publish(msg);
00094 ros::spinOnce();
00095 }
00096
00097 void backup(){
00098
00099 while (backUpCounter<=100){
00100
00101 if(backUpCounter==0){
00102 ROS_INFO("The wall is too close! I need to do some backing up...");
00103
00104 geometry_msgs::Twist cmd_vel;
00105 cmd_vel.linear.x = -0.1;
00106 cmd_vel.angular.z = 0.0;
00107 cmd_vel_pub.publish(cmd_vel);
00108 }
00109
00110 if(backUpCounter==40){
00111
00112 geometry_msgs::Twist cmd_vel;
00113 cmd_vel.linear.x = 0.0;
00114 cmd_vel.angular.z = 0.5;
00115 cmd_vel_pub.publish(cmd_vel);
00116 }
00117
00118 if(backUpCounter==100){
00119
00120 geometry_msgs::Twist cmd_vel;
00121 cmd_vel.linear.x = 0.0;
00122 cmd_vel.angular.z = 0.0;
00123 cmd_vel_pub.publish(cmd_vel);
00124
00125 ROS_INFO("Done backing up, now on with my life!");
00126 }
00127
00128 backUpCounter++;
00129 }
00130
00131 }
00132
00133 void goalDoneCallback(const actionlib::SimpleClientGoalState &state, const move_base_msgs::MoveBaseResultConstPtr &result){
00134
00135
00136
00137
00138
00139
00140 if(state.state_ == actionlib::SimpleClientGoalState::SUCCEEDED){
00141 ROS_INFO("SUCCESS");
00142 goal_complete = true;
00143 send_goal_result (next_vertex);
00144
00145 }else{
00146 ROS_INFO("CANCELLED or ABORTED...BACKUP & Resend Goal!");
00147 backUpCounter = 0;
00148 backup();
00149 ResendGoal = true;
00150 }
00151 }
00152
00153 void goalActiveCallback(){
00154 goal_complete = false;
00155
00156 }
00157
00158 void odomCB(const nav_msgs::Odometry::ConstPtr& msg) {
00159
00160
00161 int idx = ID_ROBOT;
00162
00163 if (ID_ROBOT<=-1){
00164 idx = 0;
00165 }
00166
00167 xPos[idx]=msg->pose.pose.position.x;
00168 yPos[idx]=msg->pose.pose.position.y;
00169
00170
00171 }
00172
00173 void positionsCB(const nav_msgs::Odometry::ConstPtr& msg) {
00174
00175
00176
00177 char id[20];
00178 strcpy( id, msg->header.frame_id.c_str() );
00179
00180
00181
00182
00183
00184 if (ID_ROBOT>-1){
00185
00186
00187 char str_idx[4];
00188 uint i;
00189
00190 for (i=6; i<10; i++){
00191 if (id[i]=='/'){
00192 str_idx[i-6] = '\0';
00193 break;
00194 }else{
00195 str_idx[i-6] = id[i];
00196 }
00197 }
00198
00199 int idx = atoi (str_idx);
00200
00201
00202 if (idx >= TEAMSIZE && TEAMSIZE <= NUM_MAX_ROBOTS){
00203
00204 TEAMSIZE = idx+1;
00205 }
00206
00207 if (ID_ROBOT != idx){
00208 xPos[idx]=msg->pose.pose.position.x;
00209 yPos[idx]=msg->pose.pose.position.y;
00210 }
00211
00212 }
00213 }
00214
00215 void resultsCB(const geometry_msgs::PointStamped::ConstPtr& msg) {
00216
00217 if(initialize){
00218
00219
00220
00221 if (msg->header.frame_id == "monitor"){
00222 printf("Let's Patrol!\n");
00223 initialize = false;
00224 }
00225
00226 }else {
00227
00228 if (msg->header.frame_id == "monitor" && msg->point.x == 1.0 && msg->point.y == 1.0 && msg->point.z == 1.0){
00229 printf("The simulation is over. Let's leave\n");
00230 end_simulation = true;
00231
00232
00233 }else if (msg->header.frame_id != "monitor") {
00234
00235 double interf = msg->point.y;
00236 double init = msg->point.z;
00237
00238 robot_arrived = atoi( msg->header.frame_id.c_str() );
00239 vertex_arrived = (int)msg->point.x;
00240
00241 if (interf == 0.0 && init == 0.0){
00242 if (robot_arrived != ID_ROBOT){
00243 arrived = true;
00244
00245 }
00246 }
00247 }
00248 }
00249 }
00250
00251 void initialize_node (){
00252
00253
00254
00255
00256 printf("Initialize Node: Robot %d\n",ID_ROBOT);
00257 ros::Rate loop_rate(1);
00258
00259 geometry_msgs::PointStamped msg;
00260
00261 char id_robot_str[3];
00262 sprintf(id_robot_str, "%d", ID_ROBOT);
00263
00264 msg.header.frame_id = id_robot_str;
00265 msg.point.x = 0.0;
00266 msg.point.y = 0.0;
00267 msg.point.z = (float) ID_ROBOT;
00268
00269 int count = 0;
00270 while (count<2){
00271 results_pub.publish(msg);
00272 ros::spinOnce();
00273
00274 loop_rate.sleep();
00275 count++;
00276 }
00277 }
00278
00279 void send_interference(){
00280
00281
00282
00283
00284 printf("Send Interference: Robot %d\n",ID_ROBOT);
00285
00286
00287 geometry_msgs::PointStamped msg;
00288 char id_robot_str[3];
00289 sprintf(id_robot_str, "%d", ID_ROBOT);
00290
00291 msg.header.frame_id = id_robot_str;
00292 msg.point.x = 0.0;
00293 msg.point.y = 1.0;
00294 msg.point.z = 0.0;
00295
00296 results_pub.publish(msg);
00297 ros::spinOnce();
00298 }
00299
00300 bool check_interference (void){
00301
00302 int i;
00303 double dist_quad;
00304
00305
00306 for (i=0; i<ID_ROBOT; i++){
00307
00308 dist_quad = (xPos[i] - xPos[ID_ROBOT])*(xPos[i] - xPos[ID_ROBOT]) + (yPos[i] - yPos[ID_ROBOT])*(yPos[i] - yPos[ID_ROBOT]);
00309
00310 if (dist_quad <= 4){
00311
00312 interference = true;
00313 return interference;
00314 }
00315 }
00316
00317 interference = false;
00318 return interference;
00319
00320 }
00321
00322 void goalFeedbackCallback(const move_base_msgs::MoveBaseFeedbackConstPtr &feedback){
00323
00324
00325
00326
00327 nav_msgs::Odometry msg;
00328
00329 int idx = ID_ROBOT;
00330
00331 if (ID_ROBOT <= -1){
00332 msg.header.frame_id = "odom";
00333 idx = 0;
00334 }else{
00335 char string[20];
00336 strcpy (string,"robot_");
00337 char id[3];
00338 itoa(ID_ROBOT, id, 10);
00339 strcat(string,id);
00340 strcat(string,"/odom");
00341
00342 msg.header.frame_id = string;
00343 }
00344
00345 msg.pose.pose.position.x = xPos[idx];
00346 msg.pose.pose.position.y = yPos[idx];
00347
00348 odom_pub.publish(msg);
00349 ros::spinOnce();
00350
00351
00352
00353
00354 check_interference();
00355 }
00356
00357
00358 int main(int argc, char** argv){
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 if ( atoi(argv[3])>NUM_MAX_ROBOTS || atoi(argv[3])<-1 ){
00371 ROS_INFO("The Robot's ID must be an integer number between 0 an 99");
00372 return 0;
00373 }else{
00374 ID_ROBOT = atoi(argv[3]);
00375
00376 }
00377
00378 uint i = strlen( argv[2] );
00379 char graph_file[i];
00380 strcpy (graph_file,argv[2]);
00381
00382
00383 uint dimension = GetGraphDimension(graph_file);
00384
00385
00386 vertex vertex_web[dimension];
00387
00388
00389 GetGraphInfo(vertex_web, dimension, graph_file);
00390
00391
00392
00394 double G1 = 0.1;
00395
00396 int NUMBER_OF_ROBOTS = atoi(argv[4]);
00397
00398
00399 double G2 = 100.0;
00400 double edge_min = 1.0;
00401
00402 if ( strcmp (graph_file,"maps/grid/grid.graph") == 0 ){
00403 if (NUMBER_OF_ROBOTS == 1){G2 = 20.54;}
00404 if (NUMBER_OF_ROBOTS == 2){G2 = 17.70;}
00405 if (NUMBER_OF_ROBOTS == 4){G2 = 11.15;}
00406 if (NUMBER_OF_ROBOTS == 6){G2 = 10.71;}
00407 if (NUMBER_OF_ROBOTS == 8){G2 = 10.29;}
00408 if (NUMBER_OF_ROBOTS == 12){G2 = 9.13;}
00409
00410 }else if (strcmp (graph_file,"maps/example/example.graph") == 0 ) {
00411 if (NUMBER_OF_ROBOTS == 1){G2 = 220.0;}
00412 if (NUMBER_OF_ROBOTS == 2){G2 = 180.5;}
00413 if (NUMBER_OF_ROBOTS == 4){G2 = 159.3;}
00414 if (NUMBER_OF_ROBOTS == 6){G2 = 137.15;}
00415 if (NUMBER_OF_ROBOTS == 8 || NUMBER_OF_ROBOTS == 12){G2 = 126.1;}
00416 edge_min = 20.0;
00417
00418 }else if (strcmp (graph_file,"maps/cumberland/cumberland.graph") == 0) {
00419 if (NUMBER_OF_ROBOTS == 1){G2 = 152.0;}
00420 if (NUMBER_OF_ROBOTS == 2){G2 = 100.4;}
00421 if (NUMBER_OF_ROBOTS == 4){G2 = 80.74;}
00422 if (NUMBER_OF_ROBOTS == 6){G2 = 77.0;}
00423 if (NUMBER_OF_ROBOTS == 8 || NUMBER_OF_ROBOTS == 12){G2 = 63.5;}
00424 edge_min = 50.0;
00425
00426 }
00427
00428 printf("G1 = %f, G2 = %f\n", G1, G2);
00429
00430
00431
00432
00433
00434 ros::init(argc, argv, "c_reactive");
00435 ros::NodeHandle nh;
00436 double initial_x, initial_y;
00437
00438 XmlRpc::XmlRpcValue list;
00439 nh.getParam("initial_pos", list);
00440 ROS_ASSERT(list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00441
00442 int value = ID_ROBOT;
00443 if (value == -1){value = 0;}
00444
00445 ROS_ASSERT(list[2*value].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00446 initial_x = static_cast<double>(list[2*value]);
00447
00448 ROS_ASSERT(list[2*value+1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00449 initial_y = static_cast<double>(list[2*value+1]);
00450
00451
00452 uint current_vertex = IdentifyVertex(vertex_web, dimension, initial_x, initial_y);
00453
00454
00455
00456
00457 odom_pub = nh.advertise<nav_msgs::Odometry>("positions", 1);
00458
00459
00460 odom_sub = nh.subscribe("positions", 10, positionsCB);
00461
00462 char string[20];
00463 char string2[20];
00464
00465 if(ID_ROBOT==-1){
00466 strcpy (string,"odom");
00467 strcpy (string2,"cmd_vel");
00468 TEAMSIZE = 1;
00469 }else{
00470 strcpy (string,"robot_");
00471 strcpy (string2,"robot_");
00472 char id[3];
00473 itoa(ID_ROBOT, id, 10);
00474 strcat(string,id);
00475 strcat(string2,id);
00476 strcat(string,"/odom");
00477 strcat(string2,"/cmd_vel");
00478 TEAMSIZE = ID_ROBOT + 1;
00479 }
00480
00481
00482
00483
00484 cmd_vel_pub = nh.advertise<geometry_msgs::Twist>(string2, 1);
00485
00486
00487 ros::Subscriber sub;
00488 sub = nh.subscribe(string, 1, odomCB);
00489 ros::spinOnce();
00490
00491
00492
00493
00494 if(ID_ROBOT==-1){
00495 strcpy (string,"move_base");
00496 }else{
00497 strcpy (string,"robot_");
00498 char id[3];
00499 itoa(ID_ROBOT, id, 10);
00500 strcat(string,id);
00501 strcat(string,"/move_base");
00502 }
00503
00504
00505 MoveBaseClient ac(string, true);
00506
00507
00508 while(!ac.waitForServer(ros::Duration(5.0))){
00509 ROS_INFO("Waiting for the move_base action server to come up");
00510 }
00511
00512
00513 move_base_msgs::MoveBaseGoal goal;
00514
00515
00516 results_pub = nh.advertise<geometry_msgs::PointStamped>("results", 1);
00517 results_sub = nh.subscribe("results", 10, resultsCB);
00518
00519 initialize_node();
00520 ros::Rate loop_rate(1);
00521
00522
00523 while(initialize){
00524 ros::spinOnce();
00525 loop_rate.sleep();
00526 }
00527
00528
00529
00530 double instantaneous_idleness [dimension];
00531 double last_visit [dimension];
00532 for(i=0;i<dimension;i++){
00533 instantaneous_idleness[i]= 0.0;
00534 last_visit[i]= 0.0;
00535
00536 if(i==current_vertex){
00537 last_visit[i]= 0.1;
00538 }
00539 }
00540
00541 interference = false;
00542 ResendGoal = false;
00543 goal_complete = true;
00544
00545 double now;
00546
00547
00548 while(1){
00549
00550 if(goal_complete){
00551
00552 if(next_vertex>-1){
00553
00554 now = ros::Time::now().toSec();
00555
00556 for(i=0; i<dimension; i++){
00557 if (i == next_vertex){
00558 last_visit[i] = now;
00559 }
00560 instantaneous_idleness[i]= now - last_visit[i];
00561 }
00562
00563 current_vertex = next_vertex;
00564
00565
00566
00567
00568
00569
00570 }
00571
00572
00573 next_vertex = (int) greedy_bayesian_strategy(current_vertex, vertex_web, instantaneous_idleness, G1, G2, edge_min);
00574
00575
00576
00577 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00578 goal.target_pose.header.frame_id = "map";
00579 goal.target_pose.header.stamp = ros::Time::now();
00580 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00581 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00582 goal.target_pose.pose.orientation = angle_quat;
00583 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00584 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00585
00586
00587 goal_complete = false;
00588
00589 }else{
00590 if (interference){
00591
00592
00593 ROS_INFO("Interference detected!\n");
00594 send_interference();
00595
00596
00597 ros::spinOnce();
00598
00599
00600 while(interference){
00601 interference = check_interference();
00602 if (goal_complete || ResendGoal){
00603 interference = false;
00604 }
00605 }
00606
00607 }
00608
00609 if(ResendGoal){
00610
00611 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00612 goal.target_pose.header.frame_id = "map";
00613 goal.target_pose.header.stamp = ros::Time::now();
00614 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00615 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00616 goal.target_pose.pose.orientation = angle_quat;
00617 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00618
00619 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00620 ResendGoal = false;
00621 }
00622
00623 if (arrived && NUMBER_OF_ROBOTS>1){
00624
00625
00626
00627
00628 now = ros::Time::now().toSec();
00629
00630 for(i=0; i<dimension; i++){
00631 if (i == vertex_arrived){
00632
00633 last_visit[vertex_arrived] = now;
00634 }
00635
00636 instantaneous_idleness[i]= now - last_visit[i];
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646 arrived = false;
00647 }
00648
00649 if(end_simulation){
00650 return 0;
00651 }
00652
00653 }
00654 }
00655
00656 return 0;
00657 }