$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2009, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00037 #include <spline_smoother/cubic_parameterized_trajectory.h> 00038 00039 namespace spline_smoother 00040 { 00041 CubicParameterizedTrajectory::CubicParameterizedTrajectory() 00042 { 00043 apply_limits_ = true; 00044 } 00045 00046 double CubicParameterizedTrajectory::getDistance(const trajectory_msgs::JointTrajectoryPoint &start, 00047 const trajectory_msgs::JointTrajectoryPoint &end, 00048 const std::vector<arm_navigation_msgs::JointLimits> &limits) 00049 { 00050 double position = 0.0; 00051 for(unsigned int i=0; i < start.positions.size(); i++) 00052 position += jointDiff(start.positions[i],end.positions[i],limits[i]) * jointDiff(start.positions[i],end.positions[i],limits[i]); 00053 position = sqrt(position); 00054 return position; 00055 } 00056 00057 double CubicParameterizedTrajectory::getVelocityLimit(const trajectory_msgs::JointTrajectoryPoint &start, 00058 const trajectory_msgs::JointTrajectoryPoint &end, 00059 const std::vector<arm_navigation_msgs::JointLimits> &limits) 00060 { 00061 double velocity = DBL_MAX; 00062 for(unsigned int i=0; i < start.positions.size(); i++) 00063 { 00064 double tmp_vel = limits[i].max_velocity/fabs(end.positions[i]-start.positions[i]); 00065 if(velocity > tmp_vel) 00066 velocity = tmp_vel; 00067 } 00068 return velocity; 00069 } 00070 00071 double CubicParameterizedTrajectory::getAccelerationLimit(const trajectory_msgs::JointTrajectoryPoint &start, 00072 const trajectory_msgs::JointTrajectoryPoint &end, 00073 const std::vector<arm_navigation_msgs::JointLimits> &limits) 00074 { 00075 double acceleration = DBL_MAX; 00076 for(unsigned int i=0; i < start.positions.size(); i++) 00077 { 00078 double tmp_vel = limits[i].max_acceleration/fabs(end.positions[i]-start.positions[i]); 00079 if(acceleration > tmp_vel) 00080 acceleration = tmp_vel; 00081 } 00082 return acceleration; 00083 } 00084 00085 bool CubicParameterizedTrajectory::hasAccelerationLimits(const std::vector<arm_navigation_msgs::JointLimits> &limits) 00086 { 00087 for(unsigned int i=0; i < limits.size(); i++) 00088 if(!limits[i].has_acceleration_limits) 00089 return false; 00090 return true; 00091 } 00092 00093 void CubicParameterizedTrajectory::getLimit(const trajectory_msgs::JointTrajectoryPoint &start, 00094 const trajectory_msgs::JointTrajectoryPoint &end, 00095 const std::vector<arm_navigation_msgs::JointLimits> &limits, 00096 arm_navigation_msgs::JointLimits &limit_out) 00097 { 00098 limit_out.has_position_limits = true; 00099 limit_out.min_position = 0; 00100 limit_out.max_position = 1; 00101 limit_out.has_velocity_limits = true; 00102 limit_out.max_velocity = getVelocityLimit(start,end,limits); 00103 00104 limit_out.has_acceleration_limits = false; 00105 if(hasAccelerationLimits(limits)) 00106 { 00107 limit_out.max_acceleration = getAccelerationLimit(start,end,limits); 00108 limit_out.has_acceleration_limits = true; 00109 } 00110 } 00111 00112 00113 double CubicParameterizedTrajectory::jointDiff(const double &start, 00114 const double &end, 00115 const arm_navigation_msgs::JointLimits &limit) 00116 { 00117 if(limit.has_position_limits) 00118 return end-start; 00119 else 00120 return angles::shortest_angular_distance(start,end); 00121 } 00122 00123 void CubicParameterizedTrajectory::solveCubicSpline(const double &q0, 00124 const double &q1, 00125 const double &v0, 00126 const double &v1, 00127 const double &dt, 00128 std::vector<double> &coefficients) 00129 { 00130 coefficients.resize(4); 00131 double diff = q1-q0; 00132 coefficients[0] = q0; 00133 coefficients[1] = v0; 00134 coefficients[2] = (3*diff-(2*v0+v1)*dt)/(dt*dt);; 00135 coefficients[3] = (-2*diff+(v0+v1)*dt)/pow(dt,3); 00136 } 00137 00138 bool CubicParameterizedTrajectory::parameterize(const trajectory_msgs::JointTrajectory& trajectory_in, 00139 const std::vector<arm_navigation_msgs::JointLimits> &limits, 00140 spline_smoother::SplineTrajectory& spline) 00141 { 00142 int num_traj = trajectory_in.points.size(); 00143 int num_joints = trajectory_in.joint_names.size(); 00144 spline.names = trajectory_in.joint_names; 00145 spline.segments.resize(num_traj-1); 00146 00147 for(int i=0; i<num_joints; i++) 00148 { 00149 if(!limits[i].has_velocity_limits) 00150 { 00151 ROS_ERROR("Trying to apply velocity limits without supplying them. Set velocity_limits in the message and set has_velocity_limits flag to true."); 00152 return false; 00153 } 00154 } 00155 for (int i=1; i< num_traj; ++i) 00156 { 00157 spline.segments[i-1].joints.resize(num_joints); 00158 00159 for(int j =0; j < num_joints; j++) 00160 spline.segments[i-1].joints[j].coefficients.resize(4); 00161 double dT = (trajectory_in.points[i].time_from_start - trajectory_in.points[i-1].time_from_start).toSec(); 00162 00163 // Start and end parameterized positions 00164 trajectory_msgs::JointTrajectoryPoint start,end; 00165 start.positions.resize(1); 00166 start.velocities.resize(1); 00167 start.positions[0] = 0.0; 00168 00169 end.positions.resize(1); 00170 end.velocities.resize(1); 00171 end.positions[0] = 1.0; 00172 00173 // Velocity limits on parameter 00174 arm_navigation_msgs::JointLimits parameter_limits; 00175 parameter_limits.joint_name = "cubic_parameterization"; 00176 getLimit(trajectory_in.points[i-1],trajectory_in.points[i],limits,parameter_limits); 00177 00178 if(apply_limits_) 00179 { 00180 spline_smoother::CubicTrajectory solver; 00181 spline_smoother::SplineTrajectory spline; 00182 arm_navigation_msgs::JointTrajectoryWithLimits wpt; 00183 double dTMin; 00184 00185 wpt.trajectory.points.push_back(start); 00186 wpt.trajectory.points.push_back(end); 00187 wpt.limits.push_back(parameter_limits); 00188 00189 solver.parameterize(wpt.trajectory,wpt.limits,spline); 00190 spline_smoother::getTotalTime(spline,dTMin); 00191 if(dTMin > dT) // if minimum time required to satisfy limits is greater than time available, stretch this segment 00192 dT = dTMin; 00193 } 00194 00195 std::vector<double> coefficients; 00196 solveCubicSpline(start.positions[0], 00197 end.positions[0], 00198 0.0, 00199 0.0, 00200 dT, 00201 coefficients); 00202 spline.segments[i-1].duration = ros::Duration(dT); 00203 00204 for(int j=0; j<num_joints; j++) 00205 { 00206 double diff = trajectory_in.points[i].positions[j] - trajectory_in.points[i-1].positions[j]; 00207 00208 spline.segments[i-1].joints[j].coefficients[0] = trajectory_in.points[i-1].positions[j] + diff * coefficients[0]; 00209 spline.segments[i-1].joints[j].coefficients[1] = diff*coefficients[1]; 00210 spline.segments[i-1].joints[j].coefficients[2] = diff*coefficients[2]; 00211 spline.segments[i-1].joints[j].coefficients[3] = diff*coefficients[3]; 00212 } 00213 } 00214 return true; 00215 } 00216 }