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
00039 #include <tedusar_daf_path_follower/tedusar_daf_path_follower.hpp>
00040
00041 namespace tedusar_path_follower
00042 {
00043 tedusar_path_follower::tedusar_path_follower(ros::NodeHandle nh)
00044 : nh_(nh),
00045 execute_path_action_server_(nh_, "execute_path", boost::bind(&tedusar_path_follower::executePathCB, this, _1), false)
00046 {
00047
00048 ros::NodeHandle private_nh("~");
00049
00050 private_nh.param<double>("pub_cmd_hz", pub_cmd_hz, 10);
00051 private_nh.param<std::string>("path_topic", path_topic, string("/exploration_path"));
00052 private_nh.param<std::string>("pose_update_topic", pose_update_topic, string("/odom"));
00053 private_nh.param<std::string>("imu_data", imu_topic, string("/imu_data"));
00054 private_nh.param<std::string>("out_cmd_vel", cmd_vel_out, string("/cmd_vel"));
00055 private_nh.param<std::string>("map_link", map_link, string("/map"));
00056 private_nh.param<std::string>("base_link", base_link, string("/base_footprint"));
00057 private_nh.param<double>("max_lin_vel", max_lin_speed, 0.4);
00058 private_nh.param<double>("min_lin_vel", min_lin_speed, 0.1);
00059 private_nh.param<double>("max_rot_vel", max_rot_speed, 0.8);
00060 private_nh.param<double>("min_rot_vel", min_rot_speed, 0.4);
00061 private_nh.param<double>("rot_correction_factor", rot_correction_factor, 1);
00062 private_nh.param<double>("execution_period", execution_period, 1.0);
00063 private_nh.param<double>("update_skip_until_vel_increase", update_skip, 5);
00064 private_nh.param<double>("global_goal_tolerance", global_goal_tolerance, 0.2);
00065 private_nh.param<double>("lower_al_angle", lower_al_angle, 0.2);
00066 private_nh.param<double>("upper_al_angle", upper_al_angle, 0.6);
00067
00068 private_nh.param<bool>("enable_angle_compensation", enable_angle_compensation, true);
00069 private_nh.param<bool>("enable_ground_compensation", enable_ground_compensation, true);
00070 private_nh.param<bool>("enable_velocity_encrease", enable_velocity_encrease, true);
00071 private_nh.param<bool>("show_trajectory_planing", show_trajectory_planing, true);
00072 private_nh.param<double>("stability_angle", stability_angle, 1.0);
00073 }
00074
00075
00076
00077 tedusar_path_follower::~tedusar_path_follower()
00078 {
00079 }
00080
00081
00082
00083 void tedusar_path_follower::init()
00084 {
00085
00086 pose_update_sub = nh_.subscribe<nav_msgs::Odometry>(pose_update_topic ,10 , &tedusar_path_follower::pose_update, this);
00087 cmd_vel_pub = nh_.advertise<geometry_msgs::Twist>(cmd_vel_out, 1);
00088 imu_data_sub = nh_.subscribe<sensor_msgs::Imu>(imu_topic, 1, &tedusar_path_follower::imuCallback, this);
00089
00090
00091 if(show_trajectory_planing)
00092 {
00093 path_pub = nh_.advertise<nav_msgs::Path>("/calc_path", 1);
00094 local_path_pub = nh_.advertise<nav_msgs::Path>("/local_calc_path", 1);
00095 marker_pub = nh_.advertise<visualization_msgs::Marker>("visualization_marker", 1);
00096 }
00097
00098
00099 resetPathFollowing();
00100
00101
00102 execute_path_action_server_.start();
00103 }
00104
00105
00106
00107 void tedusar_path_follower::resetPathFollowing()
00108 {
00109 alignment_finished = false;
00110 co_unchanged = 0;
00111 st_point = 0;
00112 path_po_lenght = 0;
00113 lin_vel = max_lin_speed/2;
00114
00115
00116 lin_vel_ref = lin_vel;
00117
00118
00119
00120 imu_yaw = 0;
00121 imu_pitch = 0;
00122 imu_roll = 0;
00123 old_pos_x = 0;
00124 old_pos_y = 0;
00125 rad = 0;
00126 err_cont = 0;
00127 oscilation_rotation = 1;
00128
00129 move_robot = false;
00130 cmd.linear.x = 0.0;
00131 cmd.angular.z = 0.0;
00132 cmd_vel_pub.publish(cmd);
00133 }
00134
00135
00136
00137 void tedusar_path_follower::imuCallback(const sensor_msgs::ImuConstPtr &imu_msg)
00138 {
00139 tf::Quaternion imu_quaternion;
00140 tf::quaternionMsgToTF(imu_msg->orientation, imu_quaternion);
00141 tf::Transform imu_orientation(imu_quaternion, tf::Vector3(0,0,0));
00142 imu_orientation.getBasis().getEulerYPR(imu_yaw, imu_pitch, imu_roll);
00143 }
00144
00145
00146
00147 void tedusar_path_follower::pose_update(const nav_msgs::Odometry pose)
00148 {
00149
00150 if(move_robot)
00151 {
00152
00153 if(listener.canTransform(map_link, base_link, ros::Time(0)))
00154 {
00155 now = ros::Time::now();
00156 listener.lookupTransform(map_link, base_link, ros::Time(0), transform);
00157 origin = transform.getOrigin();
00158 rotation = transform.getRotation();
00159 axis = rotation.getAxis();
00160 odom.pose.pose.position.x = origin.x();
00161 odom.pose.pose.position.y = origin.y();
00162 odom.pose.pose.position.z = origin.z();
00163 tf::Quaternion q(transform.getRotation().x(), transform.getRotation().y(), transform.getRotation().z(), transform.getRotation().w());
00164 tf::Matrix3x3 m(q);
00165 m.getRPY(roll, pitch, yaw);
00166
00167
00168 calc_local_path();
00169
00170
00171 velocity_increase();
00172 }else
00173 {
00174 ROS_WARN("There is no transfrmationa avaliable from %s to %s", map_link.c_str(), base_link.c_str());
00175 }
00176 }
00177 }
00178
00179
00180
00181 void tedusar_path_follower::path_cb(const nav_msgs::Path::ConstPtr& path)
00182 {
00183 curr_path = *path;
00184 psize = (int)curr_path.poses.size();
00185 dist = abs(execution_period*max_lin_speed);
00186
00187 if(psize > 0) {
00188 move_robot = true;
00189 }else{
00190 move_robot = false;}
00191
00192 ROS_INFO("New Path Received from topic. Path seq: %i size: %i distance to plan path: %f", curr_path.header.seq, psize, dist);
00193 }
00194
00195
00196
00197 void tedusar_path_follower::calc_local_path()
00198 {
00199 path_po_lenght = 0;
00200
00201 for(int i=0; i < psize; i++)
00202 {
00203 double curr_dist_x = abs(odom.pose.pose.position.x - curr_path.poses[i].pose.position.x);
00204 double curr_dist_y = abs(odom.pose.pose.position.y - curr_path.poses[i].pose.position.y);
00205 double curr_dist = sqrt(curr_dist_x*curr_dist_x + curr_dist_y*curr_dist_y);
00206
00207 if(abs(curr_dist) > dist)
00208 {
00209 continue;
00210 }
00211 path_po_lenght = path_po_lenght + 1;
00212 }
00213
00214 double min_dif = 10.0;
00215
00216
00217 points[0][0] = odom.pose.pose.position.x;
00218 points[0][1] = odom.pose.pose.position.y;
00219
00220
00221 for(int i=0; i < psize; i++)
00222 {
00223 double po_dist = sqrt((curr_path.poses[i].pose.position.x - points[0][0])*(curr_path.poses[i].pose.position.x - points[0][0]) + (curr_path.poses[i].pose.position.y - points[0][1])*(curr_path.poses[i].pose.position.y - points[0][1]));
00224 if(abs(po_dist) < min_dif)
00225 {
00226 min_dif = abs(po_dist);
00227 st_point = i;
00228 }
00229 }
00230
00231
00232
00233 co_points = 0;
00234 for(int i=st_point; i < (st_point+path_po_lenght); i++)
00235 {
00236 if(i > (psize-2))
00237 {
00238 co_points = co_points +1;
00239 points[co_points][0] = curr_path.poses[i].pose.position.x;
00240 points[co_points][1] = curr_path.poses[i].pose.position.y;
00241 i = (st_point+path_po_lenght)+1;
00242 }else
00243 {
00244 co_points = co_points +1;
00245 points[co_points][0] = curr_path.poses[i].pose.position.x;
00246 points[co_points][1] = curr_path.poses[i].pose.position.y;
00247 }
00248 }
00249
00250 th_po_x = 0; th_po_y = 0; fi_po_x = 0; fi_po_y = 0;
00251 se_po_x = 0; se_po_y = 0; dirx = 1; diry = -1; max_H = 0;
00252
00253
00254 for(int i=0; i < co_points; i++)
00255 {
00256
00257
00258
00259 sideA = sqrt(((points[0][0] - points[i][0])*(points[0][0] - points[i][0])) + (points[0][1] - points[i][1])*(points[0][1] - points[i][1]));
00260 sideB = sqrt(((points[i][0] - points[co_points][0])*(points[i][0] - points[co_points][0])) + (points[i][1] - points[co_points][1])*(points[i][1] - points[co_points][1]));
00261 sideC = sqrt(((points[co_points][0] - points[0][0])*(points[co_points][0] - points[0][0])) + (points[co_points][1] - points[0][1])*(points[co_points][1] - points[0][1]));
00262
00263 ss = (sideA + sideB + sideC)/2;
00264 area = sqrt(ss*(ss-sideA)*(ss-sideB)*(ss-sideC));
00265
00266 tmp_H = (area*2)/sideC;
00267
00268 if(tmp_H > max_H)
00269 {
00270 max_H = tmp_H;
00271 float det_dir = (points[co_points][0] - points[1][0])*(points[i][1] - points[0][1]) - (points[co_points][1] - points[0][1])*(points[i][0]- points[0][0]);
00272 se_po_x = points[i][0];
00273 se_po_y = points[i][1];
00274
00275 if(det_dir > 0)
00276 {
00277 dirx = -1;
00278 diry = 1;
00279 rot_vel_dir = -1;
00280 }else
00281 {
00282 dirx = 1;
00283 diry = -1;
00284 rot_vel_dir = 1;
00285 }
00286 }
00287 Wid = sideC;
00288 }
00289
00290
00291 if(co_points < 3)
00292 {
00293 max_H = 0.001;
00294 }
00295
00296
00297
00298
00299 calc_ground_compensation();
00300
00301 fi_po_x = points[0][0];
00302 fi_po_y = points[0][1];
00303 th_po_x = points[co_points][0];
00304 th_po_y = points[co_points][1];
00305
00306
00307 rad = max_H/2 + (Wid*Wid)/(8*max_H);
00308
00309
00310
00311 midX = (points[0][0] + points[co_points][0])/2;
00312 midY = (points[0][1] + points[co_points][1])/2;
00313 dx = (points[0][0] - points[co_points][0])/2;
00314 dy = (points[0][1] - points[co_points][1])/2;
00315 distt = sqrt(dx*dx + dy*dy);
00316 pdist = sqrt(rad*rad - distt*distt);
00317 mDx = dirx*dy*pdist/distt;
00318 mDy = diry*dx*pdist/distt;
00319
00320
00321 double curr_dist_x = points[0][0] - (midX + mDx);
00322 double curr_dist_y = points[0][1] - (midY + mDy);
00323
00324
00325 if((curr_dist_x < 0)&&(curr_dist_y < 0))
00326 {
00327 alignment_angle = atan2(curr_dist_y,curr_dist_x) + rot_vel_dir*PI/2;
00328 }
00329 else if((curr_dist_x > 0)&&(curr_dist_y > 0))
00330 {
00331 alignment_angle = atan2(curr_dist_y,curr_dist_x) + rot_vel_dir*PI/2;
00332 }
00333 else if((curr_dist_x < 0)&&(curr_dist_y > 0))
00334 {
00335 alignment_angle = atan2(curr_dist_y,curr_dist_x) + rot_vel_dir*PI/2;
00336 }
00337 else if((curr_dist_x > 0)&&(curr_dist_y < 0))
00338 {
00339 alignment_angle = atan2(curr_dist_y,curr_dist_x) + rot_vel_dir*PI/2;
00340 }
00341
00342
00343 if(alignment_angle > PI)
00344 {
00345 alignment_angle = alignment_angle - 2*PI;
00346 }
00347 if(alignment_angle < -PI)
00348 {
00349 alignment_angle = alignment_angle + 2*PI;
00350 }
00351
00352 if(isnan(alignment_angle))
00353 {
00354 ROS_WARN("Alignment Angle can not be computed!");
00355 }
00356
00357
00358 if(isnan(alignment_angle))
00359 {
00360 ROS_INFO("Alignment angle is nan - return to calc_local_path");
00361 calc_local_path();
00362 }
00363
00364
00365 feedback.feedback = (int)round((100*st_point)/psize);
00366 execute_path_action_server_.publishFeedback(feedback);
00367
00368
00369 if(show_trajectory_planing == true)
00370 {
00371 uint32_t shape = visualization_msgs::Marker::CUBE;
00372
00373 local_calc_path.header.frame_id = map_link;
00374 local_calc_path.poses.resize(360);
00375
00376 for(int d= 0; d < 360; d++)
00377 {
00378 double xp = sin(d*0.0174532925)*rad + (midX + mDx);
00379 double yp = cos(d*0.0174532925)*rad + (midY + mDy);
00380 local_calc_path.poses[d].pose.position.x = xp;
00381 local_calc_path.poses[d].pose.position.y = yp;
00382 local_calc_path.poses[d].pose.position.z = 0;
00383 }
00384
00385 local_path_pub.publish(local_calc_path);
00386
00387
00388 calc_path.header.frame_id = map_link;
00389 calc_path.poses.resize(4);
00390
00391
00392 calc_path.poses[0].pose.position.x = points[0][0];
00393 calc_path.poses[0].pose.position.y = points[0][1];
00394 calc_path.poses[0].pose.position.z = 0;
00395 calc_path.poses[1].pose.position.x = se_po_x;
00396 calc_path.poses[1].pose.position.y = se_po_y;
00397 calc_path.poses[1].pose.position.z = 0;
00398 calc_path.poses[2].pose.position.x = points[co_points][0];
00399 calc_path.poses[2].pose.position.y = points[co_points][1];
00400 calc_path.poses[2].pose.position.z = 0;
00401 calc_path.poses[3].pose.position.x = points[0][0];
00402 calc_path.poses[3].pose.position.y = points[0][1];
00403 calc_path.poses[3].pose.position.z = 0;
00404 calc_path.poses.resize(4);
00405 path_pub.publish(calc_path);
00406
00407
00408 visualization_msgs::Marker marker;
00409 marker.header.frame_id = map_link;
00410 marker.header.stamp = ros::Time::now();
00411
00412 marker.ns = "first_point";
00413 marker.id = 0;
00414 marker.type = shape;
00415 marker.action = visualization_msgs::Marker::ADD;
00416 marker.pose.position.x = fi_po_x;
00417 marker.pose.position.y = fi_po_y;
00418 marker.pose.position.z = 0;
00419 marker.pose.orientation.x = 0.0;
00420 marker.pose.orientation.y = 0.0;
00421 marker.pose.orientation.z = 0.0;
00422 marker.pose.orientation.w = 1.0;
00423
00424 marker.scale.x = 0.02;
00425 marker.scale.y = 0.02;
00426 marker.scale.z = 0.02;
00427
00428 marker.color.r = 1;
00429 marker.color.g = 0;
00430 marker.color.b = 0;
00431 marker.color.a = 1.0;
00432 marker.lifetime = ros::Duration();
00433
00434 marker_pub.publish(marker);
00435
00436 marker.ns = "second_point";
00437 marker.id = 2;
00438 marker.type = shape;
00439 marker.action = visualization_msgs::Marker::ADD;
00440 marker.pose.position.x = se_po_x;
00441 marker.pose.position.y = se_po_y;
00442 marker.pose.position.z = 0;
00443 marker.pose.orientation.x = 0.0;
00444 marker.pose.orientation.y = 0.0;
00445 marker.pose.orientation.z = 0.0;
00446 marker.pose.orientation.w = 1.0;
00447
00448 marker.scale.x = 0.02;
00449 marker.scale.y = 0.02;
00450 marker.scale.z = 0.02;
00451
00452 marker.color.r = 0;
00453 marker.color.g = 1;
00454 marker.color.b = 0;
00455 marker.color.a = 1.0;
00456 marker.lifetime = ros::Duration();
00457
00458 marker_pub.publish(marker);
00459
00460
00461 marker.ns = "third_point";
00462 marker.id = 4;
00463 marker.type = shape;
00464 marker.action = visualization_msgs::Marker::ADD;
00465 marker.pose.position.x = th_po_x;
00466 marker.pose.position.y = th_po_y;
00467 marker.pose.position.z = 0;
00468 marker.pose.orientation.x = 0.0;
00469 marker.pose.orientation.y = 0.0;
00470 marker.pose.orientation.z = 0.0;
00471 marker.pose.orientation.w = 1.0;
00472
00473 marker.scale.x = 0.02;
00474 marker.scale.y = 0.02;
00475 marker.scale.z = 0.02;
00476
00477 marker.color.r = 0;
00478 marker.color.g = 0;
00479 marker.color.b = 1;
00480 marker.color.a = 1.0;
00481 marker.lifetime = ros::Duration();
00482
00483 marker_pub.publish(marker);
00484 }
00485 }
00486
00487
00488
00489 void tedusar_path_follower::calc_ground_compensation()
00490 {
00491 if(enable_ground_compensation == true)
00492 {
00493
00494 double dh = abs((max_H/cos(imu_roll))-max_H);
00495 double dw = abs((Wid/cos(imu_pitch))-Wid);
00496
00497 max_H = max_H + dh;
00498 Wid = Wid + dw;
00499
00500 }
00501 }
00502
00503
00504
00505 void tedusar_path_follower::check_robot_stability()
00506 {
00507
00508 if((imu_roll > stability_angle)||(imu_pitch > stability_angle))
00509 {
00510 action_result.result = 1;
00511 execute_path_action_server_.setAborted(action_result, std::string("Robot has exceeded angle of stability!"));
00512 resetPathFollowing();
00513 ROS_WARN("Robot has exceeded angle of stability!");
00514 }
00515 }
00516
00517
00518
00519 void tedusar_path_follower::calculate_al_rot()
00520 {
00521
00522 angle_diff = alignment_angle - yaw;
00523
00524 if(fabs(angle_diff) > M_PI)
00525 {
00526 if(angle_diff > 0)
00527 {
00528 angle_diff = -2 * M_PI + fabs(angle_diff);
00529 }
00530 else
00531 {
00532 angle_diff = 2 * M_PI - fabs(angle_diff);
00533 }
00534 }
00535
00536 if(angle_diff > 0){rot_dir_opti = 1;}
00537 else{ rot_dir_opti = -1;}
00538 }
00539
00540
00541
00542 void tedusar_path_follower::executePathCB(const ExecutePathGoalConstPtr &goal)
00543 {
00544 resetPathFollowing();
00545
00546 curr_path = goal->path;
00547
00548 psize = (int)curr_path.poses.size();
00549 dist = abs(execution_period*max_lin_speed);
00550
00551 if(psize > 0)
00552 {
00553 ROS_INFO("New Path Received from Action. Path seq: %i size: %i distance to plan path: %f", curr_path.header.seq, psize, dist);
00554 move_robot = true;
00555
00556 ros::Rate r(pub_cmd_hz);
00557 while(ros::ok())
00558 {
00559 if(execute_path_action_server_.isPreemptRequested() || !move_robot)
00560 {
00561 move_robot = false;
00562 resetPathFollowing();
00563 execute_path_action_server_.setPreempted();
00564 ROS_INFO("path execution is preempted");
00565 return;
00566 }
00567 calculate_cmd();
00568 r.sleep();
00569 }
00570 }else{
00571 move_robot = false;
00572
00573
00574 action_result.result = 1;
00575 execute_path_action_server_.setAborted(action_result, std::string("Path size is 0"));
00576 }
00577 }
00578
00579
00580
00581 void tedusar_path_follower::calc_angel_compensation()
00582 {
00583 if(enable_angle_compensation == true)
00584 {
00585
00586 angle_diff = alignment_angle - yaw;
00587
00588 if(fabs(angle_diff) > M_PI)
00589 {
00590 if(angle_diff > 0)
00591 {
00592 angle_diff = -2 * M_PI + fabs(angle_diff);
00593 }
00594 else
00595 {
00596 angle_diff = 2 * M_PI - fabs(angle_diff);
00597 }
00598 }
00599
00600 double add_al_rot = abs(angle_diff/(execution_period));
00601
00602
00603 rot_vel = rot_vel_dir * lin_vel/rad*rot_correction_factor + rot_dir_opti*add_al_rot;
00604 }else
00605 {
00606 rot_vel = rot_vel_dir * lin_vel/rad*rot_correction_factor;
00607
00608 lower_al_angle = upper_al_angle;
00609 }
00610 }
00611
00612
00613
00614 void tedusar_path_follower::velocity_increase()
00615 {
00616
00617
00618 double pose_diff_x = fabs(odom.pose.pose.position.x - old_pos_x);
00619 double pose_diff_y = fabs(odom.pose.pose.position.y - old_pos_y);
00620
00621 if((pose_diff_x <= std::numeric_limits<double>::epsilon()) && (pose_diff_y <= std::numeric_limits<double>::epsilon()))
00622 {
00623 ++co_unchanged;
00624
00625 if (co_unchanged > update_skip)
00626 {
00627 co_unchanged = 0;
00628
00629 if(enable_velocity_encrease == true)
00630 {
00631
00632 lin_vel = lin_vel + max_lin_speed/10;
00633
00634 if(lin_vel >= max_lin_speed)
00635 {
00636 lin_vel = max_lin_speed;
00637
00638
00639 action_result.result = 1;
00640 execute_path_action_server_.setAborted(action_result, std::string("Robot cannot move, maximum speed reached!"));
00641 resetPathFollowing();
00642 ROS_WARN("Robot cannot move! Maximum speed reached!");
00643 }
00644 }else
00645 {
00646 action_result.result = 1;
00647 execute_path_action_server_.setAborted(action_result, std::string("Robot cannot move!"));
00648 resetPathFollowing();
00649 ROS_WARN("Robot cannot move!");
00650 }
00651 }
00652 }
00653 else
00654 {
00655
00656 old_pos_x = odom.pose.pose.position.x;
00657 old_pos_y = odom.pose.pose.position.y;
00658 co_unchanged = 0;
00659 lin_vel = lin_vel_ref;
00660 }
00661 }
00662
00663
00664
00665
00666 void tedusar_path_follower::calculate_cmd()
00667 {
00668 if(move_robot == true)
00669 {
00670
00671 check_robot_stability();
00672
00673 ROS_INFO_ONCE("Start calculating cmd velocity!");
00674
00675 al_an_diff = alignment_angle - yaw;
00676
00677 if(al_an_diff > M_PI)
00678 {
00679 al_an_diff = 2 * M_PI - al_an_diff;
00680 }
00681
00682 calculate_al_rot();
00683
00684
00685 if((fabs(al_an_diff) > (lower_al_angle + upper_al_angle))||(alignment_finished == false))
00686 {
00687
00688
00689 if (yaw > alignment_angle)
00690 {
00691 cmd.linear.x = 0.0;
00692 cmd.angular.z = rot_dir_opti*max_rot_speed/2;
00693 }
00694 else if (yaw < alignment_angle)
00695 {
00696 cmd.linear.x = 0.0;
00697 cmd.angular.z = rot_dir_opti*max_rot_speed/2;
00698 }
00699
00700 if(fabs(al_an_diff) < lower_al_angle/2)
00701 {
00702 alignment_finished = true;
00703 ROS_INFO("Alignment completed!");
00704 err_cont = 0;
00705 }else
00706 {
00707 alignment_finished = false;
00708
00709
00710 ++err_cont;
00711 if(err_cont > pub_cmd_hz*8)
00712 {
00713 action_result.result = 1;
00714 execute_path_action_server_.setAborted(action_result, std::string("Robot cannot move, maximum speed reached!"));
00715 resetPathFollowing();
00716 ROS_WARN("If your robot is oscilating, please increase lower_al_angle and upper_al_angle parameter (recommended: lower_al_angle=0.6, upper_al_angle=1.0)");
00717 ROS_WARN("Requesting new path!");
00718
00719 }
00720 }
00721 }
00722
00723 else if((fabs(al_an_diff) > lower_al_angle)&&((fabs(al_an_diff) < (lower_al_angle + upper_al_angle))))
00724 {
00725
00726
00727 calculate_al_rot();
00728
00729
00730 calc_angel_compensation();
00731
00732 cmd.linear.x = lin_vel;
00733 cmd.angular.z = rot_vel;
00734
00735
00736 glo_pos_diff_x = abs(odom.pose.pose.position.x - curr_path.poses[psize-1].pose.position.x);
00737 glo_pos_diff_y = abs(odom.pose.pose.position.y - curr_path.poses[psize-1].pose.position.y);
00738 if((glo_pos_diff_x < global_goal_tolerance)&&(glo_pos_diff_y < global_goal_tolerance))
00739 {
00740 ROS_INFO("GLOBAL GOAL REACHED");
00741 cmd.linear.x = 0;
00742 cmd.angular.z = 0;
00743
00744 action_result.result = 0;
00745 execute_path_action_server_.setSucceeded(action_result);
00746 move_robot = false;
00747 }
00748 }
00749
00750 else
00751 {
00752
00753
00754 calculate_al_rot();
00755
00756 rot_vel = rot_vel_dir * lin_vel/rad*rot_correction_factor;
00757
00758 cmd.linear.x = lin_vel;
00759 cmd.angular.z = rot_vel;
00760
00761
00762 glo_pos_diff_x = fabs(odom.pose.pose.position.x - curr_path.poses[psize-1].pose.position.x);
00763 glo_pos_diff_y = fabs(odom.pose.pose.position.y - curr_path.poses[psize-1].pose.position.y);
00764 if((glo_pos_diff_x < global_goal_tolerance)&&(glo_pos_diff_y < global_goal_tolerance))
00765 {
00766 ROS_INFO("GLOBAL GOAL REACHED");
00767 cmd.linear.x = 0;
00768 cmd.angular.z = 0;
00769
00770 action_result.result = 0;
00771 execute_path_action_server_.setSucceeded(action_result);
00772 move_robot = false;
00773
00774 }
00775 }
00776
00777
00778 cmd_vel_pub.publish(cmd);
00779
00780 }
00781 }
00782 }
00783
00784 int main (int argc, char** argv)
00785 {
00786
00787 ros::init (argc, argv, "tedusar_path_follower");
00788 ros::NodeHandle nh;
00789
00790
00791 tedusar_path_follower::tedusar_path_follower tedusar_path_follower_handler(nh);
00792
00793 tedusar_path_follower_handler.init();
00794
00795 ros::spin();
00796 return 0;
00797 }