This lib is considered to be used as a sensor's calibration program. Calibration with Spline Interpolation might be useful in the case that you want some model expressing relationship such like between a value of physical quantity and your sensor's voltage, but you cannot estimate a model such as liner, square, cubic polynomial, or sine curve. This makes (Parametric) Cubic Spline Polynomial Model (Coefficients of the polynomial) from some sample plots(e.g. sets of (value, voltage)). The inverse function (x,y)->(y,x) has been implemented so as to get analog data (not stepping or leveled data).

Fork of TRP105F_Spline by Akifumi Takahashi

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CubicSpline.cpp Source File

CubicSpline.cpp

00001 #include "CubicSpline.h"
00002 
00003 //  To get voltage of TRP105F
00004 AnalogIn g_Sensor_Voltage(p16);
00005 //  To get sample distance via seral com
00006 Serial g_Serial_Signal(USBTX, USBRX);
00007 
00008 LocalFileSystem local("local");  // マウントポイントを定義(ディレクトリパスになる)
00009 // for debug
00010 #ifdef DEBUG
00011 DigitalOut led1(LED1);
00012 DigitalOut led2(LED2);
00013 DigitalOut led3(LED3);
00014 DigitalOut led4(LED4);
00015 #endif
00016 
00017 CubicSpline2d::CubicSpline2d()
00018     :_useType(AsMODULE)
00019 {
00020     _Sample_Num = 5;
00021     _Sample_Set = (Vxyt  *)malloc(_Sample_Num * sizeof(Vxyt));
00022     _Last_Point = (Vxyt) {
00023         0.0, 0.0, 0.0
00024     };
00025     for(int i = 0; i < 4; i++) {
00026         _C_x[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00027         _C_y[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00028     }
00029     //calibrateSensor();
00030 }
00031 
00032 CubicSpline2d::CubicSpline2d(
00033     unsigned int arg_num
00034 )
00035     :_useType(AsMODULE)
00036 {
00037     _Sample_Num = arg_num;
00038     _Sample_Set = (Vxyt  *)malloc(_Sample_Num * sizeof(Vxyt));
00039     _Last_Point = (Vxyt) {
00040         0.0, 0.0, 0.0
00041     };
00042     for(int i = 0; i < 4; i++) {
00043         _C_x[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00044         _C_y[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00045     }
00046     //calibrateSensor();
00047 }
00048 
00049 CubicSpline2d::CubicSpline2d(
00050     unsigned int    arg_num,
00051     UseType         arg_useType
00052 )
00053     :_useType(arg_useType)
00054 {
00055     _Sample_Num = arg_num;
00056     _Sample_Set = (Vxyt  *)malloc(_Sample_Num * sizeof(Vxyt));
00057     _Last_Point = (Vxyt) {
00058         0.0, 0.0, 0.0
00059     };
00060     for(int i = 0; i < 4; i++) {
00061         _C_x[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00062         _C_y[i]= (double*)malloc((_Sample_Num - 1)* sizeof(double));;
00063     }
00064     //calibrateSensor();
00065 }
00066 
00067 CubicSpline2d::~CubicSpline2d()
00068 {
00069     free(_Sample_Set);
00070     //free(_u_param);
00071     for(int i = 0; i < 4; i++) {
00072         free(_C_x[i]);
00073         free(_C_y[i]);
00074     }
00075 }
00076 
00077 void CubicSpline2d::_sampleData()
00078 {
00079     int     tmp;
00080     char    sig;
00081     Vxyt    tmp_set;
00082 
00083     int floatflag = 0;
00084 
00085     //  For evry set,
00086     //  1, get dst data via serai com,
00087     //  2, get vol data,
00088     //  and then do same for next index set.
00089     for(int i = 0; i < _Sample_Num; i++) {
00090         if(_useType == AsDEBUG) {
00091             //
00092             //  Recieve a Distance datus and store it into member
00093             //
00094             g_Serial_Signal.printf("X:");
00095             _Sample_Set[i].x = 0.0;
00096             do {
00097                 sig = g_Serial_Signal.getc();
00098                 if('0' <= sig && sig <= '9') {
00099                     if(floatflag == 0) {
00100                         _Sample_Set[i].x = 10.0 * _Sample_Set[i].x + (double)(sig - 48);
00101                     } else {
00102                         _Sample_Set[i].x = _Sample_Set[i].x + (double)(sig - 48) * pow(10.0, (double)- floatflag);
00103                         floatflag++;
00104                     }
00105                     g_Serial_Signal.putc(char(sig));
00106                 } else if(sig == '.') {
00107                     if(floatflag == 0) {
00108                         floatflag = 1;
00109                         g_Serial_Signal.putc(char(sig));
00110                     }
00111                 } else if(sig == 0x08) {
00112                     _Sample_Set[i].x = 0.0;
00113                     g_Serial_Signal.printf("[canseled!]");
00114                     g_Serial_Signal.putc('\n');
00115                     g_Serial_Signal.putc('>');
00116                 }
00117             } while (!(sig == 0x0a || sig == 0x0d));
00118             floatflag = 0;
00119             g_Serial_Signal.putc('\n');
00120             g_Serial_Signal.printf("x:%f|",_Sample_Set[i].x);
00121             //
00122             //  Recieve a Voltage datus and store it into member
00123             //
00124             //  LOW PASS FILTERED
00125             //  Get 10 data and store mean as a sample.
00126             //  After get one original sample, system waits for 0.1 sec,
00127             //  thus it takes 1 sec evry sampling.
00128             _Sample_Set[i].y = 0.0;
00129             for(int j = 0; j < 10; j++) {
00130                 tmp_set.y = g_Sensor_Voltage.read();
00131 #ifdef DEBUG
00132                 g_Serial_Signal.printf("%f,",tmp_set.y);
00133 #endif
00134                 _Sample_Set[i].y += (tmp_set.y / 10.0);
00135                 wait(0.1);
00136             }
00137 #ifdef DEBUG
00138             g_Serial_Signal.printf("(%f)\n",_Sample_Set[i].y);
00139 #endif
00140         }
00141 
00142         //  if the input data is over the bound, it is calibrated
00143         if (_Sample_Set[i].x < 0.0)
00144             _Sample_Set[i].x = 0.0;
00145     }
00146     //
00147     //  Sort set data array in x-Ascending order
00148     //
00149     tmp = 0;
00150     for(    int i = 0              ; i < _Sample_Num; i++) {
00151         for(int j = _Sample_Num - 1; i < j          ; j--) {
00152             //  use dst as index for dst range [2,20]
00153             if (_Sample_Set[i].x > _Sample_Set[j].x) {
00154                 tmp_set.x     = _Sample_Set[i].x;
00155                 tmp_set.y     = _Sample_Set[i].y;
00156                 _Sample_Set[i].x = _Sample_Set[j].x;
00157                 _Sample_Set[i].y = _Sample_Set[j].y;
00158                 _Sample_Set[j].x = tmp_set.x;
00159                 _Sample_Set[j].y = tmp_set.y;
00160             }
00161             // if a same dst has been input, calcurate mean.
00162             else if (_Sample_Set[i].x == _Sample_Set[j].x) {
00163                 tmp_set.y = (_Sample_Set[i].y + _Sample_Set[j].y)/2.0;
00164                 _Sample_Set[i].y = tmp_set.y;
00165                 for(int k = j; k < _Sample_Num - 1; k++)
00166                     _Sample_Set[k] = _Sample_Set[k+1];
00167                 tmp++;
00168             }
00169         }
00170     }
00171 #ifdef DEBUG
00172     g_Serial_Signal.printf("  _Sample_num: %d\n", _Sample_Num );
00173     g_Serial_Signal.printf("-)        tmp: %d\n", tmp );
00174 #endif
00175     //  substruct tmp from number of sample.
00176     _Sample_Num -= tmp;
00177 #ifdef DEBUG
00178     g_Serial_Signal.printf("-----------------\n");
00179     g_Serial_Signal.printf("  _Sample_num: %d\n", _Sample_Num );
00180 #endif
00181 
00182     //  generate t which is parameter related to x,y
00183     _Sample_Set[0].t = 0.0;
00184     for(int i = 1; i < _Sample_Num; i++)
00185         _Sample_Set[i].t =
00186             _Sample_Set[i-1].t
00187             + sqrt(pow(_Sample_Set[i].x - _Sample_Set[i-1].x, 2.0)
00188                    +pow(_Sample_Set[i].y - _Sample_Set[i-1].y, 2.0));
00189 }
00190 
00191 //
00192 //  Function to define _u_spline, specific constants of spline.
00193 //
00194 void CubicSpline2d::_makeModel(const double* arg_sampled_t, const double* arg_sampled_ft, double* arg_C[4], const unsigned int arg_num)
00195 {
00196     //  arg_t :     t; The variable of f(t)
00197     //  arg_ft:     f(t); The cubic poliminal in Interval-j.
00198     //  arg_C[i]:   Ci; The coefficient of t^i of f(t) that defines Spline Model Poliminal f(t).
00199     //  arg_num:    j in [0,_Sample_Num-1]; The number of interval.
00200     //  f(t)j = C3j*t^3 + C2j*t^2 + C1j*t + C0j
00201     //
00202     //  N: max of index <=> (_Sample_Num - 1)
00203     //
00204     //  u[i] === d^2/dx^2(Spline f)[i]
00205     //  i:[0,N]
00206     //  u[0] = u[N] = 0
00207 #if defined (VERSION_C)
00208     double *u = (double*)malloc((arg_num    ) * sizeof(double));
00209 #elif defined (VERSION_Cpp)
00210     double *u = new double[arg_num];
00211 #elif defined (VERSION_Cpp11)
00212     std::array<double,arg_num> u;
00213 #endif
00214     //
00215     //  h[i] = x[i+1] - x[i]
00216     //  i:[0,N-1]; num of elm: N<=>_Sample_Num - 1
00217     double *h = (double*)malloc((arg_num - 1) * sizeof(double));
00218     //
00219     //  v[i] = 6*((y[i+2]-y[i+1])/h[i+1] + (y[i+1]-y[i])/h[i])
00220     //  i:[0,N-2]
00221     double *v = (double*)malloc((arg_num - 2) * sizeof(double));
00222     //
00223     //  temporary array whose num of elm equals v array
00224     double *w = (double*)malloc((arg_num - 2) * sizeof(double));
00225     //
00226     //  [ 2(h[0]+h[1])  , h[1]          ,                                 O                 ]   [u[1]  ]   [v[0]  ]
00227     //  [ h[1]          , 2(h[1]+h[2])  , h[2]                                              ]   [u[2]  ]   [v[1]  ]
00228     //  [                       ...                                                         ] * [...   ] = [...   ]
00229     //  [                   h[j]          , 2(h[j]+h[j+1])  , h[j+1]                        ]   [u[j+1]]   [v[j]  ]
00230     //  [                                   ...                                             ]   [ ...  ]   [ ...  ]
00231     //  [                               h[N-3]        , 2(h[N-3]+h[N-2]), h[N-2]            ]   [u[j+1]]   [v[j]  ]
00232     //  [       O                                       h[N-2]          , 2(h[N-2]+h[N-1])  ]   [u[N-1]]   [v[N-2]]
00233     //
00234     // For LU decomposition
00235     double *Upper = (double*)malloc((arg_num - 2) * sizeof(double));
00236     double *Lower = (double*)malloc((arg_num - 2) * sizeof(double));
00237 #ifdef DEBUG_MAKE_MODEL
00238     _printOutDataCouple(arg_sampled_t, arg_sampled_ft, arg_num, "\nargument set\n");
00239 #endif
00240 
00241     for(int i = 0; i < arg_num - 1; i++)
00242         h[i] =  (double)(arg_sampled_t[i + 1] - arg_sampled_t[i]);
00243 
00244     for(int i = 0; i < arg_num - 2; i++)
00245         v[i] = 6.0 * (
00246                    ((double)(arg_sampled_ft[i + 2] - arg_sampled_ft[i + 1])) / h[i + 1]
00247                    -
00248                    ((double)(arg_sampled_ft[i + 1] - arg_sampled_ft[i]))     / h[i]
00249                );
00250 
00251     //
00252     //  LU decomposition
00253     //
00254     Upper[0] = 2.0 * (h[0] + h[1]);
00255     Lower[0] = 0.0;
00256     for (int i = 1; i < arg_num - 2; i++) {
00257         Lower[i] = h[i] / Upper[i - 1];
00258         Upper[i] = 2.0 * (h[i] + h[i + 1]) - Lower[i] * h[i];
00259     }
00260     //
00261     //  forward substitution
00262     //
00263     w[0] = v[0];
00264     for (int i = 1; i < arg_num - 2; i ++) {
00265         w[i] = v[i] - Lower[i] * w[i-1];
00266     }
00267     //
00268     //  backward substitution
00269     //
00270     u[arg_num - 2] =  w[arg_num - 3]                     / Upper[arg_num - 3];
00271     for(int i = arg_num - 3; i > 0; i--) {
00272         u[i]       = (w[(i - 1)] -  h[(i)] * u[(i) + 1]) / Upper[(i - 1)];
00273     }
00274     // _u_spline[i] === d^2/dx^2(Spline f)[i]
00275     u[0] = u[arg_num - 1] = 0.0;
00276 #ifdef DEBUG_MAKE_MODEL
00277     _printOutData(h,     arg_num - 1, "h");
00278     _printOutData(v,     arg_num - 2, "v");
00279     _printOutData(w,     arg_num - 2, "w");
00280     _printOutData(Upper, arg_num - 2, "Upper");
00281     _printOutData(Lower, arg_num - 2, "Lower");
00282     _printOutData(u,     arg_num    , "u");
00283 #endif
00284 
00285     for(int ival = 0; ival < arg_num - 1; ival++) {
00286         arg_C[3][ival] = (u[ival + 1] - u[ival]) / 6.0 / (arg_sampled_t[ival + 1] - arg_sampled_t[ival]);
00287         arg_C[2][ival] = (u[ival]) / 2.0;
00288         arg_C[1][ival] = (arg_sampled_ft[ival + 1] - arg_sampled_ft[ival]) / (arg_sampled_t[ival + 1] - arg_sampled_t[ival])
00289                          -
00290                          (arg_sampled_t[ival + 1]  - arg_sampled_t[ival])  * (u[ival + 1] + 2.0 * u[ival]) / 6.0;
00291         arg_C[0][ival] = (arg_sampled_ft[ival]);
00292     }
00293 #ifdef DEBUG_MAKE_MODEL
00294     for(int ival = 0; ival < arg_num - 1; ival++) {
00295         for(int i = 0; i < 4; i++)
00296             g_Serial_Signal.printf("C[%d][%d]: %f\n", i, ival, arg_C[i][ival]);
00297     }
00298 #endif
00299 
00300     free(h);
00301     free(u);
00302     free(v);
00303     free(w);
00304     free(Upper);
00305     free(Lower);
00306 }
00307 void CubicSpline2d::_makeModel(const double* arg_t, const double* arg_ft, double* arg_C[4])
00308 {
00309     _makeModel(arg_t, arg_ft, arg_C, _Sample_Num);
00310 }
00311 
00312 
00313 void CubicSpline2d::calibrateSensor()
00314 {
00315     double t[_Sample_Num];
00316     double ft[_Sample_Num];
00317 
00318     _sampleData();
00319     _Last_Point = _Sample_Set[0];
00320 
00321     for(int i = 0; i < _Sample_Num; i++) {
00322         t[i] = _Sample_Set[i].t;
00323         ft[i]= _Sample_Set[i].x;
00324     }
00325     _makeModel(t,ft,_C_x);
00326 
00327     for(int i = 0; i < _Sample_Num; i++) {
00328         ft[i]= _Sample_Set[i].y;
00329     }
00330     _makeModel(t,ft,_C_y);
00331 
00332 }
00333 
00334 
00335 //
00336 //  Fuction to return the value of Cubic polynomial f(t)
00337 //
00338 double  CubicSpline2d::_cubic_f(const double   arg_t, const double arg_C[4])
00339 {
00340     double ft;  //the value of Spline f(t).
00341 
00342     ft = arg_C[3] * pow(arg_t, 3.0) + arg_C[2] * pow(arg_t, 2.0) + arg_C[1] * arg_t + arg_C[0];
00343 
00344     return ft;
00345 }
00346 
00347 
00348 //
00349 //  Function to solve a cubic polinomial
00350 //  by using Gardano-Tartaglia formula
00351 //
00352 void CubicSpline2d::_solve_cubic_f(
00353     std::complex<double> arg_t[3],
00354     const double  arg_C[4],
00355     const double  arg_ft)
00356 {
00357 #ifdef DEBUG_SOLVE
00358     for(int i = 0; i < 4; i++)
00359         g_Serial_Signal.printf("C%d: %f\n", i, arg_C[i]);
00360 #endif
00361 
00362     //arg_t: solution that's expected to be solved in this function.
00363     //t_sol: the solution that's actually wanted as Sprine's solution.
00364     //t0_ival: _Sample_Set[ival].t
00365     //arg_t  = t_sol - t0_ival
00366     //=>
00367     //arg_ft = C[3](t_sol - t0_ival)^3 + C[2](t_sol - t0_ival)^2 + C[1](t_sol - t0_ival) + C[0]
00368     //       = C[3]arg_t^3 + C[2]arg_t^2 + C[1]arg_t + C[0]
00369     double c[3];
00370     //f(t) := arg_ft/arg_C[3]
00371     //      = arg_t^3 + c[2]*arg_t^2 + c[1]*arg_t + c[0].
00372     for(int i = 0; i < 3; i++) {
00373         c[i] = arg_C[i] / arg_C[3];
00374     }
00375     //modify the formula
00376     //t^3 + c[2]*t^2 + c[1]*t + (c[0] - f(t)) = 0.
00377     c[0] -= arg_ft / arg_C[3];
00378 #ifdef DEBUG_SOLVE
00379     for(int i = 0; i < 3; i++)
00380         g_Serial_Signal.printf("c%d: %f\n", i, c[i]);
00381 #endif
00382 
00383     std::complex<double> d;
00384     //d := c[2] / 3
00385     //T := t + d (== arg_t - t_iavl + c[2]/3)
00386     d = std::complex<double>(c[2] / 3.0, 0.0);
00387     //=>    T^3 + 3pT + 2q = 0.
00388     double p,q;
00389     //The values defined from coefficients of the formula
00390     //that identify solutions
00391     p = (     -pow(c[2], 2.0) + 3.0 * c[1]) / 9.0;
00392     q = (2.0 * pow(c[2], 3.0) - 9.0 * c[2] * c[1] + 27.0 * c[0]) / 54.0;
00393 
00394     //Discriminant section
00395     double D;
00396     D = pow(p, 3.0) + pow(q, 2.0);
00397 #ifdef DEBUG_SOLVE
00398     g_Serial_Signal.printf("p: %f\n", p);
00399     g_Serial_Signal.printf("q: %f\n", q);
00400     g_Serial_Signal.printf("D: %f\n", D);
00401 #endif
00402 
00403     //For all T, u, there exsists v: T = u + v;  increment degree of freedom.
00404     //Futhermore,
00405     //  u^3 + v^3 - 2q = 0
00406     //  uv + p = 0 <=> u^3v^3 = -p^3
00407     //those because: T = u + v, T^3 + 3pT + 2q = 0,
00408     //=>    (u + v)^3 + 3p(u + v) + 2q = 0
00409     //=>    u^3 + v^3 + 3(uv + p)(u+v) + 2q = 0
00410     //The values defined from p and q
00411     //that idetify solutions
00412     std::complex<double> u,v;
00413     //Real root only
00414     if(D <= 0.0) {
00415         u = std::complex<double>(-q, sqrt(-D));
00416         v = std::complex<double>(-q,-sqrt(-D));
00417         //u = pow(u, 1/3);
00418         //v = pow(v, 1/3);
00419         u = std::exp(std::log(u)/std::complex<double>(3.0,0.0));
00420         v = std::exp(std::log(v)/std::complex<double>(3.0,0.0));
00421     }
00422     //One real root and two complex root
00423     else {
00424         u = std::complex<double>(-q+sqrt(D),0.0);
00425         v = std::complex<double>(-q-sqrt(D),0.0);
00426         u = std::complex<double>(cbrt(u.real()), 0.0);
00427         v = std::complex<double>(cbrt(v.real()), 0.0);
00428     }
00429 #ifdef DEBUG_SOLVE
00430     g_Serial_Signal.printf("u: %f + (%f)i\n", u.real(), u.imag());
00431     g_Serial_Signal.printf("v: %f + (%f)i\n", v.real(), v.imag());
00432     g_Serial_Signal.printf("d: %f + (%f)i\n", d.real(), d.imag());
00433 #endif
00434 
00435     //Cubic root of 1
00436     std::complex<double> omega[3]= {
00437         std::complex<double>( 1.0, 0.0),
00438         std::complex<double>(-1.0/2.0, sqrt(3.0)/2.0),
00439         std::complex<double>(-1.0/2.0,-sqrt(3.0)/2.0)
00440     };
00441 
00442     //Solution of the formula
00443     arg_t[0] = omega[0] * u + omega[0] * v - d;
00444     arg_t[1] = omega[1] * u + omega[2] * v - d;
00445     arg_t[2] = omega[2] * u + omega[1] * v - d;
00446 
00447 #ifdef DEBUG_SOLVE
00448     for(int i = 0; i < 3; i++)
00449         g_Serial_Signal.printf("t%d: %f + (%f)i\n", i, arg_t[i].real(), arg_t[i].imag() );
00450 #endif
00451 }
00452 
00453 double  CubicSpline2d::getX(double arg_y)
00454 {
00455     double x;
00456     double C[4];
00457     double the_t;
00458     int    the_i;
00459     std::complex<double>t_sol[3];
00460     std::vector<double> t_real;
00461     std::vector<int>    t_ival;
00462 
00463 #ifdef DEBUG_GETX
00464     g_Serial_Signal.printf(DEBUG_GETX);
00465 #endif
00466     //  For the every Intervals of Spline,
00467     //it solves the polynomial defined by C[i] of the interval,
00468     //checks the solutions are real number,
00469     //and ckecks the solutions are in the interval.
00470     //  And if not-excluded solutions are more than one,
00471     //it trys to find which one is more nearest to last point.
00472     for(int ival = 0; ival < _Sample_Num - 1; ival++) {
00473         for(int i = 0; i < 4; i++) C[i] = _C_y[i][ival];
00474         _solve_cubic_f(t_sol, C, arg_y);
00475         for(int i = 0; i < 3; i++) t_sol[i] += _Sample_Set[ival].t;
00476 #ifdef DEBUG_GETX
00477         g_Serial_Signal.printf("interval:%d \t %f < t < %f\n", ival, _Sample_Set[ival].t, _Sample_Set[ival + 1].t);
00478 #endif
00479         for(int i = 0; i < 3; i++) {
00480             //  regarding only real solution
00481             //  acuracy (error range) is supposed +-10E-3 here(groundless)
00482             if(std::abs(t_sol[i].imag()) < 0.000001) {
00483                 /*  */ if (ival == 0               && t_sol[i].real() < _Sample_Set[ival].t) {
00484                     t_real.push_back(t_sol[i].real());
00485                     t_ival.push_back(ival);
00486 #ifdef DEBUG_GETX
00487                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00488 #endif
00489                 } else if (ival == _Sample_Num - 2 && _Sample_Set[ival + 1].t <= t_sol[i].real()) {
00490                     t_real.push_back(t_sol[i].real());
00491                     t_ival.push_back(ival);
00492 #ifdef DEBUG_GETX
00493                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00494 #endif
00495                 } else if (_Sample_Set[ival].t <= t_sol[i].real() && t_sol[i].real() < _Sample_Set[ival + 1].t) {
00496                     t_real.push_back(t_sol[i].real());
00497                     t_ival.push_back(ival);
00498 #ifdef DEBUG_GETX
00499                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00500 #endif
00501                 }
00502             }
00503         }
00504     }
00505 
00506     if(!t_real.empty()) {
00507         the_t = t_real[0];
00508         the_i = t_ival[0];
00509         //if t's size is bigger than 1
00510         for(int i = 1; i < t_real.size(); i++) {
00511             if(std::abs(t_real[i] - _Last_Point.t) < std::abs(the_t - _Last_Point.t)) {
00512                 the_t = t_real[i];
00513                 the_i = t_ival[i];
00514             }
00515         }
00516     } else {
00517 #ifdef DEBUG_GETX
00518         g_Serial_Signal.printf("LastPoint\n");
00519 #endif
00520         the_t = _Last_Point.t;
00521         for (int i = 0; i < _Sample_Num - 1; i++)
00522             if(_Sample_Set[i].t <= the_t && the_t <= _Sample_Set[i+1].t)
00523                 the_i = i;
00524     }
00525     /* */if (the_t < _Sample_Set[0].t) the_t = _Sample_Set[0].t;
00526     else if (_Sample_Set[_Sample_Num - 1].t <= the_t) the_t = _Sample_Set[_Sample_Num - 1].t;
00527 
00528     for(int i = 0; i < 4; i++) C[i] = _C_x[i][the_i];
00529     x = _cubic_f(the_t - _Sample_Set[the_i].t, C);
00530 #ifdef DEBUG_GETX
00531     g_Serial_Signal.printf("(the_t, the_i):= (%f , %d)\n",the_t, the_i);
00532 #endif
00533     _Last_Point = (Vxyt) {
00534         x, arg_y, the_t
00535     };
00536     return x;
00537 }
00538 
00539 double  CubicSpline2d::getY(double arg_x)
00540 {
00541 
00542     double y;
00543     double C[4];
00544     double the_t;
00545     int    the_i;
00546     std::complex<double>t_sol[3];
00547     std::vector<double> t_real;
00548     std::vector<int>    t_ival;
00549 
00550 #ifdef DEBUG_GETY
00551     g_Serial_Signal.printf(DEBUG_GETY);
00552     g_Serial_Signal.printf("arg_x: %f\n", arg_x);
00553 #endif
00554     //  For the every Intervals of Spline,
00555     //it solves the polynomial defined by C[i] of the interval,
00556     //checks the solutions are real number,
00557     //and ckecks the solutions are in the interval.
00558     //  And if not-excluded solutions are more than one,
00559     //it trys to find which one is more nearest to last point.
00560     for(int ival = 0; ival < _Sample_Num - 1; ival++) {
00561         for(int i = 0; i < 4; i++) C[i] = _C_x[i][ival];
00562         _solve_cubic_f(t_sol, C, arg_x);
00563         for(int i = 0; i < 3; i++) t_sol[i] += _Sample_Set[ival].t;
00564         //arg_ft = C[3](t_sol - t0_ival)^3 + C[2](t_sol - t0_ival)^2 + C[1](t_sol - t0_ival) + C[0]
00565         //       = C[3]arg_t^3 + C[2]arg_t^2 + C[1]arg_t + C[0]
00566 #ifdef DEBUG_GETY
00567         g_Serial_Signal.printf("interval:%d \t %f <= t < %f\n", ival, _Sample_Set[ival].t, _Sample_Set[ival + 1].t);
00568         for(int i = 0; i < 3; i++)
00569             g_Serial_Signal.printf("t%d \t %f + (%f)i\n", i, t_sol[i].real(), t_sol[i].imag());
00570 #endif
00571         for(int i = 0; i < 3; i++) {
00572             //  regarding only real solution
00573             //  acuracy (error range) is supposed +-10E-6 here(groundless)
00574             if(std::abs(t_sol[i].imag()) < 0.000001) {
00575                 /**/ if (ival == 0               && t_sol[i].real() < _Sample_Set[ival].t) {
00576                     t_real.push_back(t_sol[i].real());
00577                     t_ival.push_back(ival);
00578 #ifdef DEBUG_GETY
00579                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00580 #endif
00581                 }//
00582                 else if (ival == _Sample_Num - 2 && _Sample_Set[ival + 1].t <= t_sol[i].real()) {
00583                     t_real.push_back(t_sol[i].real());
00584                     t_ival.push_back(ival);
00585 #ifdef DEBUG_GETY
00586                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00587 #endif
00588                 }
00589                 //  There sometimes be a so fucking small error in solutions,
00590                 //  so acuracy is set at 10E-6(groundless)
00591                 else if (static_cast<int>(_Sample_Set[ival].t * std::pow(10., 6.)) <= static_cast<int>(t_sol[i].real() * std::pow(10., 6.))
00592                          &&  static_cast<int>(t_sol[i].real() * std::pow(10., 6.))     <  static_cast<int>(_Sample_Set[ival + 1].t * std::pow(10., 6.))) {
00593                     t_real.push_back(t_sol[i].real());
00594                     t_ival.push_back(ival);
00595 #ifdef DEBUG_GETY
00596                     g_Serial_Signal.printf("(t, i) = (%f, %d)\n", t_real[t_real.size() - 1], ival);
00597 #endif
00598                 }
00599             }
00600         }
00601     }
00602 
00603     if(!t_real.empty()) {
00604         the_t = t_real[0];
00605         the_i = t_ival[0];
00606         //if t's size is bigger than 1
00607         for(int i = 1; i < t_real.size(); i++) {
00608             if(std::abs(t_real[i] - _Last_Point.t) < std::abs(the_t - _Last_Point.t)) {
00609                 the_t = t_real[i];
00610                 the_i = t_ival[i];
00611             }
00612         }
00613     }
00614     //if no solution muched due to any errors
00615     else {
00616 #ifdef DEBUG_GETY
00617         g_Serial_Signal.printf("LastPoint\n");
00618 #endif
00619         the_t = _Last_Point.t;
00620         for (int i = 0; i < _Sample_Num - 1; i++)
00621             if(_Sample_Set[i].t <= the_t && the_t <= _Sample_Set[i+1].t)
00622                 the_i = i;
00623     }
00624 
00625     //
00626     /* */if (the_t < _Sample_Set[0].t) the_t = _Sample_Set[0].t;
00627     else if (_Sample_Set[_Sample_Num - 1].t < the_t) the_t = _Sample_Set[_Sample_Num - 1].t;
00628 
00629     //
00630     for(int i = 0; i < 4; i++) C[i] = _C_y[i][the_i];
00631     y = _cubic_f(the_t - _Sample_Set[the_i].t, C);
00632 #ifdef DEBUG_GETY
00633     g_Serial_Signal.printf("(the_t, the_i):= (%f , %d)\n",the_t, the_i);
00634 #endif
00635     _Last_Point = (Vxyt) {
00636         y, arg_x, the_t
00637     };
00638     return y;
00639 }
00640 
00641 
00642 
00643 void CubicSpline2d::saveSetting()
00644 {
00645     FILE *fp;
00646 
00647     fp = fopen("/local/savedata.log", "wb");
00648 
00649     //  Save _Sample_Num
00650     fwrite(&_Sample_Num, sizeof(unsigned int), 1, fp);
00651     fputc(0x3b, fp);
00652     //  Save _Sample_Set
00653     for(int i = 0; i < _Sample_Num; i++) {
00654         fwrite(&_Sample_Set[i].x,    sizeof(double), 1, fp);
00655         fputc(0x2c, fp);
00656         fwrite(&_Sample_Set[i].y,    sizeof(double), 1, fp);
00657         fputc(0x2c, fp);
00658         fwrite(&_Sample_Set[i].t,    sizeof(double), 1, fp);
00659         fputc(0x3b, fp);
00660     }
00661     //  Save _C_x
00662     for(int i = 0; i < _Sample_Num - 1; i++) {
00663         for(int j = 0; j < 4; j++) {
00664             fwrite(&_C_x[j][i],    sizeof(double), 1, fp);
00665             fputc((j != 3)? 0x2c : 0x3b, fp);
00666         }
00667     }
00668     //  Save _C_y
00669     for(int i = 0; i < _Sample_Num - 1; i++) {
00670         for(int j = 0; j < 4; j++) {
00671             fwrite(&_C_y[j][i],    sizeof(double), 1, fp);
00672             fputc((j != 3)? 0x2c : 0x3b, fp);
00673         }
00674     }
00675 
00676     fclose(fp);
00677 
00678 }
00679 
00680 void CubicSpline2d::saveSetting(
00681     const char *filename
00682 )
00683 {
00684     FILE *fp;
00685     char *filepath;
00686     int fnnum = 0;
00687 
00688     while (filename[fnnum] != 0) fnnum++;
00689     filepath = (char *)malloc((fnnum + 8) * sizeof(char)); // "/local/" are 7 char and \0 is 1 char.
00690 
00691     sprintf(filepath, "/local/%s", filename);
00692     fp = fopen(filepath, "wb");
00693 
00694     //  Save _Sample_Num
00695     fwrite(&_Sample_Num, sizeof(unsigned int), 1, fp);
00696     fputc(0x3b, fp);
00697     //  Save _Sample_Set
00698     for(int i = 0; i < _Sample_Num; i++) {
00699         fwrite(&_Sample_Set[i].x,    sizeof(double), 1, fp);
00700         fputc(0x2c, fp);
00701         fwrite(&_Sample_Set[i].y,    sizeof(double), 1, fp);
00702         fputc(0x2c, fp);
00703         fwrite(&_Sample_Set[i].t,    sizeof(double), 1, fp);
00704         fputc(0x3b, fp);
00705     }
00706     //  Save _C_x
00707     for(int i = 0; i < _Sample_Num - 1; i++) {
00708         for(int j = 0; j < 4; j++) {
00709             fwrite(&_C_x[j][i],    sizeof(double), 1, fp);
00710             fputc((j != 3)? 0x2c : 0x3b, fp);
00711         }
00712     }
00713     //  Save _C_y
00714     for(int i = 0; i < _Sample_Num - 1; i++) {
00715         for(int j = 0; j < 4; j++) {
00716             fwrite(&_C_y[j][i],    sizeof(double), 1, fp);
00717             fputc((j != 3)? 0x2c : 0x3b, fp);
00718         }
00719     }
00720 
00721     fclose(fp);
00722     free(filepath);
00723 }
00724 
00725 void CubicSpline2d::loadSetting()
00726 {
00727     FILE *fp;
00728     char tmp;
00729 
00730     //sprintf(filepath, "/local/%s", filename);
00731     //fp = fopen(filepath, "rb");
00732     fp = fopen("/local/savedata.log", "rb");
00733 
00734     //  Load _Sample_Num
00735     fread(&_Sample_Num, sizeof(unsigned int),  1, fp);
00736     fread(&tmp,         sizeof(char), 1, fp);
00737 
00738     //  Load _Sample_Set
00739     for(int i = 0; i < _Sample_Num; i++) {
00740         fread(&_Sample_Set[i].x, sizeof(double), 1, fp);
00741         fread(&tmp, sizeof(char),1,fp);
00742         fread(&_Sample_Set[i].y, sizeof(double), 1, fp);
00743         fread(&tmp, sizeof(char),1,fp);
00744         fread(&_Sample_Set[i].t, sizeof(double), 1, fp);
00745         fread(&tmp, sizeof(char),1,fp);
00746     }
00747 
00748     //  Load _C_x
00749     for(int i = 0; i < _Sample_Num - 1; i++) {
00750         for(int j = 0; j < 4; j++) {
00751             fread(&_C_x[j][i], sizeof(double), 1, fp);
00752             fread(&tmp, sizeof(char),1,fp);
00753         }
00754     }
00755     //  Load _C_y
00756     for(int i = 0; i < _Sample_Num - 1; i++) {
00757         for(int j = 0; j < 4; j++) {
00758             fread(&_C_y[j][i], sizeof(double), 1, fp);
00759             fread(&tmp, sizeof(char),1,fp);
00760         }
00761     }
00762     fclose(fp);
00763 }
00764 
00765 
00766 void CubicSpline2d::loadSetting(
00767     const char *filename
00768 )
00769 {
00770     FILE *fp;
00771     char *filepath;
00772     char tmp;
00773     int fnnum = 0;
00774 
00775     while (filename[fnnum] != 0) fnnum++;
00776     filepath = (char *)malloc((fnnum + 8) * sizeof(char)); // "/local/" are 7 char and \0 is 1 char.
00777 
00778     sprintf(filepath, "/local/%s", filename);
00779     fp = fopen(filepath, "rb");
00780 
00781     //  Load _Sample_Num
00782     fread(&_Sample_Num, sizeof(unsigned int),  1, fp);
00783     fread(&tmp,         sizeof(char), 1, fp);
00784 
00785     //  Load _Sample_Set
00786     for(int i = 0; i < _Sample_Num; i++) {
00787         fread(&_Sample_Set[i].x, sizeof(double), 1, fp);
00788         fread(&tmp, sizeof(char),1,fp);
00789         fread(&_Sample_Set[i].y, sizeof(double), 1, fp);
00790         fread(&tmp, sizeof(char),1,fp);
00791         fread(&_Sample_Set[i].t, sizeof(double), 1, fp);
00792         fread(&tmp, sizeof(char),1,fp);
00793     }
00794 
00795     //  Load _C_x
00796     for(int i = 0; i < _Sample_Num - 1; i++) {
00797         for(int j = 0; j < 4; j++) {
00798             fread(&_C_x[j][i], sizeof(double), 1, fp);
00799             fread(&tmp, sizeof(char),1,fp);
00800         }
00801     }
00802 
00803     //  Load _C_y
00804     for(int i = 0; i < _Sample_Num - 1; i++) {
00805         for(int j = 0; j < 4; j++) {
00806             fread(&_C_y[j][i], sizeof(double), 1, fp);
00807             fread(&tmp, sizeof(char),1,fp);
00808         }
00809     }
00810     fclose(fp);
00811     free(filepath);
00812 }
00813 
00814 void CubicSpline2d::printOutData()
00815 {
00816     FILE *fp;
00817     double x,y,t;
00818     double d = (_Sample_Set[_Sample_Num - 1].x - _Sample_Set[0].x) / 100.0;
00819 
00820     fp = fopen("/local/log.txt", "w");  // open file in writing mode
00821 
00822     fprintf(fp, "x, y, (t)\n");
00823     for(int ival = 0; ival < _Sample_Num - 1; ival++) {
00824         fprintf(fp, "ival: %d \n", ival);
00825         for(x = _Sample_Set[ival].x; x <= _Sample_Set[ival + 1].x; x += d) {
00826             y = getY(x);
00827             if(ival == 0)
00828                 t = sqrt((x - _Sample_Set[ival].x)*(x - _Sample_Set[ival].x) + (x - _Sample_Set[ival].y)*(x - _Sample_Set[ival].y));
00829             else
00830                 t = _Sample_Set[ival-1].t + sqrt((x - _Sample_Set[ival-1].x)*(x - _Sample_Set[ival-1].x) + (x - _Sample_Set[ival].y)*(x - _Sample_Set[ival].y));
00831             fprintf(fp, "%f,%f,(%f)\n", x, y, t);
00832         }
00833         fprintf(fp, "-----------------------------------------\n");
00834     }
00835 
00836     fprintf(fp, "\nSample:dst, vol\n");
00837     for(int i = 0; i < _Sample_Num; i++) {
00838         fprintf(fp, "%f,%f,(%f)\n", _Sample_Set[i].x, _Sample_Set[i].y, _Sample_Set[i].t);
00839     }
00840     fclose(fp);
00841 
00842 }
00843 void CubicSpline2d::_printOutData(const double *arg, const int num, const char* name)
00844 {
00845     FILE *fp;
00846 
00847     fp = fopen("/local/varlog.txt", "a");  // open file in add mode
00848     fprintf(fp, "%10s\n", name);
00849     for(int i = 0; i < num; i++) {
00850         fprintf(fp, "%.2f, ", arg[i]);
00851     }
00852     fprintf(fp, "\n");
00853     fclose(fp);
00854 }
00855 void CubicSpline2d::_printOutDataCouple(const double *arg1, const double *arg2, const int num, const char* name)
00856 {
00857     FILE *fp;
00858 
00859     fp = fopen("/local/varlog.txt", "a");  // open file in add mode
00860     fprintf(fp, "%10s\n", name);
00861     for(int i = 0; i < num; i++) {
00862         fprintf(fp, "(%.2f, %.2f)\n", arg1[i], arg2[i]);
00863     }
00864     fprintf(fp, "\n");
00865     fclose(fp);
00866 }
00867 void CubicSpline2d::_printOutData(const Vxyt *arg, int num, const char* name)
00868 {
00869     FILE *fp;
00870 
00871     fp = fopen("/local/varlog.txt", "a");  // open file in add mode
00872     fprintf(fp, "%10s\n", name);
00873     for(int i = 0; i < num; i++) {
00874         fprintf(fp, "%f, ", arg[i].y);
00875     }
00876     fprintf(fp, "\n");
00877     fclose(fp);
00878 }