EulerSpiral Class Reference

#include <euler.h>


Detailed Description

Definition at line 139 of file euler.h.


Public Member Functions

Point2D< double > compute_end_pt (double k0, double gamma, double L, bool bNormalized=false)
Point2D< double > compute_end_pt (double arclength, bool bNormalized=false)
double compute_error (double k0, double L)
void compute_es_params ()
Point2D< double > compute_es_point (EulerSpiralParams &es_params, double arclength, bool bNormalized=false)
void computeSpiral (std::vector< Point2D< double > > &spiral, double ds=0, int NPts=0)
 EulerSpiral (Point2D< double > start_pt, double start_angle, double k0, double gamma, double L)
 EulerSpiral (Point2D< double > start_pt, double start_angle, Point2D< double > end_pt, double end_angle)
 EulerSpiral ()
Point2D< double > get_fresnel_integral (double value)
void set_end_params (Point2D< double > end_pt, double end_angle)
void set_params (Point2D< double > start_pt, double start_angle, Point2D< double > end_pt, double end_angle)
void set_start_params (Point2D< double > start_pt, double start_angle)

Data Fields

EulerSpiralParams params
std::vector< Point2D< double > > pts

Private Attributes

BiArc _bi_arc_estimate

Constructor & Destructor Documentation

EulerSpiral::EulerSpiral (  )  [inline]

Definition at line 148 of file euler.h.

00148 {};

EulerSpiral::EulerSpiral ( Point2D< double >  start_pt,
double  start_angle,
Point2D< double >  end_pt,
double  end_angle 
) [inline]

Definition at line 151 of file euler.h.

References angle0To2Pi(), compute_es_params(), EulerSpiralParams::end_angle, EulerSpiralParams::end_pt, params, EulerSpiralParams::start_angle, and EulerSpiralParams::start_pt.

00152   {
00153     params.start_pt = start_pt;
00154     params.start_angle = angle0To2Pi(start_angle);
00155 
00156     params.end_pt = end_pt;
00157     params.end_angle = angle0To2Pi(end_angle);
00158 
00159     //since we have all the parameters, we might as well compute it
00160     compute_es_params();
00161   }

EulerSpiral::EulerSpiral ( Point2D< double >  start_pt,
double  start_angle,
double  k0,
double  gamma,
double  L 
) [inline]

Definition at line 164 of file euler.h.

References angle0To2Pi(), compute_end_pt(), compute_es_params(), EulerSpiralParams::end_angle, EulerSpiralParams::end_pt, params, EulerSpiralParams::start_angle, and EulerSpiralParams::start_pt.

00165   {
00166     params.start_pt = start_pt;
00167     params.start_angle = angle0To2Pi(start_angle);
00168     params.end_pt = compute_end_pt(k0, gamma, L);
00169     params.end_angle = start_angle + 0.5*gamma*L*L + k0*L;
00170 
00171     //since we have all the parameters, we might as well compute it
00172     compute_es_params();
00173   }


Member Function Documentation

Point2D< double > EulerSpiral::compute_end_pt ( double  k0,
double  gamma,
double  L,
bool  bNormalized = false 
)

Definition at line 400 of file euler.cpp.

References CCW(), eGamma, eK, get_fresnel_integral(), Point2D< coord_type >::getX(), Point2D< coord_type >::getY(), M_PI, params, EulerSpiralParams::psi, Point2D< coord_type >::setX(), Point2D< coord_type >::setY(), EulerSpiralParams::start_angle, and EulerSpiralParams::start_pt.

00401 {
00402   Point2D<double> start_pt;
00403   Point2D<double> end_pt;
00404 
00405   double theta;
00406 
00407   if (bNormalized){
00408     start_pt = Point2D<double>(0,0);
00409     theta = CCW(params.psi, params.start_angle);
00410   }
00411   else {
00412     start_pt = params.start_pt;
00413     theta = params.start_angle;
00414   }
00415 
00416   if (L==0)
00417     return start_pt;
00418 
00419   if (fabs(gamma)<eGamma) 
00420   { 
00421     if (fabs(k0)<eK)
00422     {
00423       //straight line
00424       end_pt.setX(start_pt.getX()+L*cos(theta));
00425       end_pt.setY(start_pt.getY()+L*sin(theta));
00426     }
00427     else 
00428     { 
00429       //circle
00430       double const_term = 1.0/k0;
00431       end_pt.setX(start_pt.getX()+const_term*(sin(k0*L+theta)-sin(theta)));
00432       end_pt.setY(start_pt.getY()-const_term*(cos(k0*L+theta)-cos(theta))); 
00433     }
00434     return end_pt;
00435   }
00436 
00437   double const1 = sqrt(M_PI*fabs(gamma));
00438   double const2 = sqrt(M_PI/fabs(gamma));
00439 
00440   Point2D<double> fresnel1 = get_fresnel_integral((k0+gamma*L)/const1);
00441   Point2D<double> fresnel2 = get_fresnel_integral(k0/const1);
00442 
00443   double C = (fresnel1.getX() - fresnel2.getX());
00444   if(gamma<0) {
00445       C *= -1.;
00446   }
00447   double S = fresnel1.getY() - fresnel2.getY();
00448 
00449   double cos_term = cos(theta-((k0*k0)/(2.0*gamma)));
00450   double sin_term = sin(theta-((k0*k0)/(2.0*gamma))); 
00451   
00452   end_pt.setX(start_pt.getX() + const2*(C*cos_term - S*sin_term));
00453   end_pt.setY(start_pt.getY() + const2*(C*sin_term + S*cos_term));
00454 
00455   return end_pt;
00456 }

Point2D< double > EulerSpiral::compute_end_pt ( double  arclength,
bool  bNormalized = false 
)

Definition at line 395 of file euler.cpp.

References EulerSpiralParams::gamma, EulerSpiralParams::K0, and params.

Referenced by compute_error(), compute_es_point(), computeSpiral(), and EulerSpiral().

00396 {
00397   return compute_end_pt(params.K0, params.gamma, arclength, bNormalized);
00398 }

double EulerSpiral::compute_error ( double  k0,
double  L 
) [inline]

Definition at line 458 of file euler.cpp.

References compute_end_pt(), euc_distance(), params, and EulerSpiralParams::turningAngle.

Referenced by compute_es_params().

00459 {
00460   //assumes normalized parameters
00461 
00462   //compute the endpoint of the Euler spiral with the given intrinsic parameters
00463   double gamma = 2*(params.turningAngle - k0*L)/(L*L);
00464   Point2D<double> cur_end_pt = compute_end_pt(k0, gamma, L, true);
00465 
00466   //the error is the distance between the current end point and the desired end point
00467   return euc_distance(Point2D<double>(1,0), cur_end_pt);
00468 }

void EulerSpiral::compute_es_params (  ) 

Definition at line 288 of file euler.cpp.

References _bi_arc_estimate, angle0To2Pi(), BiArc::compute_biarc_params(), compute_error(), eError, EulerSpiralParams::end_angle, EulerSpiralParams::end_pt, EulerSpiralParams::error, euc_distance(), EulerSpiralParams::gamma, EulerSpiralParams::K0, BiArcParams::K1, EulerSpiralParams::K2, BiArcParams::K2, EulerSpiralParams::L, BiArcParams::L(), BiArcParams::L1, BiArcParams::L2, MAX_NUM_ITERATIONS, MIN2(), BiArc::params, params, EulerSpiralParams::psi, BiArc::set_end_params(), BiArc::set_start_params(), EulerSpiralParams::start_angle, EulerSpiralParams::start_pt, EulerSpiralParams::turningAngle, Point2D< coord_type >::x(), and Point2D< coord_type >::y().

Referenced by EulerSpiral().

00289 {
00290   //compute scaling distance
00291   double d = euc_distance(params.start_pt, params.end_pt);
00292   params.psi = angle0To2Pi(atan2(params.end_pt.y()-params.start_pt.y(),params.end_pt.x()-params.start_pt.x()));
00293 
00294   //degeneracy check
00295   if (d<eError)
00296     return; 
00297 
00298   //first compute a biarc estimate
00299   _bi_arc_estimate.set_start_params(params.start_pt, params.start_angle);
00300   _bi_arc_estimate.set_end_params(params.end_pt, params.end_angle);
00301   _bi_arc_estimate.compute_biarc_params();
00302 
00303   //get the total turning angle::This is an important parameter because
00304   //it defines the one solution out of many possible solutions
00305   params.turningAngle = _bi_arc_estimate.params.K1*_bi_arc_estimate.params.L1 +
00306                  _bi_arc_estimate.params.K2*_bi_arc_estimate.params.L2;
00307 
00308   //From here on, normlize the parameters and use these to perform the optimization
00309 
00310   double k0_init_est = _bi_arc_estimate.params.K1*d;
00311   double L_init_est = _bi_arc_estimate.params.L()/d;
00312   double dstep = 0.1;
00313 
00314   //Alternately, we can get the initial values from the lookup table and perform 
00315   //the optimization from there
00316   //double k0_init_est = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->k0(CCW(params.psi, params.start_angle), CCW(params.psi, params.end_angle));
00317   //double L_init_est = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->L(CCW(params.psi, params.start_angle), CCW(params.psi, params.end_angle));
00318   //double dstep = globalEulerSpiralLookupTable->get_globalEulerSpiralLookupTable()->dt()/4;
00319 
00320   //then perform a simple gradient descent to find the real solution
00321   double error = compute_error(k0_init_est, L_init_est);
00322   double prev_error = error;
00323   
00324   double k0 = k0_init_est;
00325   double L = L_init_est;
00326 
00327   double e1, e2, e3, e4;
00328 
00329   for (int i=0;i<MAX_NUM_ITERATIONS;i++)
00330   {
00331      if (error<eError)
00332         break;
00333     
00334      e1 = compute_error(k0 + dstep, L);
00335      e2 = compute_error(k0 - dstep, L);
00336      e3 = compute_error(k0, L + dstep);
00337      if (L>dstep)  e4 = compute_error(k0, L - dstep);
00338     
00339      error = MIN2(MIN2(e1,e2),MIN2(e3,e4));
00340     
00341      if (error>prev_error)
00342      {
00343        dstep = dstep/2;
00344        continue;
00345      }
00346     
00347      if    (error==e1)  k0 = k0 + dstep;
00348      else if (error==e2) k0 = k0 - dstep;
00349      else if (error==e3) L = L + dstep;
00350      else if (error==e4) L = L - dstep;
00351       
00352      prev_error = error;
00353   }
00354 
00355   //store the parameters
00356   params.K0 = k0/d;
00357   params.L = L*d;
00358   params.gamma = 2*(params.turningAngle - k0*L)/(L*L)/(d*d);
00359   params.K2 = (k0 + params.gamma*L)/d;
00360   params.error = error;
00361 }

Point2D< double > EulerSpiral::compute_es_point ( EulerSpiralParams es_params,
double  arclength,
bool  bNormalized = false 
)

Definition at line 389 of file euler.cpp.

References compute_end_pt(), EulerSpiralParams::gamma, EulerSpiralParams::K0, and params.

00390 {
00391   params = es_params;
00392   return compute_end_pt(params.K0, params.gamma, arclength, bNormalized);
00393 }

void EulerSpiral::computeSpiral ( std::vector< Point2D< double > > &  spiral,
double  ds = 0,
int  NPts = 0 
)

Definition at line 364 of file euler.cpp.

References compute_end_pt(), EulerSpiralParams::end_pt, EulerSpiralParams::L, params, and EulerSpiralParams::start_pt.

Referenced by NIImporter_OpenDrive::geomFromSpiral().

00365 {
00366   if (ds==0 && NPts==0){
00367     //use default values
00368     NPts = 100;
00369     ds = params.L/NPts;
00370   }
00371 
00372   spiral.clear();
00373   spiral.push_back(params.start_pt);
00374 
00375   double s=ds;
00376   if (NPts == 0) 
00377     NPts = (int) (params.L / ds);
00378   for (int i=1; i<NPts; i++,s+=ds){
00379     Point2D<double> cur_pt = compute_end_pt(s);
00380     spiral.push_back(cur_pt);
00381   }
00382   spiral.push_back(params.end_pt);
00383 }

Point2D< double > EulerSpiral::get_fresnel_integral ( double  value  ) 

Definition at line 482 of file euler.cpp.

References EPS, FPMIN, M_PI, MAXIT, Point2D< coord_type >::setX(), Point2D< coord_type >::setY(), sign, and XMIN.

Referenced by compute_end_pt().

00483 {
00484   bool odd;
00485   int k,n;
00486   double a,ax,fact,pix2,sign,sum,sumc,sums,term,test;
00487 
00488   std::complex<double> b,cc,d,h,del,cs;
00489   Point2D<double> result;
00490 
00491   ax=fabs(x);
00492   if (ax < sqrt(FPMIN)) 
00493   { 
00494     //Special case: avoid failure of convergence test because of undeflow.
00495     result.setY(0.0);
00496     result.setX(ax);
00497   }
00498   else {
00499     if (ax <= XMIN)
00500     {
00501       // Evaluate both series simultaneously.
00502       sum=sums=0.0;
00503       sumc=ax;
00504       sign=1.0;
00505       fact=(M_PI/2.0)*ax*ax;
00506       odd=true;
00507       term=ax;
00508       n=3;
00509 
00510       for (k=1;k<=MAXIT;k++)
00511       { 
00512         term *= fact/k;
00513         sum  += sign*term/n;
00514         test=fabs(sum)*EPS;
00515         if (odd) 
00516         {
00517           sign = -sign;
00518           sums=sum;
00519           sum=sumc;
00520         }
00521         else {
00522           sumc=sum;
00523           sum=sums;
00524         }
00525 
00526         if (term < test) break;
00527         odd=!odd;
00528         n +=2;
00529       }
00530 
00531       if (k > MAXIT) 
00532         std::cout << "series failed in fresnel" << std::endl;
00533 
00534       result.setY(sums); 
00535       result.setX(sumc);
00536     }
00537     else {
00538       // Evaluate continued fraction by modified Lentz's method
00539       pix2=M_PI*ax*ax;
00540       b   = std::complex<double>(1.0,-pix2);
00541       cc  = std::complex<double>(1.0/FPMIN,0.0);
00542       d=h = std::complex<double>(1.0,0.0)/b;
00543       n = -1;
00544 
00545       for (k=2;k<=MAXIT;k++) 
00546       {
00547         n +=2;
00548         a = -n*(n+1);
00549         b= b+std::complex<double>(4.0,0.0);
00550         d=(std::complex<double>(1.0,0.0)/((a*d)+b));
00551 
00552         //Denominators cannot be zero
00553         cc=(b+(std::complex<double>(a,0.0)/cc));
00554 
00555         del=(cc*d);
00556         h=h*del;
00557         if ((fabs(del.real()-1.0)+fabs(del.imag())) < EPS)
00558           break;
00559       }
00560       if (k > MAXIT) 
00561         std::cout << "cf failed in frenel" << std::endl;
00562 
00563       h=std::complex<double>(ax,-ax)*h;
00564       cs=std::complex<double>(0.5,0.5)*(std::complex<double>(1.0,0.0) - std::complex<double>(cos(0.5*pix2),sin(0.5*pix2))*h );
00565 
00566       result.setX(cs.real());
00567       result.setY(cs.imag());
00568     }
00569   }
00570 
00571   if (x<0){ //use antisymmetry
00572     result = -1*result;  
00573   }
00574 
00575   return result;
00576 }

void EulerSpiral::set_end_params ( Point2D< double >  end_pt,
double  end_angle 
) [inline]

Definition at line 181 of file euler.h.

References angle0To2Pi(), EulerSpiralParams::end_angle, EulerSpiralParams::end_pt, and params.

00182   {
00183     params.end_pt = end_pt;
00184     params.end_angle = angle0To2Pi(end_angle);
00185   }

void EulerSpiral::set_params ( Point2D< double >  start_pt,
double  start_angle,
Point2D< double >  end_pt,
double  end_angle 
) [inline]

Definition at line 187 of file euler.h.

References angle0To2Pi(), EulerSpiralParams::end_angle, EulerSpiralParams::end_pt, params, EulerSpiralParams::start_angle, and EulerSpiralParams::start_pt.

00188   {
00189     params.start_pt = start_pt;
00190     params.start_angle = angle0To2Pi(start_angle);
00191 
00192     params.end_pt = end_pt;
00193     params.end_angle = angle0To2Pi(end_angle);
00194   }

void EulerSpiral::set_start_params ( Point2D< double >  start_pt,
double  start_angle 
) [inline]

Definition at line 175 of file euler.h.

References angle0To2Pi(), params, EulerSpiralParams::start_angle, and EulerSpiralParams::start_pt.

00176   {
00177     params.start_pt = start_pt;
00178     params.start_angle = angle0To2Pi(start_angle);
00179   }


Field Documentation

Definition at line 142 of file euler.h.

Referenced by compute_es_params().

std::vector<Point2D<double> > EulerSpiral::pts

Definition at line 146 of file euler.h.


The documentation for this class was generated from the following files:

Generated on Wed May 5 00:06:41 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6