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 uint next_vertex;
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...BACKUP & 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 if ( atoi(argv[3]) >= NUM_MAX_ROBOTS || atoi(argv[3])<-1 ){
00346 ROS_INFO("The Robot's ID must be an integer number between 0 and %d", NUM_MAX_ROBOTS-1);
00347 return 0;
00348 }else{
00349 ID_ROBOT = atoi(argv[3]);
00350 }
00351
00352
00353 uint i = strlen( argv[2] );
00354 char graph_file[i];
00355 strcpy (graph_file,argv[2]);
00356
00357
00358 uint dimension = GetGraphDimension(graph_file);
00359
00360
00361 vertex vertex_web[dimension];
00362
00363
00364 GetGraphInfo(vertex_web, dimension, graph_file);
00365
00366 uint j;
00367
00368
00369
00370
00371 for (i=0;i<dimension;i++){
00372 printf ("ID= %u\n", vertex_web[i].id);
00373 printf ("X= %f, Y= %f\n", vertex_web[i].x, vertex_web[i].y);
00374 printf ("#Neigh= %u\n", vertex_web[i].num_neigh);
00375
00376 for (j=0;j<vertex_web[i].num_neigh; j++){
00377 printf("\tID = %u, DIR = %s, COST = %u\n", vertex_web[i].id_neigh[j], vertex_web[i].dir[j], vertex_web[i].cost[j]);
00378 }
00379
00380 printf("\n");
00381 }
00382
00383
00384
00385
00386
00387 ros::init(argc, argv, "c_cognitive");
00388 ros::NodeHandle nh;
00389 double initial_x, initial_y;
00390
00391 XmlRpc::XmlRpcValue list;
00392 nh.getParam("initial_pos", list);
00393 ROS_ASSERT(list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00394
00395 int value = ID_ROBOT;
00396 if (value == -1){value = 0;}
00397
00398 ROS_ASSERT(list[2*value].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00399 initial_x = static_cast<double>(list[2*value]);
00400
00401 ROS_ASSERT(list[2*value+1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00402 initial_y = static_cast<double>(list[2*value+1]);
00403
00404
00405 uint current_vertex = IdentifyVertex(vertex_web, dimension, initial_x, initial_y);
00406
00407
00408
00409 odom_pub = nh.advertise<nav_msgs::Odometry>("positions", 1);
00410
00411
00412 odom_sub = nh.subscribe("positions", 10, positionsCB);
00413
00414 char string[20];
00415 char string2[20];
00416
00417 if(ID_ROBOT==-1){
00418 strcpy (string,"odom");
00419 strcpy (string2,"cmd_vel");
00420 TEAMSIZE = 1;
00421 }else{
00422 strcpy (string,"robot_");
00423 strcpy (string2,"robot_");
00424 char id[3];
00425 itoa(ID_ROBOT, id, 10);
00426 strcat(string,id);
00427 strcat(string2,id);
00428 strcat(string,"/odom");
00429 strcat(string2,"/cmd_vel");
00430 TEAMSIZE = ID_ROBOT + 1;
00431 }
00432
00433
00434
00435
00436 cmd_vel_pub = nh.advertise<geometry_msgs::Twist>(string2, 1);
00437
00438
00439 ros::Subscriber sub;
00440 sub = nh.subscribe(string, 1, odomCB);
00441 ros::spinOnce();
00442
00443
00444
00445
00446 if(ID_ROBOT==-1){
00447 strcpy (string,"move_base");
00448 }else{
00449 strcpy (string,"robot_");
00450 char id[3];
00451 itoa(ID_ROBOT, id, 10);
00452 strcat(string,id);
00453 strcat(string,"/move_base");
00454 }
00455
00456
00457 MoveBaseClient ac(string, true);
00458
00459
00460 while(!ac.waitForServer(ros::Duration(5.0))){
00461 ROS_INFO("Waiting for the move_base action server to come up");
00462 }
00463
00464
00465 move_base_msgs::MoveBaseGoal goal;
00466
00467
00468 results_pub = nh.advertise<geometry_msgs::PointStamped>("results", 1);
00469 results_sub = nh.subscribe("results", 10, resultsCB);
00470
00471 initialize_node();
00472 ros::Rate loop_rate(1);
00473
00474
00475 while(initialize){
00476 ros::spinOnce();
00477 loop_rate.sleep();
00478 }
00479
00480
00481
00482
00483 double instantaneous_idleness [dimension];
00484 double last_visit [dimension];
00485 for(i=0;i<dimension;i++){
00486 instantaneous_idleness[i]= 0.0;
00487 last_visit[i]= 0.0;
00488
00489 if(i==current_vertex){
00490 last_visit[i]= 0.1;
00491 }
00492 }
00493
00494
00495 bool inpath = false;
00496 uint path [dimension];
00497 uint elem_s_path=0, i_path=0;
00498
00499 interference = false;
00500 ResendGoal = false;
00501 goal_complete = true;
00502
00503
00504
00505 while(1){
00506
00507 if (goal_complete){
00508
00509 if (i_path>0){
00510
00511 double now = ros::Time::now().toSec();
00512
00513 for(i=0; i<dimension; i++){
00514 if (i == next_vertex){
00515 last_visit[i] = now;
00516 }
00517 instantaneous_idleness[i]= now - last_visit[i];
00518 }
00519
00520 current_vertex = next_vertex;
00521
00522
00523
00524
00525
00526
00527
00528 }
00529
00530 if(inpath){
00531
00532 i_path++;
00533
00534 if (i_path<elem_s_path){
00535 next_vertex=path[i_path];
00536 }else{
00537 inpath = false;
00538 }
00539 }
00540
00541 if (!inpath){
00542 elem_s_path = heuristic_pathfinder_conscientious_cognitive(current_vertex, vertex_web, instantaneous_idleness, dimension, path);
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 i_path=1;
00555 next_vertex = path[i_path];
00556 inpath = true;
00557
00558 }
00559
00560 if (inpath){
00561
00562 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00563
00564
00565 goal.target_pose.header.frame_id = "map";
00566 goal.target_pose.header.stamp = ros::Time::now();
00567 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00568 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00569 goal.target_pose.pose.orientation = angle_quat;
00570 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00571 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00572
00573
00574 }
00575
00576 goal_complete = false;
00577
00578
00579 }else{
00580
00581 if (interference){
00582
00583
00584 ROS_INFO("Interference detected!\n");
00585 send_interference();
00586
00587
00588 ros::spinOnce();
00589
00590
00591 while(interference){
00592 interference = check_interference();
00593 if (goal_complete || ResendGoal){
00594 interference = false;
00595 }
00596 }
00597
00598 }
00599
00600 if(ResendGoal){
00601 geometry_msgs::Quaternion angle_quat = tf::createQuaternionMsgFromYaw(0.0);
00602
00603
00604 goal.target_pose.header.frame_id = "map";
00605 goal.target_pose.header.stamp = ros::Time::now();
00606 goal.target_pose.pose.position.x = vertex_web[next_vertex].x;
00607 goal.target_pose.pose.position.y = vertex_web[next_vertex].y;
00608 goal.target_pose.pose.orientation = angle_quat;
00609 ROS_INFO("Sending goal - Vertex %d (%f,%f)\n", next_vertex, vertex_web[next_vertex].x, vertex_web[next_vertex].y);
00610
00611 ac.sendGoal(goal, boost::bind(&goalDoneCallback, _1, _2), boost::bind(&goalActiveCallback), boost::bind(&goalFeedbackCallback, _1));
00612 ResendGoal = false;
00613 }
00614
00615 if(end_simulation){
00616 return 0;
00617 }
00618
00619
00620
00621 }
00622
00623 }
00624
00625
00626 }