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