RefValJS_PTP_Trajectory.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


cob_trajectory_controller
Author(s): Alexander Bubeck
autogenerated on Fri Mar 1 2013 17:49:16