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 int TEAMSIZE;
00061 int ID_ROBOT;
00062
00063 double xPos[NUM_MAX_ROBOTS];
00064 double yPos[NUM_MAX_ROBOTS];
00065
00066 ros::Subscriber odom_sub;
00067 ros::Publisher odom_pub;
00068 ros::Subscriber results_sub;
00069 ros::Publisher results_pub;
00070 ros::Publisher cmd_vel_pub;
00071
00072 void send_goal_result (uint vertex){
00073
00074
00075
00076
00077 printf("Send Vertex %u [Goal] to Results: Robot %d\n",vertex,ID_ROBOT);
00078
00079 geometry_msgs::PointStamped msg;
00080 char id_robot_str[3];
00081 sprintf(id_robot_str, "%d", ID_ROBOT);
00082
00083 msg.header.frame_id = id_robot_str;
00084 msg.point.x = float (vertex);
00085 msg.point.y = 0.0;
00086 msg.point.z = 0.0;
00087
00088 results_pub.publish(msg);
00089 ros::spinOnce();
00090 }
00091
00092 void backup(){
00093
00094 while (backUpCounter<=100){
00095
00096 if(backUpCounter==0){
00097 ROS_INFO("The wall is too close! I need to do some backing up...");
00098
00099 geometry_msgs::Twist cmd_vel;
00100 cmd_vel.linear.x = -0.1;
00101 cmd_vel.angular.z = 0.0;
00102 cmd_vel_pub.publish(cmd_vel);
00103 }
00104
00105 if(backUpCounter==40){
00106
00107 geometry_msgs::Twist cmd_vel;
00108 cmd_vel.linear.x = 0.0;
00109 cmd_vel.angular.z = 0.5;
00110 cmd_vel_pub.publish(cmd_vel);
00111 }
00112
00113 if(backUpCounter==100){
00114
00115 geometry_msgs::Twist cmd_vel;
00116 cmd_vel.linear.x = 0.0;
00117 cmd_vel.angular.z = 0.0;
00118 cmd_vel_pub.publish(cmd_vel);
00119
00120 ROS_INFO("Done backing up, now on with my life!");
00121 }
00122
00123 backUpCounter++;
00124 }
00125
00126 }
00127
00128 void goalDoneCallback(const actionlib::SimpleClientGoalState &state, const move_base_msgs::MoveBaseResultConstPtr &result){
00129
00130
00131
00132
00133
00134
00135 if(state.state_ == actionlib::SimpleClientGoalState::SUCCEEDED){
00136 ROS_INFO("SUCCESS");
00137 goal_complete = true;
00138 send_goal_result (next_vertex);
00139
00140 }else{
00141 ROS_INFO("CANCELLED or ABORTED...Resend Goal!");
00142 backUpCounter = 0;
00143 backup();
00144 ResendGoal = true;
00145 }
00146 }
00147
00148 void goalActiveCallback(){
00149 goal_complete = false;
00150
00151 }
00152
00153 void odomCB(const nav_msgs::Odometry::ConstPtr& msg) {
00154
00155
00156 int idx = ID_ROBOT;
00157
00158 if (ID_ROBOT<=-1){
00159 idx = 0;
00160 }
00161
00162 xPos[idx]=msg->pose.pose.position.x;
00163 yPos[idx]=msg->pose.pose.position.y;
00164
00165
00166 }
00167
00168 void positionsCB(const nav_msgs::Odometry::ConstPtr& msg) {
00169
00170
00171
00172 char id[20];
00173 strcpy( id, msg->header.frame_id.c_str() );
00174
00175
00176
00177
00178
00179 if (ID_ROBOT>-1){
00180
00181
00182 char str_idx[4];
00183 uint i;
00184
00185 for (i=6; i<10; i++){
00186 if (id[i]=='/'){
00187 str_idx[i-6] = '\0';
00188 break;
00189 }else{
00190 str_idx[i-6] = id[i];
00191 }
00192 }
00193
00194 int idx = atoi (str_idx);
00195
00196
00197 if (idx >= TEAMSIZE && TEAMSIZE <= NUM_MAX_ROBOTS){
00198
00199 TEAMSIZE = idx+1;
00200 }
00201
00202 if (ID_ROBOT != idx){
00203 xPos[idx]=msg->pose.pose.position.x;
00204 yPos[idx]=msg->pose.pose.position.y;
00205 }
00206
00207 }
00208 }
00209
00210 void resultsCB(const geometry_msgs::PointStamped::ConstPtr& msg) {
00211
00212 if(initialize){
00213
00214
00215
00216 if (msg->header.frame_id == "monitor"){
00217 printf("Let's Patrol!\n");
00218 initialize = false;
00219 }
00220 }else {
00221 if (msg->header.frame_id == "monitor" && msg->point.x == 1.0 && msg->point.y == 1.0 && msg->point.z == 1.0){
00222 printf("The simulation is over. Let's leave\n");
00223 end_simulation = true;
00224 }
00225 }
00226 }
00227
00228 void initialize_node (){
00229
00230
00231
00232
00233 printf("Initialize Node: Robot %d\n",ID_ROBOT);
00234 ros::Rate loop_rate(1);
00235
00236 geometry_msgs::PointStamped msg;
00237
00238 char id_robot_str[3];
00239 sprintf(id_robot_str, "%d", ID_ROBOT);
00240
00241 msg.header.frame_id = id_robot_str;
00242 msg.point.x = 0.0;
00243 msg.point.y = 0.0;
00244 msg.point.z = (float) ID_ROBOT;
00245
00246 int count = 0;
00247 while (count<2){
00248 results_pub.publish(msg);
00249 ros::spinOnce();
00250
00251 loop_rate.sleep();
00252 count++;
00253 }
00254 }
00255
00256 void send_interference(){
00257
00258
00259
00260
00261 printf("Send Interference: Robot %d\n",ID_ROBOT);
00262
00263
00264 geometry_msgs::PointStamped msg;
00265 char id_robot_str[3];
00266 sprintf(id_robot_str, "%d", ID_ROBOT);
00267
00268 msg.header.frame_id = id_robot_str;
00269 msg.point.x = 0.0;
00270 msg.point.y = 1.0;
00271 msg.point.z = 0.0;
00272
00273 results_pub.publish(msg);
00274 ros::spinOnce();
00275 }
00276
00277 bool check_interference (void){
00278
00279 int i;
00280 double dist_quad;
00281
00282
00283 for (i=0; i<ID_ROBOT; i++){
00284
00285 dist_quad = (xPos[i] - xPos[ID_ROBOT])*(xPos[i] - xPos[ID_ROBOT]) + (yPos[i] - yPos[ID_ROBOT])*(yPos[i] - yPos[ID_ROBOT]);
00286
00287 if (dist_quad <= 4){
00288
00289 interference = true;
00290 return interference;
00291 }
00292 }
00293
00294 interference = false;
00295 return interference;
00296
00297 }
00298
00299 void goalFeedbackCallback(const move_base_msgs::MoveBaseFeedbackConstPtr &feedback){
00300
00301
00302
00303
00304 nav_msgs::Odometry msg;
00305
00306 int idx = ID_ROBOT;
00307
00308 if (ID_ROBOT <= -1){
00309 msg.header.frame_id = "odom";
00310 idx = 0;
00311 }else{
00312 char string[20];
00313 strcpy (string,"robot_");
00314 char id[3];
00315 itoa(ID_ROBOT, id, 10);
00316 strcat(string,id);
00317 strcat(string,"/odom");
00318
00319 msg.header.frame_id = string;
00320 }
00321
00322 msg.pose.pose.position.x = xPos[idx];
00323 msg.pose.pose.position.y = yPos[idx];
00324
00325 odom_pub.publish(msg);
00326 ros::spinOnce();
00327
00328
00329
00330
00331 check_interference();
00332 }
00333
00334
00335 int main(int argc, char** argv){
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 if ( atoi(argv[3])>NUM_MAX_ROBOTS || atoi(argv[3])<-1 ){
00347 ROS_INFO("The Robot's ID must be an integer number between 0 an 99");
00348 return 0;
00349 }else{
00350 ID_ROBOT = atoi(argv[3]);
00351
00352 }
00353
00354 uint i = strlen( argv[2] );
00355 char graph_file[i];
00356 strcpy (graph_file,argv[2]);
00357
00358
00359 uint dimension = GetGraphDimension(graph_file);
00360
00361
00362 vertex vertex_web[dimension];
00363
00364
00365 GetGraphInfo(vertex_web, dimension, graph_file);
00366
00367 uint j;
00368
00369
00370
00371
00372 for (i=0;i<dimension;i++){
00373 printf ("ID= %u\n", vertex_web[i].id);
00374 printf ("X= %f, Y= %f\n", vertex_web[i].x, vertex_web[i].y);
00375 printf ("#Neigh= %u\n", vertex_web[i].num_neigh);
00376
00377 for (j=0;j<vertex_web[i].num_neigh; j++){
00378 printf("\tID = %u, DIR = %s, COST = %u\n", vertex_web[i].id_neigh[j], vertex_web[i].dir[j], vertex_web[i].cost[j]);
00379 }
00380
00381 printf("\n");
00382 }
00383
00384
00385
00386
00387
00388 ros::init(argc, argv, "hc_reactive");
00389 ros::NodeHandle nh;
00390 double initial_x, initial_y;
00391
00392 XmlRpc::XmlRpcValue list;
00393 nh.getParam("initial_pos", list);
00394 ROS_ASSERT(list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00395
00396 int value = ID_ROBOT;
00397 if (value == -1){value = 0;}
00398
00399 ROS_ASSERT(list[2*value].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00400 initial_x = static_cast<double>(list[2*value]);
00401
00402 ROS_ASSERT(list[2*value+1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00403 initial_y = static_cast<double>(list[2*value+1]);
00404
00405
00406 uint current_vertex = IdentifyVertex(vertex_web, dimension, initial_x, initial_y);
00407
00408
00409
00410 odom_pub = nh.advertise<nav_msgs::Odometry>("positions", 1);
00411
00412
00413 odom_sub = nh.subscribe("positions", 10, positionsCB);
00414
00415 char string[20];
00416 char string2[20];
00417
00418 if(ID_ROBOT==-1){
00419 strcpy (string,"odom");
00420 strcpy (string2,"cmd_vel");
00421 TEAMSIZE = 1;
00422 }else{
00423 strcpy (string,"robot_");
00424 strcpy (string2,"robot_");
00425 char id[3];
00426 itoa(ID_ROBOT, id, 10);
00427 strcat(string,id);
00428 strcat(string2,id);
00429 strcat(string,"/odom");
00430 strcat(string2,"/cmd_vel");
00431 TEAMSIZE = ID_ROBOT + 1;
00432 }
00433
00434
00435
00436
00437 cmd_vel_pub = nh.advertise<geometry_msgs::Twist>(string2, 1);
00438
00439
00440 ros::Subscriber sub;
00441 sub = nh.subscribe(string, 1, odomCB);
00442 ros::spinOnce();
00443
00444
00445
00446
00447 if(ID_ROBOT==-1){
00448 strcpy (string,"move_base");
00449 }else{
00450 strcpy (string,"robot_");
00451 char id[3];
00452 itoa(ID_ROBOT, id, 10);
00453 strcat(string,id);
00454 strcat(string,"/move_base");
00455 }
00456
00457
00458 MoveBaseClient ac(string, true);
00459
00460
00461 while(!ac.waitForServer(ros::Duration(5.0))){
00462 ROS_INFO("Waiting for the move_base action server to come up");
00463 }
00464
00465
00466 move_base_msgs::MoveBaseGoal goal;
00467
00468
00469 results_pub = nh.advertise<geometry_msgs::PointStamped>("results", 1);
00470 results_sub = nh.subscribe("results", 10, resultsCB);
00471
00472 initialize_node();
00473 ros::Rate loop_rate(1);
00474
00475
00476 while(initialize){
00477 ros::spinOnce();
00478 loop_rate.sleep();
00479 }
00480
00481
00482
00483
00484 double instantaneous_idleness [dimension];
00485 double last_visit [dimension];
00486 for(i=0;i<dimension;i++){
00487 instantaneous_idleness[i]= 0.0;
00488 last_visit[i]= 0.0;
00489
00490 if(i==current_vertex){
00491 last_visit[i]= 0.1;
00492 }
00493 }
00494
00495 interference = false;
00496 ResendGoal = false;
00497 goal_complete = true;
00498
00499
00500 while(1){
00501
00502 if(goal_complete){
00503
00504 if (next_vertex>-1){
00505
00506 double now = ros::Time::now().toSec();
00507
00508 for(i=0; i<dimension; i++){
00509 if (i == next_vertex){
00510 last_visit[i] = now;
00511 }
00512 instantaneous_idleness[i]= now - last_visit[i];
00513 }
00514
00515 current_vertex = next_vertex;
00516
00517
00518
00519
00520
00521 }
00522
00523
00524 next_vertex = (int) heuristic_conscientious_reactive(current_vertex, vertex_web, instantaneous_idleness);
00525
00526
00527
00528 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00529 goal.target_pose.header.frame_id = "map";
00530 goal.target_pose.header.stamp = ros::Time::now();
00531 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00532 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00533 goal.target_pose.pose.orientation = angle_quat;
00534 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00535 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 goal_complete = false;
00547
00548 }else{
00549 if (interference){
00550
00551
00552 ROS_INFO("Interference detected!\n");
00553 send_interference();
00554
00555
00556 ros::spinOnce();
00557
00558
00559 while(interference){
00560 interference = check_interference();
00561 if (goal_complete || ResendGoal){
00562 interference = false;
00563 }
00564 }
00565
00566 }
00567
00568 if(ResendGoal){
00569
00570 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00571 goal.target_pose.header.frame_id = "map";
00572 goal.target_pose.header.stamp = ros::Time::now();
00573 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00574 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00575 goal.target_pose.pose.orientation = angle_quat;
00576 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00577
00578 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00579 ResendGoal = false;
00580 }
00581
00582 if(end_simulation){
00583 return 0;
00584 }
00585
00586 }
00587 }
00588 return 0;
00589 }