libcarla/include/odrSpiral/odrSpiral.cpp

251 lines
5.9 KiB
C++
Raw Normal View History

2024-10-18 13:19:59 +08:00
/* ===================================================
* file: odrSpiral.c
* ---------------------------------------------------
* purpose: free method for computing spirals
* in OpenDRIVE applications
* ---------------------------------------------------
* using methods of CEPHES library
* ---------------------------------------------------
* first edit: 09.03.2010 by M. Dupuis @ VIRES GmbH
* last mod.: 09.03.2010 by M. Dupuis @ VIRES GmbH
* ===================================================
Copyright 2010 VIRES Simulationstechnologie GmbH
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NOTE:
The methods have been realized using the CEPHES library
http://www.netlib.org/cephes/
and do neither constitute the only nor the exclusive way of implementing
spirals for OpenDRIVE applications. Their sole purpose is to facilitate
the interpretation of OpenDRIVE spiral data.
*/
/* ====== INCLUSIONS ====== */
#include <stdio.h>
// Edit to original file-----
#define _USE_MATH_DEFINES // Enable windows compatibility
// --------------------------
#include <math.h>
/* ====== LOCAL VARIABLES ====== */
/* S(x) for small x */
static double sn[6] = {
-2.99181919401019853726E3,
7.08840045257738576863E5,
-6.29741486205862506537E7,
2.54890880573376359104E9,
-4.42979518059697779103E10,
3.18016297876567817986E11,
};
static double sd[6] = {
/* 1.00000000000000000000E0,*/
2.81376268889994315696E2,
4.55847810806532581675E4,
5.17343888770096400730E6,
4.19320245898111231129E8,
2.24411795645340920940E10,
6.07366389490084639049E11,
};
/* C(x) for small x */
static double cn[6] = {
-4.98843114573573548651E-8,
9.50428062829859605134E-6,
-6.45191435683965050962E-4,
1.88843319396703850064E-2,
-2.05525900955013891793E-1,
9.99999999999999998822E-1,
};
static double cd[7] = {
3.99982968972495980367E-12,
9.15439215774657478799E-10,
1.25001862479598821474E-7,
1.22262789024179030997E-5,
8.68029542941784300606E-4,
4.12142090722199792936E-2,
1.00000000000000000118E0,
};
/* Auxiliary function f(x) */
static double fn[10] = {
4.21543555043677546506E-1,
1.43407919780758885261E-1,
1.15220955073585758835E-2,
3.45017939782574027900E-4,
4.63613749287867322088E-6,
3.05568983790257605827E-8,
1.02304514164907233465E-10,
1.72010743268161828879E-13,
1.34283276233062758925E-16,
3.76329711269987889006E-20,
};
static double fd[10] = {
/* 1.00000000000000000000E0,*/
7.51586398353378947175E-1,
1.16888925859191382142E-1,
6.44051526508858611005E-3,
1.55934409164153020873E-4,
1.84627567348930545870E-6,
1.12699224763999035261E-8,
3.60140029589371370404E-11,
5.88754533621578410010E-14,
4.52001434074129701496E-17,
1.25443237090011264384E-20,
};
/* Auxiliary function g(x) */
static double gn[11] = {
5.04442073643383265887E-1,
1.97102833525523411709E-1,
1.87648584092575249293E-2,
6.84079380915393090172E-4,
1.15138826111884280931E-5,
9.82852443688422223854E-8,
4.45344415861750144738E-10,
1.08268041139020870318E-12,
1.37555460633261799868E-15,
8.36354435630677421531E-19,
1.86958710162783235106E-22,
};
static double gd[11] = {
/* 1.00000000000000000000E0,*/
1.47495759925128324529E0,
3.37748989120019970451E-1,
2.53603741420338795122E-2,
8.14679107184306179049E-4,
1.27545075667729118702E-5,
1.04314589657571990585E-7,
4.60680728146520428211E-10,
1.10273215066240270757E-12,
1.38796531259578871258E-15,
8.39158816283118707363E-19,
1.86958710162783236342E-22,
};
static double polevl( double x, double* coef, int n )
{
double ans;
double *p = coef;
int i;
ans = *p++;
i = n;
do
{
ans = ans * x + *p++;
}
while (--i);
return ans;
}
static double p1evl( double x, double* coef, int n )
{
double ans;
double *p = coef;
int i;
ans = x + *p++;
i = n - 1;
do
{
ans = ans * x + *p++;
}
while (--i);
return ans;
}
static void fresnel( double xxa, double *ssa, double *cca )
{
double f, g, cc, ss, c, s, t, u;
double x, x2;
x = fabs( xxa );
x2 = x * x;
if ( x2 < 2.5625 )
{
t = x2 * x2;
ss = x * x2 * polevl (t, sn, 5) / p1evl (t, sd, 6);
cc = x * polevl (t, cn, 5) / polevl (t, cd, 6);
}
else if ( x > 36974.0 )
{
cc = 0.5;
ss = 0.5;
}
else
{
x2 = x * x;
t = M_PI * x2;
u = 1.0 / (t * t);
t = 1.0 / t;
f = 1.0 - u * polevl (u, fn, 9) / p1evl(u, fd, 10);
g = t * polevl (u, gn, 10) / p1evl (u, gd, 11);
t = M_PI * 0.5 * x2;
c = cos (t);
s = sin (t);
t = M_PI * x;
cc = 0.5 + (f * s - g * c) / t;
ss = 0.5 - (f * c + g * s) / t;
}
if ( xxa < 0.0 )
{
cc = -cc;
ss = -ss;
}
*cca = cc;
*ssa = ss;
}
/**
* compute the actual "standard" spiral, starting with curvature 0
* @param s run-length along spiral
* @param cDot first derivative of curvature [1/m2]
* @param x resulting x-coordinate in spirals local co-ordinate system [m]
* @param y resulting y-coordinate in spirals local co-ordinate system [m]
* @param t tangent direction at s [rad]
*/
void odrSpiral( double s, double cDot, double *x, double *y, double *t )
{
double a;
a = 1.0 / sqrt( fabs( cDot ) );
a *= sqrt( M_PI );
fresnel( s / a, y, x );
*x *= a;
*y *= a;
if ( cDot < 0.0 )
*y *= -1.0;
*t = s * s * cDot * 0.5;
}