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
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
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
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
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
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
00286 MinTimeNode min_time_node_(n);
00287 ROS_INFO("min_time_to_move ready.");
00288 ros::spin();
00289 return 0;
00290 }
00291
00292