$search
00001 #include <cob_trajectory_controller/RefValJS_PTP_Trajectory.h> 00002 #include <stdexcept> 00003 #include <algorithm> 00004 #include <vector> 00005 00006 //#define PTP_TRAJ_DEBUG 00007 00008 const double RefValJS_PTP_Trajectory::weigths[] = { 1.5, 1.5, 1.0, 1.0, 0.8, 0.8, 0.7 }; 00009 00010 00011 inline double sqr(double x) 00012 { 00013 return x*x; 00014 } 00015 00016 RefValJS_PTP_Trajectory::RefValJS_PTP_Trajectory(const trajectory_msgs::JointTrajectory& trajectory, double v_rad_s, double a_rad_s2, bool smooth) 00017 { 00018 m_trajectory = trajectory; 00019 m_length = 0; 00020 m_stepSize = 0.4; 00021 //m_stepSize = 0.0175; // 0.0175 rad = 1° 00022 m_length_parts.clear(); 00023 m_s_parts.clear(); 00024 00025 if ( m_trajectory.points.size() < 1 ) 00026 { 00027 throw std::runtime_error("Tried to create reference values for empty trajectory!"); 00028 } 00029 00030 std::vector<std::vector<double> > zwischenPunkte; 00031 00032 if (smooth == false) 00033 { 00034 // Maß dafür, wo groß die Rundung wird 00035 // double between_stepsize = 2.5; // 0.2 rad = 11.5° 00036 //uhr-messmerf: 00037 double between_stepsize = 0.1; //verkleinert wegen Exception (s.u.) 00038 for (unsigned int i=0; i < m_trajectory.points.size()-1; i++) 00039 { 00040 std::vector<double> direction; 00041 direction.resize( m_trajectory.points[i+1].positions.size()); 00042 double len = 0; 00043 for(unsigned int j = 0; j < m_trajectory.points[i+1].positions.size(); j++) 00044 { 00045 direction.at(j) = m_trajectory.points[i+1].positions.at(j)-m_trajectory.points[i].positions.at(j); 00046 len += direction.at(j) * direction.at(j); 00047 } 00048 double dist = sqrt(len); 00049 int num_segs = ceil(dist/between_stepsize); 00050 zwischenPunkte.resize(num_segs); 00051 for (int j=0; j < num_segs; j++) 00052 { 00053 std::vector<double> betw_joint; 00054 betw_joint.resize(direction.size()); 00055 for(unsigned int d=0; d < direction.size(); d++) 00056 { 00057 betw_joint.at(d) = m_trajectory.points[i].positions.at(d) + direction.at(d) * ( (double)j / (double)num_segs ); 00058 } 00059 zwischenPunkte.at(j) = betw_joint; 00060 } 00061 } 00062 zwischenPunkte.push_back( m_trajectory.points.back().positions ); 00063 } else 00064 { 00065 zwischenPunkte.resize(trajectory.points.size()); 00066 for(unsigned int i = 0; i < trajectory.points.size(); i++) 00067 { 00068 zwischenPunkte.at(i) = trajectory.points.at(i).positions; 00069 } 00070 } 00071 ROS_INFO("Calculated %d zwischenPunkte", zwischenPunkte.size()); 00072 00073 m_TrajectorySpline.setCtrlPoints(zwischenPunkte); 00074 00075 // Note: unlike the name of the function suggests, the distance between any two neigbouring points 00076 // is not always the same! 00077 if ( m_TrajectorySpline.ipoWithConstSampleDist(m_stepSize, m_SplinePoints)==false ) 00078 { 00079 //uhr-messmerf: diese exception wird geworfen, wenn nicht genügend Stützpunkte vorhanden sind (kleiner m_iGrad=3) 00080 //uhr-messmerf: dies tritt auf, wenn die Punkte der Trajectory pfad zu nah beieinander liegen (dist < between_stepsize=2.5) 00081 throw std::runtime_error("Error in BSplineND::ipoWithConstSampleDist!"); 00082 } 00083 m_SplinePoints = zwischenPunkte; 00084 ROS_INFO("Calculated %d splinepoints", m_SplinePoints.size()); 00085 00086 m_length_cumulated.clear(); 00087 m_length_cumulated.push_back(0.0); 00088 00089 for (unsigned int i=0; i < m_SplinePoints.size()-1; i++) 00090 { 00091 std::vector<double> dist; 00092 dist.resize(m_SplinePoints[i].size()); 00093 for(unsigned int j=0; j < m_SplinePoints[i].size(); j++) 00094 { 00095 dist.at(j) = m_SplinePoints[i+1].at(j) - m_SplinePoints[i].at(j); 00096 } 00097 //double max = fabs(direction.getMax()); 00098 //double min = fabs(direction.getMin()); 00099 m_length_parts.push_back( norm(dist) ); 00100 m_length += norm(dist); 00101 m_length_cumulated.push_back(m_length); 00102 } 00103 00104 m_param_length = m_TrajectorySpline.getMaxdPos(); 00105 00106 for (unsigned int i=0; i < m_length_parts.size(); i++) 00107 { 00108 m_s_parts.push_back( m_length_parts[i] / m_length ); 00109 } 00110 00111 m_v_rad_s = v_rad_s; 00112 m_a_rad_s2 = a_rad_s2; 00113 00114 /* Parameter für Beschl.begrenzte Fahrt: */ 00115 double a = fabs(m_a_rad_s2); 00116 double v = fabs(m_v_rad_s); 00117 00118 if (m_length > v*v/a) 00119 { 00120 // Phase mit konst. Geschw. wird erreicht: 00121 m_T1 = m_T3 = v / a; 00122 m_T2 = (m_length - v*v/a) / v; 00123 00124 // Wegparameter s immer positiv, deswegen keine weitere Fallunterscheidung nötig: 00125 m_sv2 = 1.0 / (m_T1 + m_T2); 00126 m_sa1 = m_sv2 / m_T1; 00127 m_sa3 = -m_sa1; 00128 } 00129 else { 00130 // Phase konst. Geschw. wird nicht erreicht: 00131 m_T2 = 0.0; 00132 m_T1 = m_T3 = sqrt(m_length / a); 00133 00134 m_sv2 = 1.0 / m_T1; 00135 m_sa1 = m_sv2 / m_T1; 00136 m_sa3 = -m_sa1; 00137 00138 } 00139 // Bewegung vollständig charakterisiert. 00140 00141 } 00142 00143 std::vector<double> RefValJS_PTP_Trajectory::r(double s) const 00144 { 00145 //printw("Line %d\ts: %f\n", __LINE__, s); 00146 std::vector<double> soll; 00147 if (s <= 0) 00148 { 00149 soll = m_trajectory.points.front().positions; 00150 } else 00151 if (s < 1) 00152 { 00153 // since the Distances between the points of m_SplinePoints are not equal, 00154 // we first need to find the last i where m_length_cumulated[i] is smaller than s*m_length 00155 00156 // return the first index i, where m_length_cumulated[i] is not smaller s * m_length 00157 // more information under: http://www.cplusplus.com/reference/algorithm/lower_bound/ 00158 //typedef std::vector<double> dvec; 00159 00160 00161 vecd_it start = m_length_cumulated.begin(); 00162 vecd_it end = m_length_cumulated.end(); 00163 vecd_it it = upper_bound(start, end, s * m_length); 00164 00165 int i = int(it-start) - 1; 00166 double frac = (s * m_length - m_length_cumulated[i]) / m_length_parts[i]; 00167 00168 00169 /* 00170 int i = floor( s * m_param_length / m_stepSize); 00171 double frac = s * m_param_length / m_stepSize - (double) i; 00172 */ 00173 // interpolate 00174 soll.resize(m_SplinePoints[i].size()); 00175 for(unsigned int j = 0; j < m_SplinePoints[i].size(); j++) 00176 { 00177 soll.at(j) = m_SplinePoints[i].at(j) + (m_SplinePoints[i+1].at(j)-m_SplinePoints[i].at(j))*frac; 00178 } 00179 } 00180 else 00181 { 00182 soll = m_trajectory.points.back().positions; 00183 } 00184 return soll; 00185 } 00186 00187 double RefValJS_PTP_Trajectory::s(double t) const 00188 { 00189 if (t >= m_T1 + m_T2 + m_T3) 00190 return 1.0; 00191 else if (t >= m_T1 + m_T2) 00192 { 00193 return 0.5*m_sa1*m_T1*m_T1 + m_sv2*m_T2 + m_sv2*(t-m_T1-m_T2) + 0.5*m_sa3*sqr(t-m_T1-m_T2); 00194 } 00195 else if (t >= m_T1) 00196 { 00197 return 0.5*m_sa1*m_T1*m_T1 + m_sv2*(t-m_T1); 00198 } 00199 else if (t > 0.0) 00200 { 00201 return 0.5*m_sa1*t*t; 00202 } 00203 else return 0.0; 00204 } 00205 00206 double RefValJS_PTP_Trajectory::ds_dt(double t) const 00207 { 00208 if (t >= m_T1 + m_T2 + m_T3) 00209 return 0.0; 00210 else if (t >= m_T1 + m_T2) 00211 { 00212 return m_sv2 + m_sa3*(t-m_T1-m_T2); 00213 } 00214 else if (t >= m_T1) 00215 { 00216 return m_sv2; 00217 } 00218 else if (t > 0.0) 00219 { 00220 return m_sa1*t; 00221 } 00222 else return 0.0; 00223 } 00224 00225 00226 std::vector<double> RefValJS_PTP_Trajectory::dr_ds(double s) const 00227 { 00228 //printw("Line %d\ts: %f\n", __LINE__, s); 00229 std::vector<double> result = m_trajectory.points.front().positions; 00230 if (s < 0.0 || s >= 1.0) 00231 { 00232 for(unsigned int j=0; j < result.size(); j++) 00233 result.at(j) = 0.0; 00234 } 00235 else 00236 { 00237 00238 vecd_it start = m_length_cumulated.begin(); 00239 vecd_it end = m_length_cumulated.end(); 00240 vecd_it it = upper_bound(start, end, s * m_length); 00241 00242 int i = int(it-start) - 1; 00243 double frac = (s * m_length - m_length_cumulated[i]) / m_length_parts[i]; 00244 00245 00246 /* 00247 int i = floor( s * m_param_length / m_stepSize); 00248 double frac = s * m_param_length / m_stepSize - (double) i; 00249 */ 00250 00251 std::vector<double> vi; // vi 00252 std::vector<double> vii;// vi+1 00253 00254 double step_s = m_stepSize / m_param_length; 00255 00256 if ( i == 0 ) 00257 { 00258 // vi rechtsseitig approximieren 00259 step_s = m_length_parts[0] / m_length; 00260 vi.resize(m_SplinePoints[i].size()); 00261 for(unsigned int k = 0; k < m_SplinePoints[i].size(); k++) 00262 { 00263 vi.at(k) = (m_SplinePoints[1].at(k) - m_SplinePoints[0].at(k)) / step_s; 00264 } 00265 vii = vi; 00266 // vi+1 zentrisch approximieren 00267 //step_s = (m_length_parts[i]+m_length_parts[i+1]) / m_length; 00268 //vii = (m_SplinePoints[i+2] - m_SplinePoints[i]) / (2.0 * step_s); 00269 } else 00270 if ( i == (int) m_SplinePoints.size() - 2 ) 00271 { 00272 // vi zentrisch: 00273 //step_s = (m_length_parts[i]+m_length_parts[i-1]) / m_length; 00274 //vi = (m_SplinePoints[i+1] - m_SplinePoints[i-1]) / (2.0 * step_s); 00275 // vi+1 linksseitig: 00276 step_s = (m_length_parts[i]) / m_length; 00277 vii.resize(m_SplinePoints[i].size()); 00278 for(unsigned int k = 0; k < m_SplinePoints[i].size(); k++) 00279 vii.at(k) = (m_SplinePoints[i+1].at(k) - m_SplinePoints[i].at(k)) / step_s; 00280 vi = vii; 00281 } else 00282 { 00283 // beide zentrisch: 00284 step_s = (m_length_parts[i]+m_length_parts[i-1]) / m_length; 00285 vi.resize(m_SplinePoints[i].size()); 00286 for(unsigned int k = 0; k < m_SplinePoints[i].size(); k++) 00287 vi.at(k) = (m_SplinePoints[i+1].at(k) - m_SplinePoints[i-1].at(k)) / step_s; 00288 step_s = (m_length_parts[i]+m_length_parts[i+1]) / m_length; 00289 vii.resize(m_SplinePoints[i].size()); 00290 for(unsigned int k = 0; k < m_SplinePoints[i].size(); k++) 00291 vii.at(k) = (m_SplinePoints[i+2].at(k) - m_SplinePoints[i].at(k)) / step_s; 00292 } 00293 00294 // linear interpolieren: 00295 result.resize(m_SplinePoints[i].size()); 00296 for(unsigned int k = 0; k < m_SplinePoints[i].size(); k++) 00297 result.at(k) = vi.at(k) + (vii.at(k)-vi.at(k))*frac; 00298 } 00299 00300 return result; 00301 } 00302 00303 00304 00305