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 <eband_local_planner/eband_trajectory_controller.h>
00039 #include <tf/transform_datatypes.h>
00040 
00041 
00042 namespace eband_local_planner{
00043 
00044 using std::min;
00045 using std::max;
00046 
00047 
00048 EBandTrajectoryCtrl::EBandTrajectoryCtrl() : costmap_ros_(NULL), initialized_(false), band_set_(false), visualization_(false) {}
00049 
00050 
00051 EBandTrajectoryCtrl::EBandTrajectoryCtrl(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00052   : costmap_ros_(NULL), initialized_(false), band_set_(false), visualization_(false)
00053 {
00054         
00055         initialize(name, costmap_ros);
00056 
00057   
00058   pid_.initPid(1, 0, 0, 10, -10);
00059 }
00060 
00061 
00062 EBandTrajectoryCtrl::~EBandTrajectoryCtrl() {}
00063 
00064 
00065 void EBandTrajectoryCtrl::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros)
00066 {
00067 
00068         
00069         if(!initialized_)
00070         {
00071                 
00072                 ros::NodeHandle node_private("~/" + name);
00073         
00074                 
00075                 node_private.param("max_vel_lin", max_vel_lin_, 0.6);
00076                 node_private.param("max_vel_th", max_vel_th_, 1.5);
00077 
00078                 node_private.param("min_vel_lin", min_vel_lin_, 0.1);
00079                 node_private.param("min_vel_th", min_vel_th_, 0.0);
00080 
00081                 node_private.param("min_in_place_vel_th", min_in_place_vel_th_, 0.0);
00082                 node_private.param("in_place_trans_vel", in_place_trans_vel_, 0.0);
00083 
00084                 node_private.param("tolerance_trans", tolerance_trans_, 0.02);
00085                 node_private.param("tolerance_rot", tolerance_rot_, 0.04);
00086                 node_private.param("tolerance_timeout", tolerance_timeout_, 0.5);
00087 
00088                 node_private.param("k_prop", k_p_, 4.0);
00089                 node_private.param("k_damp", k_nu_, 3.5);
00090                 node_private.param("Ctrl_Rate", ctrl_freq_, 10.0); 
00091 
00092                 node_private.param("max_acceleration", acc_max_, 0.5);
00093                 node_private.param("virtual_mass", virt_mass_, 0.75);
00094 
00095                 node_private.param("max_translational_acceleration", acc_max_trans_, 0.5);
00096                 node_private.param("max_rotational_acceleration", acc_max_rot_, 1.5);
00097 
00098                 node_private.param("rotation_correction_threshold", rotation_correction_threshold_, 0.5);
00099 
00100                 
00101                 costmap_ros_ = costmap_ros;
00102 
00103                 
00104                 last_vel_.linear.x = 0.0;
00105                 last_vel_.linear.y = 0.0;
00106                 last_vel_.linear.z = 0.0;
00107                 last_vel_.angular.x = 0.0;
00108                 last_vel_.angular.y = 0.0;
00109                 last_vel_.angular.z = 0.0;
00110 
00111                 
00112                 geometry_msgs::Pose2D tmp_pose2D;
00113                 tmp_pose2D.x = 0.0;
00114                 tmp_pose2D.y = 0.0;
00115                 tmp_pose2D.theta = 0.0;
00116                 Pose2DToPose(ref_frame_band_, tmp_pose2D);
00117 
00118                 
00119                 initialized_ = true;
00120         }
00121         else
00122         {
00123                 ROS_WARN("This planner has already been initialized, doing nothing.");
00124         }
00125 }
00126 
00127 
00128 void EBandTrajectoryCtrl::setVisualization(boost::shared_ptr<EBandVisualization> target_visual)
00129 {
00130         target_visual_ = target_visual;
00131 
00132         visualization_ = true;
00133 }
00134 
00135 bool EBandTrajectoryCtrl::setBand(const std::vector<Bubble>& elastic_band)
00136 {
00137         elastic_band_ = elastic_band;
00138         band_set_ = true;
00139         return true;
00140 }
00141 
00142 
00143 bool EBandTrajectoryCtrl::setOdometry(const nav_msgs::Odometry& odometry)
00144 {
00145         odom_vel_.linear.x = odometry.twist.twist.linear.x;
00146         odom_vel_.linear.y = odometry.twist.twist.linear.y;
00147         odom_vel_.linear.z = 0.0;
00148         odom_vel_.angular.x = 0.0;
00149         odom_vel_.angular.y = 0.0;
00150         odom_vel_.angular.z = odometry.twist.twist.angular.z;
00151 
00152         return true;
00153 }
00154 
00155 
00156 
00157 double angularDiff (const geometry_msgs::Twist& heading,
00158                     const geometry_msgs::Pose& pose)
00159 {
00160   const double pi = 3.14159265;
00161   const double t1 = atan2(heading.linear.y, heading.linear.x);
00162   const double t2 = tf::getYaw(pose.orientation);
00163   const double d = t1-t2;
00164 
00165   if (fabs(d)<pi)
00166     return d;
00167   else if (d<0)
00168     return d+2*pi;
00169   else
00170     return d-2*pi;
00171 }
00172 
00173 
00174 bool EBandTrajectoryCtrl::getTwist(geometry_msgs::Twist& twist_cmd)
00175 {
00176         
00177         geometry_msgs::Twist robot_cmd, bubble_diff, control_deviation;
00178         robot_cmd.linear.x = 0.0;
00179         robot_cmd.linear.y = 0.0;
00180         robot_cmd.linear.z = 0.0;
00181         robot_cmd.angular.x = 0.0;
00182         robot_cmd.angular.y = 0.0;
00183         robot_cmd.angular.z = 0.0;
00184 
00185         
00186         twist_cmd = robot_cmd;
00187         control_deviation = robot_cmd;
00188 
00189         
00190         if(!initialized_)
00191         {
00192                 ROS_ERROR("Requesting feedforward command from not initialized planner. Please call initialize() before using this planner");
00193                 return false;
00194         }
00195 
00196         
00197         if( (!band_set_) || (elastic_band_.size() < 2) )
00198         {
00199                 ROS_WARN("Requesting feedforward command from empty band.");
00200                 return false;
00201         }
00202 
00203         
00204 
00205         
00206         double scaled_radius = 0.7 * elastic_band_.at(0).expansion;
00207 
00208         
00209         double bubble_distance, ang_pseudo_dist;
00210         bubble_diff = getFrame1ToFrame2InRefFrame(elastic_band_.at(0).center.pose,
00211                                                                                                 elastic_band_.at(1).center.pose,
00212                                                                                                         ref_frame_band_);
00213         ang_pseudo_dist = bubble_diff.angular.z * costmap_ros_->getCircumscribedRadius();
00214         bubble_distance = sqrt( (bubble_diff.linear.x * bubble_diff.linear.x) + (bubble_diff.linear.y * bubble_diff.linear.y) +
00215                                                 (ang_pseudo_dist * ang_pseudo_dist) );
00216 
00217         if(visualization_)
00218         {
00219                 target_visual_->publishBubble("ctrl_target", 1, target_visual_->blue, elastic_band_.at(0));
00220                 target_visual_->publishBubble("ctrl_target", 2, target_visual_->blue, elastic_band_.at(1));
00221         }
00222 
00223         
00224         double abs_ctrl_dev;
00225         control_deviation = bubble_diff;
00226 
00227 
00228         ang_pseudo_dist = control_deviation.angular.z * costmap_ros_->getCircumscribedRadius();
00229         abs_ctrl_dev = sqrt( (control_deviation.linear.x * control_deviation.linear.x) +
00230                                                                 (control_deviation.linear.y * control_deviation.linear.y) +
00231                                                                         (ang_pseudo_dist * ang_pseudo_dist) );
00232 
00233         
00234         if(scaled_radius < bubble_distance)
00235         {
00236                 
00237                 double scale_difference = scaled_radius / bubble_distance;
00238                 bubble_diff.linear.x *= scale_difference;
00239                 bubble_diff.linear.y *= scale_difference;
00240                 bubble_diff.angular.z *= scale_difference;
00241                 
00242                 control_deviation = bubble_diff;
00243         }
00244         
00245         
00246 
00247         if(scaled_radius > bubble_distance)
00248         {
00249                 
00250                 if(elastic_band_.size() > 2)
00251                 {
00252                         
00253                         double next_bubble_distance;
00254                         geometry_msgs::Twist next_bubble_diff;
00255                         next_bubble_diff = getFrame1ToFrame2InRefFrame(elastic_band_.at(1).center.pose,
00256                                                                                                                         elastic_band_.at(2).center.pose,
00257                                                                                                                                 ref_frame_band_);
00258                         ang_pseudo_dist = next_bubble_diff.angular.z * costmap_ros_->getCircumscribedRadius();
00259                         next_bubble_distance = sqrt( (next_bubble_diff.linear.x * next_bubble_diff.linear.x) +
00260                                                                                         (next_bubble_diff.linear.y * next_bubble_diff.linear.y) +
00261                                                                                                 (ang_pseudo_dist * ang_pseudo_dist) );
00262 
00263                         if(scaled_radius > (bubble_distance + next_bubble_distance) )
00264                         {
00265                                 
00266                                 control_deviation.linear.x = bubble_diff.linear.x + next_bubble_diff.linear.x;
00267                                 control_deviation.linear.y = bubble_diff.linear.y + next_bubble_diff.linear.y;
00268                                 control_deviation.angular.z = bubble_diff.angular.z + next_bubble_diff.angular.z;
00269                                 
00270                                 if(visualization_)
00271                                         target_visual_->publishBubble("ctrl_target", 3, target_visual_->red, elastic_band_.at(2));
00272                         }
00273                         else
00274                         {
00275                                 if(visualization_)
00276                                         target_visual_->publishBubble("ctrl_target", 3, target_visual_->red, elastic_band_.at(2));
00277 
00278                                 
00279                                 
00280                                 double b_distance, cosine_at_bub;
00281                                 double vec_prod, norm_vec1, norm_vec2;
00282                                 double ang_pseudo_dist1, ang_pseudo_dist2;
00283 
00284                                 
00285                                 ang_pseudo_dist1 = bubble_diff.angular.z * costmap_ros_->getCircumscribedRadius();
00286                                 ang_pseudo_dist2 = next_bubble_diff.angular.z * costmap_ros_->getCircumscribedRadius();
00287                                 
00288                                 vec_prod = - ( (bubble_diff.linear.x * next_bubble_diff.linear.x) +
00289                                                                 (bubble_diff.linear.y * next_bubble_diff.linear.y) +
00290                                                                         (ang_pseudo_dist1 * ang_pseudo_dist2) );
00291 
00292                                 norm_vec1 = sqrt( (bubble_diff.linear.x * bubble_diff.linear.x) +
00293                                                                 (bubble_diff.linear.y * bubble_diff.linear.y) +
00294                                                                         (ang_pseudo_dist1 * ang_pseudo_dist1) );
00295 
00296                                 norm_vec2 = sqrt( (next_bubble_diff.linear.x * next_bubble_diff.linear.x) +
00297                                                                 (next_bubble_diff.linear.y * next_bubble_diff.linear.y) +
00298                                                                         (ang_pseudo_dist2 * ang_pseudo_dist2) );
00299 
00300                                 
00301                                 cosine_at_bub = vec_prod / norm_vec1 / norm_vec2;
00302                                 b_distance = bubble_distance * cosine_at_bub + sqrt( scaled_radius*scaled_radius -
00303                                                                 bubble_distance*bubble_distance * (1.0 - cosine_at_bub*cosine_at_bub) );
00304 
00305                                 
00306                                 double scale_next_difference = b_distance / next_bubble_distance;
00307                                 next_bubble_diff.linear.x *= scale_next_difference;
00308                                 next_bubble_diff.linear.y *= scale_next_difference;
00309                                 next_bubble_diff.angular.z *= scale_next_difference;
00310 
00311                                 
00312                                 control_deviation.linear.x = bubble_diff.linear.x + next_bubble_diff.linear.x;
00313                                 control_deviation.linear.y = bubble_diff.linear.y + next_bubble_diff.linear.y;
00314                                 control_deviation.angular.z = bubble_diff.angular.z + next_bubble_diff.angular.z;
00315                                 
00316                         }
00317                 }
00318         }
00319 
00320         
00321         ang_pseudo_dist = control_deviation.angular.z * costmap_ros_->getCircumscribedRadius();
00322         abs_ctrl_dev = sqrt( (control_deviation.linear.x * control_deviation.linear.x) +
00323                                                                 (control_deviation.linear.y * control_deviation.linear.y) +
00324                                                                         (ang_pseudo_dist * ang_pseudo_dist) );
00325 
00326 
00327         if(visualization_)
00328         {
00329                 
00330                 geometry_msgs::Pose2D tmp_bubble_2d, curr_bubble_2d;
00331                 geometry_msgs::Pose tmp_pose;
00332                 
00333                 Bubble new_bubble = elastic_band_.at(0);
00334                 PoseToPose2D(elastic_band_.at(0).center.pose, curr_bubble_2d);
00335                 tmp_bubble_2d.x = curr_bubble_2d.x + control_deviation.linear.x;
00336                 tmp_bubble_2d.y = curr_bubble_2d.y + control_deviation.linear.y;
00337                 tmp_bubble_2d.theta = curr_bubble_2d.theta + control_deviation.angular.z;
00338                 Pose2DToPose(tmp_pose, tmp_bubble_2d);
00339                 new_bubble.center.pose = tmp_pose;
00340                 new_bubble.expansion = 0.1; 
00341                 target_visual_->publishBubble("ctrl_target", 0, target_visual_->red, new_bubble);
00342         }
00343 
00344 
00345         const geometry_msgs::Point& goal = (--elastic_band_.end())->center.pose.position;
00346         const double dx = elastic_band_.at(0).center.pose.position.x - goal.x;
00347         const double dy = elastic_band_.at(0).center.pose.position.y - goal.y;
00348         const double dist_to_goal = sqrt(dx*dx + dy*dy);
00349         
00350         
00351         
00352         if (dist_to_goal > rotation_correction_threshold_)
00353         {
00354         
00355           const double angular_diff = angularDiff(control_deviation, elastic_band_.at(0).center.pose);
00356           const double vel = pid_.updatePid(-angular_diff, ros::Duration(1/ctrl_freq_));
00357           const double mult = fabs(vel) > max_vel_th_ ? max_vel_th_/fabs(vel) : 1.0;
00358           control_deviation.angular.z = vel*mult;
00359           const double abs_vel = fabs(control_deviation.angular.z);
00360 
00361           ROS_DEBUG_THROTTLE_NAMED (1.0, "angle_correction",
00362                                     "Angular diff is %.2f and desired angular "
00363                                     "vel is %.2f.  Initial translation velocity "
00364                                     "is %.2f, %.2f", angular_diff,
00365                                     control_deviation.angular.z,
00366                                     control_deviation.linear.x,
00367                                     control_deviation.linear.y);
00368           const double trans_mult = max(0.01, 1.0 - abs_vel/max_vel_th_); 
00369           control_deviation.linear.x *= trans_mult;
00370           control_deviation.linear.y *= trans_mult;
00371           ROS_DEBUG_THROTTLE_NAMED (1.0, "angle_correction",
00372                                     "Translation multiplier is %.2f and scaled "
00373                                     "translational velocity is %.2f, %.2f",
00374                                     trans_mult, control_deviation.linear.x,
00375                                     control_deviation.linear.y);
00376         }
00377         else
00378           ROS_DEBUG_THROTTLE_NAMED (1.0, "angle_correction",
00379                                     "Not applying angle correction because "
00380                                     "distance to goal is %.2f", dist_to_goal);
00381                                     
00382         
00383 
00384 
00385         
00386         geometry_msgs::Twist desired_velocity, currbub_maxvel_dir;
00387         double desvel_abs, desvel_abs_trans, currbub_maxvel_abs;
00388         double scale_des_vel;
00389         desired_velocity = robot_cmd;
00390         currbub_maxvel_dir = robot_cmd;
00391         
00392         
00393         desired_velocity.linear.x = k_p_/k_nu_ * control_deviation.linear.x;
00394         desired_velocity.linear.y = k_p_/k_nu_ * control_deviation.linear.y;
00395         desired_velocity.angular.z = k_p_/k_nu_ * control_deviation.angular.z;
00396 
00397         
00398 
00399         
00400         int curr_bub_num = 0;
00401         currbub_maxvel_abs = getBubbleTargetVel(curr_bub_num, elastic_band_, currbub_maxvel_dir);
00402 
00403         
00404         ang_pseudo_dist = desired_velocity.angular.z * costmap_ros_->getCircumscribedRadius();
00405         desvel_abs = sqrt( (desired_velocity.linear.x * desired_velocity.linear.x) +
00406                                                         (desired_velocity.linear.y * desired_velocity.linear.y) +
00407                                                                 (ang_pseudo_dist * ang_pseudo_dist) );
00408         if(desvel_abs > currbub_maxvel_abs)
00409         {
00410                 scale_des_vel = currbub_maxvel_abs / desvel_abs;
00411                 desired_velocity.linear.x *= scale_des_vel;
00412                 desired_velocity.linear.y *= scale_des_vel;
00413                 desired_velocity.angular.z *= scale_des_vel;
00414         }
00415 
00416         
00417         desvel_abs_trans = sqrt( (desired_velocity.linear.x * desired_velocity.linear.x) + (desired_velocity.linear.y * desired_velocity.linear.y) );
00418         
00419         if(desvel_abs_trans > max_vel_lin_)
00420         {
00421                 scale_des_vel = max_vel_lin_ / desvel_abs_trans;
00422                 desired_velocity.linear.x *= scale_des_vel;
00423                 desired_velocity.linear.y *= scale_des_vel;
00424                 
00425                 desired_velocity.angular.z *= scale_des_vel;
00426         }
00427 
00428         
00429         if(fabs(desired_velocity.angular.z) > max_vel_th_)
00430         {
00431                 scale_des_vel = max_vel_th_ / fabs(desired_velocity.angular.z);
00432                 desired_velocity.angular.z *= scale_des_vel;
00433                 
00434                 desired_velocity.linear.x *= scale_des_vel;
00435                 desired_velocity.linear.y *= scale_des_vel;
00436         }
00437 
00438         
00439         geometry_msgs::Twist acc_desired;
00440         acc_desired = robot_cmd;
00441         acc_desired.linear.x = (1.0/virt_mass_) * k_nu_ * (desired_velocity.linear.x - last_vel_.linear.x);
00442         acc_desired.linear.y = (1.0/virt_mass_) * k_nu_ * (desired_velocity.linear.y - last_vel_.linear.y);
00443         acc_desired.angular.z = (1.0/virt_mass_) * k_nu_ * (desired_velocity.angular.z - last_vel_.angular.z);
00444 
00445         
00446         double scale_acc;
00447         double abs_acc_trans = sqrt( (acc_desired.linear.x*acc_desired.linear.x) + (acc_desired.linear.y*acc_desired.linear.y) );
00448         if(abs_acc_trans > acc_max_trans_)
00449         {
00450                 scale_acc = acc_max_trans_ / abs_acc_trans;
00451                 acc_desired.linear.x *= scale_acc;
00452                 acc_desired.linear.y *= scale_acc;
00453                 
00454                 acc_desired.angular.z *= scale_acc;
00455         }
00456 
00457         if(fabs(acc_desired.angular.z) > acc_max_rot_)
00458         {
00459                 scale_acc = fabs(acc_desired.angular.z) / acc_max_rot_;
00460                 acc_desired.angular.z *= scale_acc;
00461                 
00462                 acc_desired.linear.x *= scale_acc;
00463                 acc_desired.linear.y *= scale_acc;
00464         }
00465 
00466         
00467         last_vel_.linear.x = last_vel_.linear.x + acc_desired.linear.x / ctrl_freq_;
00468         last_vel_.linear.y = last_vel_.linear.y + acc_desired.linear.y / ctrl_freq_;
00469         last_vel_.angular.z = last_vel_.angular.z + acc_desired.angular.z / ctrl_freq_;
00470 
00471 
00472         
00473 
00474         
00475         last_vel_ = limitTwist(last_vel_);
00476 
00477         
00478         robot_cmd = last_vel_;
00479 
00480         
00481         robot_cmd = transformTwistFromFrame1ToFrame2(robot_cmd, ref_frame_band_, elastic_band_.at(0).center.pose);
00482 
00483         
00484         int curr_target_bubble = 1;
00485         while(fabs(bubble_diff.linear.x) <= tolerance_trans_ &&
00486                         fabs(bubble_diff.linear.y) <= tolerance_trans_ &&
00487                         fabs(bubble_diff.angular.z) <= tolerance_rot_)
00488         {
00489                 if(curr_target_bubble < ((int) elastic_band_.size()) - 1)
00490                 {
00491                   curr_target_bubble++;
00492                   
00493                   
00494                   bubble_diff = getFrame1ToFrame2InRefFrame(elastic_band_.at(0).center.pose, elastic_band_.at(curr_target_bubble).center.pose,
00495                                                             ref_frame_band_);
00496                 }
00497                 else
00498                 {
00499                   ROS_DEBUG_THROTTLE_NAMED (1.0, "controller_state",
00500                                             "Goal reached with distance %.2f, %.2f, %.2f"
00501                                             "; sending zero velocity",
00502                                             bubble_diff.linear.x, bubble_diff.linear.y,
00503                                             bubble_diff.angular.z);
00504                   
00505                   robot_cmd.linear.x = 0.0;
00506                   robot_cmd.linear.y = 0.0;
00507                   robot_cmd.angular.z = 0.0;
00508                   
00509                   last_vel_.linear.x = 0.0;
00510                   last_vel_.linear.y = 0.0;
00511                   last_vel_.angular.z = 0.0;
00512                   break;
00513                 }
00514         }
00515 
00516         twist_cmd = robot_cmd;
00517         
00518         return true;
00519 }
00520 
00521 
00522 double EBandTrajectoryCtrl::getBubbleTargetVel(const int& target_bub_num, const std::vector<Bubble>& band, geometry_msgs::Twist& VelDir)
00523 {
00524         
00525         VelDir.linear.x = 0.0;
00526         VelDir.linear.y = 0.0;
00527         VelDir.linear.z = 0.0;
00528         VelDir.angular.x = 0.0;
00529         VelDir.angular.y = 0.0;
00530         VelDir.angular.z = 0.0;
00531 
00532         
00533         if(target_bub_num >= ((int) band.size() - 1))
00534                 return 0.0;
00535 
00536 
00537         
00538         double v_max_curr_bub, v_max_next_bub;
00539         double bubble_distance, angle_to_pseudo_vel, delta_vel_max;
00540         geometry_msgs::Twist bubble_diff;
00541 
00542         
00543         v_max_curr_bub = sqrt(2 * elastic_band_.at(target_bub_num).expansion * acc_max_);
00544 
00545         
00546         ROS_ASSERT( (target_bub_num >= 0) && ((target_bub_num +1) < (int) band.size()) );
00547         bubble_diff = getFrame1ToFrame2InRefFrame(band.at(target_bub_num).center.pose, band.at(target_bub_num + 1).center.pose,
00548                                                                                                 ref_frame_band_);
00549         angle_to_pseudo_vel = bubble_diff.angular.z * costmap_ros_->getCircumscribedRadius();
00550 
00551         bubble_distance = sqrt( (bubble_diff.linear.x * bubble_diff.linear.x) + (bubble_diff.linear.y * bubble_diff.linear.y) +
00552                                                         (angle_to_pseudo_vel * angle_to_pseudo_vel) );
00553 
00554         
00555         VelDir.linear.x =bubble_diff.linear.x/bubble_distance;
00556         VelDir.linear.y =bubble_diff.linear.y/bubble_distance;
00557         VelDir.angular.z =bubble_diff.angular.z/bubble_distance;
00558 
00559         
00560         if(bubble_distance > band.at(target_bub_num).expansion )
00561                 return v_max_curr_bub;
00562 
00563 
00564         
00565         int next_bub_num = target_bub_num + 1;
00566         geometry_msgs::Twist dummy_twist;
00567         v_max_next_bub = getBubbleTargetVel(next_bub_num, band, dummy_twist); 
00568 
00569         
00570         if(v_max_next_bub >= v_max_curr_bub)
00571                 return v_max_curr_bub;
00572 
00573 
00574         
00575         delta_vel_max = sqrt(2 * bubble_distance * acc_max_);
00576         v_max_curr_bub = v_max_next_bub + delta_vel_max;
00577 
00578         return v_max_curr_bub;
00579 }
00580 
00581 
00582 geometry_msgs::Twist EBandTrajectoryCtrl::getFrame1ToFrame2InRefFrame(const geometry_msgs::Pose& frame1, const geometry_msgs::Pose& frame2, const geometry_msgs::Pose& ref_frame)
00583 {
00584 
00585         geometry_msgs::Pose2D frame1_pose2D, frame2_pose2D, ref_frame_pose2D;
00586         geometry_msgs::Pose2D frame1_pose2D_rf, frame2_pose2D_rf;
00587         geometry_msgs::Twist frame_diff;
00588 
00589         
00590         PoseToPose2D(frame1, frame1_pose2D);
00591         PoseToPose2D(frame2, frame2_pose2D);
00592         PoseToPose2D(ref_frame, ref_frame_pose2D);
00593 
00594         
00595         frame1_pose2D_rf.x = (frame1_pose2D.x - ref_frame_pose2D.x) * cos(ref_frame_pose2D.theta) +
00596                                                         (frame1_pose2D.y - ref_frame_pose2D.y) * sin(ref_frame_pose2D.theta);
00597         frame1_pose2D_rf.y = -(frame1_pose2D.x - ref_frame_pose2D.x) * sin(ref_frame_pose2D.theta) +
00598                                                         (frame1_pose2D.y - ref_frame_pose2D.y) * cos(ref_frame_pose2D.theta);
00599         frame1_pose2D_rf.theta = frame1_pose2D.theta - ref_frame_pose2D.theta;
00600         frame1_pose2D_rf.theta = angles::normalize_angle(frame1_pose2D_rf.theta);
00601         
00602         frame2_pose2D_rf.x = (frame2_pose2D.x - ref_frame_pose2D.x) * cos(ref_frame_pose2D.theta) +
00603                                                         (frame2_pose2D.y - ref_frame_pose2D.y) * sin(ref_frame_pose2D.theta);
00604         frame2_pose2D_rf.y = -(frame2_pose2D.x - ref_frame_pose2D.x) * sin(ref_frame_pose2D.theta) +
00605                                                         (frame2_pose2D.y - ref_frame_pose2D.y) * cos(ref_frame_pose2D.theta);
00606         frame2_pose2D_rf.theta = frame2_pose2D.theta - ref_frame_pose2D.theta;
00607         frame2_pose2D_rf.theta = angles::normalize_angle(frame2_pose2D_rf.theta);
00608 
00609         
00610         frame_diff.linear.x = frame2_pose2D_rf.x - frame1_pose2D_rf.x;
00611         frame_diff.linear.y = frame2_pose2D_rf.y - frame1_pose2D_rf.y;
00612         frame_diff.linear.z = 0.0;
00613         frame_diff.angular.x = 0.0;
00614         frame_diff.angular.y = 0.0;
00615         frame_diff.angular.z = frame2_pose2D_rf.theta - frame1_pose2D_rf.theta;
00616         
00617         frame_diff.angular.z = angles::normalize_angle(frame_diff.angular.z);
00618 
00619         return frame_diff;
00620 }
00621 
00622 
00623 geometry_msgs::Twist EBandTrajectoryCtrl::transformTwistFromFrame1ToFrame2(const geometry_msgs::Twist& curr_twist,
00624                                                                                                                         const geometry_msgs::Pose& frame1, const geometry_msgs::Pose& frame2)
00625 {
00626         geometry_msgs::Pose2D frame1_pose2D, frame2_pose2D;
00627         geometry_msgs::Twist tmp_transformed;
00628         double delta_ang;
00629 
00630         tmp_transformed = curr_twist;
00631 
00632         
00633         PoseToPose2D(frame1, frame1_pose2D);
00634         PoseToPose2D(frame2, frame2_pose2D);
00635 
00636         
00637         delta_ang = frame2_pose2D.theta - frame1_pose2D.theta;
00638         delta_ang = angles::normalize_angle(delta_ang);
00639 
00640         
00641         tmp_transformed.linear.x = curr_twist.linear.x * cos(delta_ang) + curr_twist.linear.y * sin(delta_ang);
00642         tmp_transformed.linear.y = -curr_twist.linear.x * sin(delta_ang) + curr_twist.linear.y * cos(delta_ang);
00643 
00644         return tmp_transformed;
00645 }
00646 
00647 
00648 geometry_msgs::Twist EBandTrajectoryCtrl::limitTwist(const geometry_msgs::Twist& twist)
00649 {
00650         geometry_msgs::Twist res = twist;
00651 
00652         
00653         double lin_overshoot = sqrt(res.linear.x * res.linear.x + res.linear.y * res.linear.y) / max_vel_lin_;
00654         double lin_undershoot = min_vel_lin_ / sqrt(res.linear.x * res.linear.x + res.linear.y * res.linear.y);
00655         if (lin_overshoot > 1.0) 
00656         {
00657                 res.linear.x /= lin_overshoot;
00658                 res.linear.y /= lin_overshoot;
00659                 
00660                 res.angular.z /= lin_overshoot;
00661         }
00662 
00663         
00664         if(lin_undershoot > 1.0)
00665         {
00666                 res.linear.x *= lin_undershoot;
00667                 res.linear.y *= lin_undershoot;
00668                 
00669         }
00670 
00671         if (fabs(res.angular.z) > max_vel_th_)
00672         {
00673                 double scale = max_vel_th_/fabs(res.angular.z);
00674                 
00675                 res.angular.z *= scale;
00676                 
00677                 res.linear.x *= scale;
00678                 res.linear.y *= scale;
00679         }
00680 
00681         if (fabs(res.angular.z) < min_vel_th_) res.angular.z = min_vel_th_ * sign(res.angular.z);
00682         
00683 
00684         
00685         if(sqrt(twist.linear.x * twist.linear.x + twist.linear.y * twist.linear.y) < in_place_trans_vel_)
00686         {
00687                 if (fabs(res.angular.z) < min_in_place_vel_th_)
00688                         res.angular.z = min_in_place_vel_th_ * sign(res.angular.z);
00689 
00690                 res.linear.x = 0.0;
00691                 res.linear.y = 0.0;
00692         }
00693 
00694         ROS_DEBUG("Angular command %f", res.angular.z);
00695         return res;
00696 }
00697 
00698 
00699 }