min_time_node.cpp
Go to the documentation of this file.
00001 #include "rcommander_pr2_gui/min_time_node.h"
00002 #include <spline_smoother/spline_smoother_utils.h>
00003 
00004 bool quadSolve(const double &a, 
00005                const double &b, 
00006                const double &c, 
00007                double &solution)
00008 {
00009   double t1(0.0), t2(0.0);
00010   //  double eps = 2.2e-16;
00011   if (fabs(a) > 0.0)
00012   {
00013     double discriminant = b*b-4*a*c;
00014     if (discriminant >= 0)
00015     {
00016       t1 = (-b + sqrt(discriminant))/(2*a);
00017       t2 = (-b - sqrt(discriminant))/(2*a);
00018       ROS_DEBUG("t1:%f t2:%f",t1,t2);
00019       solution = std::max(t1,t2);
00020       ROS_DEBUG("Solution: %f",solution);
00021       return true;
00022     }
00023     else
00024       return false;
00025   }
00026   else
00027   {
00028     if(fabs(b) == 0.0)
00029       return false;
00030     t1 = -c/b;
00031     t2 = t1;
00032     solution = t1;
00033     ROS_DEBUG("Solution: %f",solution);
00034     return true;
00035   }
00036 }
00037 
00038 bool quadSolve(const double &a, 
00039                const double &b, 
00040                const double &c, 
00041                std::vector<double> &solution)
00042 {
00043   double t1(0.0), t2(0.0);
00044   double eps = 2.2e-16;
00045   if (fabs(a) > eps)
00046   {
00047     double discriminant = b*b-4*a*c;
00048     if (discriminant >= 0)
00049     {
00050       t1 = (-b + sqrt(discriminant))/(2*a);
00051       t2 = (-b - sqrt(discriminant))/(2*a);
00052       ROS_DEBUG("t1:%f t2:%f",t1,t2);
00053       solution.push_back(t1);
00054       solution.push_back(t2);
00055       return true;
00056     }
00057     else
00058     {
00059       ROS_DEBUG("Discriminant: %f",discriminant);
00060       return false;
00061     }
00062   }
00063   else
00064   {
00065     if(fabs(b) == 0.0)
00066       return false;
00067     t1 = -c/b;
00068     t2 = t1;
00069     solution.push_back(t1);
00070     solution.push_back(t2);
00071     return true;
00072   }
00073 }
00074 
00075 bool validSolution(const double &q0, 
00076                    const double &q1,
00077                    const double &v0,
00078                    const double &v1,
00079                    const double &dT,
00080                    const double &vmax,
00081                    const double &amax)
00082 {
00083   if (dT == 0.0)
00084     return false;
00085   //  double a0 = q0;
00086   double a1 = v0;
00087   double a2 = (3*(q1-q0)-(2*v0+v1)*dT)/(dT*dT);
00088   double a3 = (2*(q0-q1)+(v0+v1)*dT)/(dT*dT*dT);
00089 
00090   double max_accn = fabs(2*a2);
00091   if(fabs(2*a2+6*a3*dT) > max_accn)
00092     max_accn = fabs(2*a2+6*a3*dT);
00093 
00094   bool max_vel_exists = false;
00095   double max_vel = 0.0;
00096 
00097   if(fabs(a3) > 0.0)
00098   {
00099     double max_vel_time = (-2*a2)/(6*a3); 
00100     if (max_vel_time >= 0 && max_vel_time < dT)
00101     {
00102       max_vel_exists = true;
00103       max_vel = a1-(a2*a2)/(a3*3.0);
00104     }
00105   }
00106 
00107   if(amax > 0 && max_accn-amax > 1e-2)
00108   {
00109     ROS_DEBUG("amax allowed: %f, max_accn: %f",amax,max_accn);
00110     return false;
00111   }
00112   if(max_vel_exists)
00113     if(fabs(max_vel)-vmax > 1e-2)
00114     {
00115       ROS_DEBUG("vmax allowed: %f, max_vel: %f",vmax,max_vel);
00116       return false;
00117     }
00118   return true;
00119 }
00120 
00121 
00122 double minSegmentTime(const double &q0, 
00123                       const double &q1, 
00124                       const double &v0, 
00125                       const double &v1, 
00126                       const arm_navigation_msgs::JointLimits &limit)
00127 {
00128    //    double dq = jointDiff(q0,q1,limit);
00129    double dq = q1-q0;
00130    double vmax = limit.max_velocity;
00131    if( q0 == q1 && fabs(v0-v1) == 0.0)
00132    {
00133      return 0.0;
00134    }
00135    dq = q1-q0;
00136    double v = vmax;
00137    double solution;
00138    std::vector<double> solution_vec;
00139 
00140    double a1 = 3*(v0+v1)*v - 3* (v0+v1)*v0 + (2*v0+v1)*(2*v0+v1);
00141    double b1 = -6*dq*v + 6 * v0 *dq - 6*dq*(2*v0+v1);
00142    double c1 = 9*dq*dq;
00143 
00144    double a2 = 3*(v0+v1)*v + 3* (v0+v1)*v0 - (2*v0+v1)*(2*v0+v1);
00145    double b2 = -6*dq*v - 6 * v0 *dq + 6*dq*(2*v0+v1);
00146    double c2 = -9*dq*dq;
00147 
00148    std::vector<double> t1,t2,t3,t4,t5,t6;
00149 
00150    if(quadSolve(a1,b1,c1,t1))
00151      for(unsigned int i=0; i < t1.size(); i++)
00152        solution_vec.push_back(t1[i]);
00153    
00154    if(quadSolve(a2,b2,c2,t2))
00155      for(unsigned int i=0; i < t2.size(); i++)
00156        solution_vec.push_back(t2[i]);
00157    double amax = -1.0;
00158    
00159    if(limit.has_acceleration_limits)
00160    {
00161      amax = limit.max_acceleration;
00162      double a3 = amax/2.0;
00163      double b3 = 2*v0+v1;
00164      double c3 = -3*dq;
00165      if(quadSolve(a3,b3,c3,t3))
00166        for(unsigned int i=0; i < t3.size(); i++)
00167          solution_vec.push_back(t3[i]);
00168 
00169      double a4 = amax/2.0;
00170      double b4 = -(2*v0+v1);
00171      double c4 = 3*dq;
00172      if(quadSolve(a4,b4,c4,t4))
00173        for(unsigned int i=0; i < t4.size(); i++)
00174          solution_vec.push_back(t4[i]);
00175 
00176 
00177      double a5 = amax;
00178      double b5 = (-2*v0-4*v1);
00179      double c5 = 6*dq;
00180      if(quadSolve(a5,b5,c5,t5))
00181        for(unsigned int i=0; i < t5.size(); i++)
00182          solution_vec.push_back(t5[i]);
00183 
00184      double a6 = amax;
00185      double b6 = (2*v0+4*v1);
00186      double c6 = -6*dq;
00187      if(quadSolve(a6,b6,c6,t6))
00188        for(unsigned int i=0; i < t6.size(); i++)
00189          solution_vec.push_back(t6[i]);
00190    }
00191    std::vector<double> positive_durations, valid_durations;
00192    for(unsigned int i=0; i < solution_vec.size(); i++)
00193    {
00194      if(solution_vec[i] > 0)
00195        positive_durations.push_back(solution_vec[i]);        
00196    }
00197 
00198    for(unsigned int i=0; i < positive_durations.size(); i++)
00199    {
00200      ROS_DEBUG("Positive duration: %f",positive_durations[i]);
00201      if(validSolution(q0,q1,v0,v1,positive_durations[i],vmax,amax))
00202        valid_durations.push_back(positive_durations[i]);        
00203    }
00204 
00205    ROS_DEBUG("valid size: %d",(int)valid_durations.size());       
00206    std::sort(valid_durations.begin(),valid_durations.end());
00207    if(!valid_durations.empty())
00208      solution = valid_durations.front();
00209    else
00210      solution = 0.025;
00211 
00212    ROS_DEBUG(" ");
00213    ROS_DEBUG(" ");
00214    ROS_DEBUG(" ");
00215    return solution;
00216 }
00217 
00218 double calculateMinimumTime(const trajectory_msgs::JointTrajectoryPoint &start, 
00219                             const trajectory_msgs::JointTrajectoryPoint &end, 
00220                             const std::vector<arm_navigation_msgs::JointLimits> &limits)
00221 {
00222     double minJointTime(FLT_MAX);
00223     double segmentTime(0);
00224     int num_joints = (int) start.positions.size();
00225 
00226     for(int i = 0; i < num_joints; i++)
00227     {
00228         minJointTime = minSegmentTime(start.positions[i],end.positions[i],start.velocities[i],end.velocities[i],limits[i]);
00229         if(segmentTime < minJointTime)
00230             segmentTime = minJointTime;
00231     }
00232     return segmentTime;
00233 }
00234 
00235 
00236 MinTimeNode::MinTimeNode(ros::NodeHandle &n): n_(n)
00237 {
00238     min_time_service = n_.advertiseService("min_time_to_move", &MinTimeNode::min_time_srv_cb, this);
00239     ros::service::waitForService("pr2_left_arm_kinematics/get_ik_solver_info");
00240     ros::service::waitForService("pr2_right_arm_kinematics/get_ik_solver_info");
00241     ros::ServiceClient left_ik_client = n.serviceClient<kinematics_msgs::GetKinematicSolverInfo>(
00242             "pr2_left_arm_kinematics/get_ik_solver_info");
00243     ros::ServiceClient right_ik_client = n.serviceClient<kinematics_msgs::GetKinematicSolverInfo>(
00244             "pr2_right_arm_kinematics/get_ik_solver_info");
00245     has_left = false;
00246     has_right = false;
00247 
00248     if (left_ik_client.call(left_info))
00249     {
00250         ROS_INFO("Has left arm.");
00251         has_left = true;
00252     } 
00253 
00254     if (right_ik_client.call(right_info))
00255     {
00256         ROS_INFO("Has right arm.");
00257         has_right = true;
00258     } 
00259 }
00260 
00261 bool MinTimeNode::min_time_srv_cb(rcommander_pr2_gui::MinTime::Request &req, 
00262                                   rcommander_pr2_gui::MinTime::Response &res)
00263 {
00264     //spline_smoother::CubicTrajectory ct = spline_smoother::CubicTrajectory();
00265     double mtime = 0.0;
00266     if (req.left == true and has_left)
00267     {
00268         mtime = calculateMinimumTime(req.start_point, req.end_point, left_info.response.kinematic_solver_info.limits);
00269     } else
00270     {
00271         if (has_right)
00272             mtime = calculateMinimumTime(req.start_point, req.end_point, right_info.response.kinematic_solver_info.limits);
00273     }
00274     res.time = mtime;
00275     //req.start_point
00276     return true;
00277 }
00278 
00279 
00280 int main(int argc, char **argv)
00281 {
00282     ros::init(argc, argv, "min_time_client");
00283     ros::NodeHandle n;
00284 
00285     //Setup service
00286     MinTimeNode min_time_node_(n);
00287     ROS_INFO("min_time_to_move ready.");
00288     ros::spin();
00289     return 0;
00290 }
00291 
00292 


rcommander_pr2_gui
Author(s): Hai Nguyen
autogenerated on Thu Dec 12 2013 12:09:58