00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef MRPT_MATH_H
00029 #define MRPT_MATH_H
00030
00031 #include <mrpt/utils/utils_defs.h>
00032 #include <mrpt/math/CMatrixTemplateNumeric.h>
00033 #include <mrpt/math/CMatrixFixedNumeric.h>
00034 #include <mrpt/math/CHistogram.h>
00035
00036 #include <mrpt/math/ops_vectors.h>
00037 #include <mrpt/math/ops_matrices.h>
00038
00039 #include <numeric>
00040 #include <cmath>
00041
00042
00043
00044
00045 namespace mrpt
00046 {
00047
00048
00049 namespace math
00050 {
00051 using namespace mrpt::utils;
00052
00053
00054
00055
00056
00057
00058
00059
00060 bool BASE_IMPEXP loadVector( utils::CFileStream &f, std::vector<int> &d);
00061
00062
00063
00064
00065
00066 bool BASE_IMPEXP loadVector( utils::CFileStream &f, std::vector<double> &d);
00067
00068
00069
00070 bool BASE_IMPEXP isNaN(float f) MRPT_NO_THROWS;
00071
00072
00073 bool BASE_IMPEXP isNaN(double f) MRPT_NO_THROWS;
00074
00075
00076 bool BASE_IMPEXP isFinite(float f) MRPT_NO_THROWS;
00077
00078
00079 bool BASE_IMPEXP isFinite(double f) MRPT_NO_THROWS;
00080
00081 void BASE_IMPEXP medianFilter( const std::vector<double> &inV, std::vector<double> &outV, const int &winSize, const int &numberOfSigmas = 2 );
00082
00083 #ifdef HAVE_LONG_DOUBLE
00084
00085 bool BASE_IMPEXP isNaN(long double f) MRPT_NO_THROWS;
00086
00087
00088 bool BASE_IMPEXP isFinite(long double f) MRPT_NO_THROWS;
00089 #endif
00090
00091
00092
00093 template<typename T,typename VECTOR>
00094 void linspace(T first,T last, size_t count, VECTOR &out_vector)
00095 {
00096 if (count<2)
00097 {
00098 out_vector.assign(count,last);
00099 return;
00100 }
00101 else
00102 {
00103 out_vector.resize(count);
00104 const T incr = (last-first)/T(count-1);
00105 T c = first;
00106 for (size_t i=0;i<count;i++,c+=incr)
00107 out_vector[i] = static_cast<typename VECTOR::value_type>(c);
00108 }
00109 }
00110
00111
00112
00113 template<class T>
00114 inline Eigen::Matrix<T,Eigen::Dynamic,1> linspace(T first,T last, size_t count)
00115 {
00116 Eigen::Matrix<T,Eigen::Dynamic,1> ret;
00117 mrpt::math::linspace(first,last,count,ret);
00118 return ret;
00119 }
00120
00121
00122 template<class T,T STEP>
00123 inline Eigen::Matrix<T,Eigen::Dynamic,1> sequence(T first,size_t length)
00124 {
00125 Eigen::Matrix<T,Eigen::Dynamic,1> ret(length);
00126 if (!length) return ret;
00127 size_t i=0;
00128 while (length--) { ret[i++]=first; first+=STEP; }
00129 return ret;
00130 }
00131
00132
00133 template<class T,T STEP>
00134 inline std::vector<T> sequenceStdVec(T first,size_t length)
00135 {
00136 std::vector<T> ret(length);
00137 if (!length) return ret;
00138 size_t i=0;
00139 while (length--) { ret[i++]=first; first+=STEP; }
00140 return ret;
00141 }
00142
00143
00144 template<class T> inline Eigen::Matrix<T,Eigen::Dynamic,1> ones(size_t count)
00145 {
00146 Eigen::Matrix<T,Eigen::Dynamic,1> v(count);
00147 v.setOnes();
00148 return v;
00149 }
00150
00151
00152 template<class T> inline Eigen::Matrix<T,Eigen::Dynamic,1> zeros(size_t count)
00153 {
00154 Eigen::Matrix<T,Eigen::Dynamic,1> v(count);
00155 v.setZero();
00156 return v;
00157 }
00158
00159
00160
00161
00162
00163
00164 template <class T>
00165 inline void wrapTo2PiInPlace(T &a)
00166 {
00167 bool was_neg = a<0;
00168 a = fmod(a, static_cast<T>(M_2PI) );
00169 if (was_neg) a+=static_cast<T>(M_2PI);
00170 }
00171
00172
00173
00174
00175
00176 template <class T>
00177 inline T wrapTo2Pi(T a)
00178 {
00179 wrapTo2PiInPlace(a);
00180 return a;
00181 }
00182
00183
00184
00185
00186
00187 template <class T>
00188 inline T wrapToPi(T a)
00189 {
00190 return wrapTo2Pi( a + static_cast<T>(M_PI) )-static_cast<T>(M_PI);
00191 }
00192
00193
00194
00195
00196
00197 template <class T>
00198 inline void wrapToPiInPlace(T &a)
00199 {
00200 a = wrapToPi(a);
00201 }
00202
00203
00204
00205
00206
00207 template<class VEC1,class VEC2>
00208 void normalize(const VEC1 &v, VEC2 &out_v)
00209 {
00210 typename VEC1::value_type total=0;
00211 const size_t N = v.size();
00212 for (size_t i=0;i<N;i++)
00213 total += square(v[i]);
00214 total = std::sqrt(total);
00215 if (total)
00216 {
00217 out_v = v * (1.0/total);
00218 }
00219 else out_v.assign(v.size(),0);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 template<class VECTOR_OF_VECTORS, class MATRIXLIKE,class VECTORLIKE,class VECTORLIKE2,class VECTORLIKE3>
00233 inline void covariancesAndMeanWeighted(
00234 const VECTOR_OF_VECTORS &elements,
00235 MATRIXLIKE &covariances,
00236 VECTORLIKE &means,
00237 const VECTORLIKE2 *weights_mean,
00238 const VECTORLIKE3 *weights_cov,
00239 const bool *elem_do_wrap2pi = NULL
00240 )
00241 {
00242 ASSERTMSG_(elements.size()!=0,"No samples provided, so there is no way to deduce the output size.")
00243 typedef typename VECTORLIKE::value_type T;
00244 const size_t DIM = elements[0].size();
00245 means.resize(DIM);
00246 covariances.setSize(DIM,DIM);
00247 const size_t nElms=elements.size();
00248 const T NORM=1.0/nElms;
00249 if (weights_mean) { ASSERTDEB_(size_t(weights_mean->size())==size_t(nElms)) }
00250
00251 for (size_t i=0;i<DIM;i++)
00252 {
00253 T accum = 0;
00254 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
00255 {
00256 if (weights_mean)
00257 {
00258 for (size_t j=0;j<nElms;j++)
00259 accum+= (*weights_mean)[j] * elements[j][i];
00260 }
00261 else
00262 {
00263 for (size_t j=0;j<nElms;j++) accum+=elements[j][i];
00264 accum*=NORM;
00265 }
00266 }
00267 else
00268 {
00269 double accum_L=0,accum_R=0;
00270 double Waccum_L=0,Waccum_R=0;
00271 for (size_t j=0;j<nElms;j++)
00272 {
00273 double ang = elements[j][i];
00274 const double w = weights_mean!=NULL ? (*weights_mean)[j] : NORM;
00275 if (fabs( ang )>0.5*M_PI)
00276 {
00277 if (ang<0) ang = (M_2PI + ang);
00278 accum_L += ang * w;
00279 Waccum_L += w;
00280 }
00281 else
00282 {
00283 accum_R += ang * w;
00284 Waccum_R += w;
00285 }
00286 }
00287 if (Waccum_L>0) accum_L /= Waccum_L;
00288 if (Waccum_R>0) accum_R /= Waccum_R;
00289 if (accum_L>M_PI) accum_L -= M_2PI;
00290 accum = (accum_L* Waccum_L + accum_R * Waccum_R );
00291 }
00292 means[i]=accum;
00293 }
00294
00295 for (size_t i=0;i<DIM;i++)
00296 for (size_t j=0;j<=i;j++)
00297 {
00298 typename MATRIXLIKE::value_type elem=0;
00299 if (weights_cov)
00300 {
00301 ASSERTDEB_(size_t(weights_cov->size())==size_t(nElms))
00302 for (size_t k=0;k<nElms;k++)
00303 {
00304 const T Ai = (elements[k][i]-means[i]);
00305 const T Aj = (elements[k][j]-means[j]);
00306 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
00307 elem+= (*weights_cov)[k] * Ai * Aj;
00308 else elem+= (*weights_cov)[k] * mrpt::math::wrapToPi(Ai) * mrpt::math::wrapToPi(Aj);
00309 }
00310 }
00311 else
00312 {
00313 for (size_t k=0;k<nElms;k++)
00314 {
00315 const T Ai = (elements[k][i]-means[i]);
00316 const T Aj = (elements[k][j]-means[j]);
00317 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
00318 elem+= Ai * Aj;
00319 else elem+= mrpt::math::wrapToPi(Ai) * mrpt::math::wrapToPi(Aj);
00320 }
00321 elem*=NORM;
00322 }
00323 covariances.get_unsafe(i,j) = elem;
00324 if (i!=j) covariances.get_unsafe(j,i)=elem;
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335 template<class VECTOR_OF_VECTORS, class MATRIXLIKE,class VECTORLIKE>
00336 void covariancesAndMean(const VECTOR_OF_VECTORS &elements,MATRIXLIKE &covariances,VECTORLIKE &means, const bool *elem_do_wrap2pi = NULL)
00337 {
00338 covariancesAndMeanWeighted<VECTOR_OF_VECTORS,MATRIXLIKE,VECTORLIKE,vector_double,vector_double>(elements,covariances,means,NULL,NULL,elem_do_wrap2pi);
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 template<class VECTORLIKE1,class VECTORLIKE2>
00351 void weightedHistogram(
00352 const VECTORLIKE1 &values,
00353 const VECTORLIKE1 &weights,
00354 float binWidth,
00355 VECTORLIKE2 &out_binCenters,
00356 VECTORLIKE2 &out_binValues )
00357 {
00358 MRPT_START
00359 typedef typename VECTORLIKE1::value_type TNum;
00360
00361 ASSERT_( values.size() == weights.size() );
00362 ASSERT_( binWidth > 0 );
00363 TNum minBin = minimum( values );
00364 unsigned int nBins = static_cast<unsigned>(ceil((maximum( values )-minBin) / binWidth));
00365
00366
00367 out_binCenters.resize(nBins);
00368 out_binValues.clear(); out_binValues.resize(nBins,0);
00369 TNum halfBin = TNum(0.5)*binWidth;;
00370 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
00371 for (unsigned int i=0;i<nBins;i++)
00372 {
00373 binBorders[i+1] = binBorders[i]+binWidth;
00374 out_binCenters[i] = binBorders[i]+halfBin;
00375 }
00376
00377
00378 TNum totalSum = 0;
00379 typename VECTORLIKE1::const_iterator itVal, itW;
00380 for (itVal = values.begin(), itW = weights.begin(); itVal!=values.end(); ++itVal, ++itW )
00381 {
00382 int idx = round(((*itVal)-minBin)/binWidth);
00383 if (idx>=int(nBins)) idx=nBins-1;
00384 ASSERTDEB_(idx>=0);
00385 out_binValues[idx] += *itW;
00386 totalSum+= *itW;
00387 }
00388
00389 if (totalSum)
00390 out_binValues /= totalSum;
00391
00392
00393 MRPT_END
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 template<class VECTORLIKE1,class VECTORLIKE2>
00405 void weightedHistogramLog(
00406 const VECTORLIKE1 &values,
00407 const VECTORLIKE1 &log_weights,
00408 float binWidth,
00409 VECTORLIKE2 &out_binCenters,
00410 VECTORLIKE2 &out_binValues )
00411 {
00412 MRPT_START
00413 typedef typename VECTORLIKE1::value_type TNum;
00414
00415 ASSERT_( values.size() == log_weights.size() );
00416 ASSERT_( binWidth > 0 );
00417 TNum minBin = minimum( values );
00418 unsigned int nBins = static_cast<unsigned>(ceil((maximum( values )-minBin) / binWidth));
00419
00420
00421 out_binCenters.resize(nBins);
00422 out_binValues.clear(); out_binValues.resize(nBins,0);
00423 TNum halfBin = TNum(0.5)*binWidth;;
00424 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
00425 for (unsigned int i=0;i<nBins;i++)
00426 {
00427 binBorders[i+1] = binBorders[i]+binWidth;
00428 out_binCenters[i] = binBorders[i]+halfBin;
00429 }
00430
00431
00432 const TNum max_log_weight = maximum(log_weights);
00433 TNum totalSum = 0;
00434 typename VECTORLIKE1::const_iterator itVal, itW;
00435 for (itVal = values.begin(), itW = log_weights.begin(); itVal!=values.end(); ++itVal, ++itW )
00436 {
00437 int idx = round(((*itVal)-minBin)/binWidth);
00438 if (idx>=int(nBins)) idx=nBins-1;
00439 ASSERTDEB_(idx>=0);
00440 const TNum w = exp(*itW-max_log_weight);
00441 out_binValues[idx] += w;
00442 totalSum+= w;
00443 }
00444
00445 if (totalSum)
00446 out_binValues /= totalSum;
00447
00448 MRPT_END
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458 template <class VECTOR_OF_VECTORS, class VECTORLIKE>
00459 inline void extractColumnFromVectorOfVectors(const size_t colIndex, const VECTOR_OF_VECTORS &data, VECTORLIKE &out_column)
00460 {
00461 const size_t N = data.size();
00462 out_column.resize(N);
00463 for (size_t i=0;i<N;i++)
00464 out_column[i]=data[i][colIndex];
00465 }
00466
00467
00468
00469 uint64_t BASE_IMPEXP factorial64(unsigned int n);
00470
00471
00472
00473 double BASE_IMPEXP factorial(unsigned int n);
00474
00475
00476
00477 template <class T>
00478 T round2up(T val)
00479 {
00480 T n = 1;
00481 while (n < val)
00482 {
00483 n <<= 1;
00484 if (n<=1)
00485 THROW_EXCEPTION("Overflow!");
00486 }
00487 return n;
00488 }
00489
00490
00491
00492
00493 template <class T>
00494 T round_10power(T val, int power10)
00495 {
00496 long double F = ::pow((long double)10.0,-(long double)power10);
00497 long int t = round_long( val * F );
00498 return T(t/F);
00499 }
00500
00501
00502
00503
00504 template<class T>
00505 double correlate_matrix(const CMatrixTemplateNumeric<T> &a1, const CMatrixTemplateNumeric<T> &a2)
00506 {
00507 if ((a1.getColCount()!=a2.getColCount())|(a1.getRowCount()!=a2.getRowCount()))
00508 THROW_EXCEPTION("Correlation Error!, images with no same size");
00509
00510 int i,j;
00511 T x1,x2;
00512 T syy=0, sxy=0, sxx=0, m1=0, m2=0 ,n=a1.getRowCount()*a2.getColCount();
00513
00514
00515 for (i=0;i<a1.getRowCount();i++)
00516 {
00517 for (j=0;j<a1.getColCount();j++)
00518 {
00519 m1 += a1(i,j);
00520 m2 += a2(i,j);
00521 }
00522 }
00523 m1 /= n;
00524 m2 /= n;
00525
00526 for (i=0;i<a1.getRowCount();i++)
00527 {
00528 for (j=0;j<a1.getColCount();j++)
00529 {
00530 x1 = a1(i,j) - m1;
00531 x2 = a2(i,j) - m2;
00532 sxx += x1*x1;
00533 syy += x2*x2;
00534 sxy += x1*x2;
00535 }
00536 }
00537
00538 return sxy / sqrt(sxx * syy);
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 double BASE_IMPEXP averageLogLikelihood( const vector_double &logLikelihoods );
00550
00551
00552
00553
00554 double BASE_IMPEXP averageWrap2Pi(const vector_double &angles );
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 double BASE_IMPEXP averageLogLikelihood(
00565 const vector_double &logWeights,
00566 const vector_double &logLikelihoods );
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 std::string BASE_IMPEXP MATLAB_plotCovariance2D(
00577 const CMatrixFloat &cov22,
00578 const vector_float &mean,
00579 const float &stdCount,
00580 const std::string &style = std::string("b"),
00581 const size_t &nEllipsePoints = 30 );
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 std::string BASE_IMPEXP MATLAB_plotCovariance2D(
00592 const CMatrixDouble &cov22,
00593 const vector_double &mean,
00594 const float &stdCount,
00595 const std::string &style = std::string("b"),
00596 const size_t &nEllipsePoints = 30 );
00597
00598
00599
00600
00601
00602
00603 template <class MATRIXLIKE1,class MATRIXLIKE2>
00604 void homogeneousMatrixInverse(const MATRIXLIKE1 &M, MATRIXLIKE2 &out_inverse_M)
00605 {
00606 MRPT_START
00607 ASSERT_( M.isSquare() && size(M,1)==4);
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 out_inverse_M.setSize(4,4);
00621
00622
00623 out_inverse_M.set_unsafe(0,0, M.get_unsafe(0,0));
00624 out_inverse_M.set_unsafe(0,1, M.get_unsafe(1,0));
00625 out_inverse_M.set_unsafe(0,2, M.get_unsafe(2,0));
00626
00627 out_inverse_M.set_unsafe(1,0, M.get_unsafe(0,1));
00628 out_inverse_M.set_unsafe(1,1, M.get_unsafe(1,1));
00629 out_inverse_M.set_unsafe(1,2, M.get_unsafe(2,1));
00630
00631 out_inverse_M.set_unsafe(2,0, M.get_unsafe(0,2));
00632 out_inverse_M.set_unsafe(2,1, M.get_unsafe(1,2));
00633 out_inverse_M.set_unsafe(2,2, M.get_unsafe(2,2));
00634
00635 const double tx = -M.get_unsafe(0,3);
00636 const double ty = -M.get_unsafe(1,3);
00637 const double tz = -M.get_unsafe(2,3);
00638
00639 const double tx_ = tx*M.get_unsafe(0,0)+ty*M.get_unsafe(1,0)+tz*M.get_unsafe(2,0);
00640 const double ty_ = tx*M.get_unsafe(0,1)+ty*M.get_unsafe(1,1)+tz*M.get_unsafe(2,1);
00641 const double tz_ = tx*M.get_unsafe(0,2)+ty*M.get_unsafe(1,2)+tz*M.get_unsafe(2,2);
00642
00643 out_inverse_M.set_unsafe(0,3, tx_ );
00644 out_inverse_M.set_unsafe(1,3, ty_ );
00645 out_inverse_M.set_unsafe(2,3, tz_ );
00646
00647 out_inverse_M.set_unsafe(3,0, 0);
00648 out_inverse_M.set_unsafe(3,1, 0);
00649 out_inverse_M.set_unsafe(3,2, 0);
00650 out_inverse_M.set_unsafe(3,3, 1);
00651
00652 MRPT_END
00653 }
00654
00655 template <class IN_ROTMATRIX,class IN_XYZ, class OUT_ROTMATRIX, class OUT_XYZ>
00656 void homogeneousMatrixInverse(
00657 const IN_ROTMATRIX & in_R,
00658 const IN_XYZ & in_xyz,
00659 OUT_ROTMATRIX & out_R,
00660 OUT_XYZ & out_xyz
00661 )
00662 {
00663 MRPT_START
00664 ASSERT_( in_R.isSquare() && size(in_R,1)==3 && in_xyz.size()==3)
00665 out_R.setSize(3,3);
00666 out_xyz.resize(3);
00667
00668
00669 const double tx = -in_xyz[0];
00670 const double ty = -in_xyz[1];
00671 const double tz = -in_xyz[2];
00672
00673 out_xyz[0] = tx*in_R.get_unsafe(0,0)+ty*in_R.get_unsafe(1,0)+tz*in_R.get_unsafe(2,0);
00674 out_xyz[1] = tx*in_R.get_unsafe(0,1)+ty*in_R.get_unsafe(1,1)+tz*in_R.get_unsafe(2,1);
00675 out_xyz[2] = tx*in_R.get_unsafe(0,2)+ty*in_R.get_unsafe(1,2)+tz*in_R.get_unsafe(2,2);
00676
00677
00678 out_R = in_R.adjoint();
00679
00680 MRPT_END
00681 }
00682
00683 template <class MATRIXLIKE>
00684 inline void homogeneousMatrixInverse(MATRIXLIKE &M)
00685 {
00686 ASSERTDEB_( M.isSquare() && size(M,1)==4);
00687
00688 const double tx = -M(0,3);
00689 const double ty = -M(1,3);
00690 const double tz = -M(2,3);
00691 M(0,3) = tx*M(0,0)+ty*M(1,0)+tz*M(2,0);
00692 M(1,3) = tx*M(0,1)+ty*M(1,1)+tz*M(2,1);
00693 M(2,3) = tx*M(0,2)+ty*M(1,2)+tz*M(2,2);
00694
00695 std::swap( M(1,0),M(0,1) );
00696 std::swap( M(2,0),M(0,2) );
00697 std::swap( M(1,2),M(2,1) );
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 template <class VECTORLIKE,class VECTORLIKE2, class VECTORLIKE3, class MATRIXLIKE, class USERPARAM >
00710 void estimateJacobian(
00711 const VECTORLIKE &x,
00712 void (*functor) (const VECTORLIKE &x,const USERPARAM &y, VECTORLIKE3 &out),
00713 const VECTORLIKE2 &increments,
00714 const USERPARAM &userParam,
00715 MATRIXLIKE &out_Jacobian )
00716 {
00717 MRPT_START
00718 ASSERT_(x.size()>0 && increments.size() == x.size());
00719
00720 size_t m = 0;
00721 const size_t n = x.size();
00722
00723 for (size_t j=0;j<n;j++) { ASSERT_( increments[j]>0 ) }
00724
00725 VECTORLIKE3 f_minus, f_plus;
00726 VECTORLIKE x_mod(x);
00727
00728
00729 for (size_t j=0;j<n;j++)
00730 {
00731
00732 x_mod[j]=x[j]+increments[j];
00733 functor(x_mod,userParam, f_plus);
00734
00735 x_mod[j]=x[j]-increments[j];
00736 functor(x_mod,userParam, f_minus);
00737
00738 x_mod[j]=x[j];
00739 const double Ax_2_inv = 0.5/increments[j];
00740
00741
00742 if (j==0)
00743 {
00744 m = f_plus.size();
00745 out_Jacobian.setSize(m,n);
00746 }
00747
00748 for (size_t i=0;i<m;i++)
00749 out_Jacobian.get_unsafe(i,j) = Ax_2_inv* (f_plus[i]-f_minus[i]);
00750
00751 }
00752
00753 MRPT_END
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 template <typename T, typename At, size_t N>
00765 std::vector<T>& loadVector( std::vector<T> &v, At (&theArray)[N] )
00766 {
00767 MRPT_COMPILE_TIME_ASSERT(N!=0)
00768 v.resize(N);
00769 for (size_t i=0; i < N; i++)
00770 v[i] = static_cast<T>(theArray[i]);
00771 return v;
00772 }
00773
00774 template <typename Derived, typename At, size_t N>
00775 Eigen::EigenBase<Derived>& loadVector( Eigen::EigenBase<Derived> &v, At (&theArray)[N] )
00776 {
00777 MRPT_COMPILE_TIME_ASSERT(N!=0)
00778 v.derived().resize(N);
00779 for (size_t i=0; i < N; i++)
00780 (v.derived())[i] = static_cast<typename Derived::Scalar>(theArray[i]);
00781 return v;
00782 }
00783
00784
00785
00786
00787 void unwrap2PiSequence(vector_double &x);
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 template <size_t N, typename T>
00799 std::vector<T> make_vector(const T val1, ...)
00800 {
00801 MRPT_COMPILE_TIME_ASSERT( N>0 )
00802 std::vector<T> ret;
00803 ret.reserve(N);
00804
00805 ret.push_back(val1);
00806
00807 va_list args;
00808 va_start(args,val1);
00809 for (size_t i=0;i<N-1;i++)
00810 ret.push_back( va_arg(args,T) );
00811
00812 va_end(args);
00813 return ret;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 template<class VECTORLIKE1,class VECTORLIKE2,class MAT>
00829 typename VECTORLIKE1::value_type mahalanobisDistance2(
00830 const VECTORLIKE1 &X,
00831 const VECTORLIKE2 &MU,
00832 const MAT &COV )
00833 {
00834 MRPT_START
00835 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00836 ASSERT_( !X.empty() );
00837 ASSERT_( X.size()==MU.size() );
00838 ASSERT_( X.size()==size(COV,1) && COV.isSquare() );
00839 #endif
00840 const size_t N = X.size();
00841 mrpt::dynamicsize_vector<typename VECTORLIKE1::value_type> X_MU(N);
00842 for (size_t i=0;i<N;i++) X_MU[i]=X[i]-MU[i];
00843 return multiply_HCHt_scalar(X_MU, COV.inv() );
00844 MRPT_END
00845 }
00846
00847
00848
00849
00850
00851 template<class VECTORLIKE1,class VECTORLIKE2,class MAT>
00852 inline typename VECTORLIKE1::value_type mahalanobisDistance(
00853 const VECTORLIKE1 &X,
00854 const VECTORLIKE2 &MU,
00855 const MAT &COV )
00856 {
00857 return std::sqrt( mahalanobisDistance2(X,MU,COV) );
00858 }
00859
00860
00861
00862
00863
00864 template<class VECTORLIKE,class MAT1,class MAT2,class MAT3>
00865 typename VECTORLIKE::value_type
00866 mahalanobisDistance2(
00867 const VECTORLIKE &mean_diffs,
00868 const MAT1 &COV1,
00869 const MAT2 &COV2,
00870 const MAT3 &CROSS_COV12 )
00871 {
00872 MRPT_START
00873 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00874 ASSERT_( !mean_diffs.empty() );
00875 ASSERT_( mean_diffs.size()==size(COV1,1));
00876 ASSERT_( COV1.isSquare() && COV2.isSquare() );
00877 ASSERT_( size(COV1,1)==size(COV2,1));
00878 #endif
00879 const size_t N = size(COV1,1);
00880 MAT1 COV = COV1;
00881 COV+=COV2;
00882 COV.substract_An(CROSS_COV12,2);
00883 MAT1 COV_inv;
00884 COV.inv_fast(COV_inv);
00885 return multiply_HCHt_scalar(mean_diffs,COV_inv);
00886 MRPT_END
00887 }
00888
00889
00890
00891
00892 template<class VECTORLIKE,class MAT1,class MAT2,class MAT3> inline typename VECTORLIKE::value_type
00893 mahalanobisDistance(
00894 const VECTORLIKE &mean_diffs,
00895 const MAT1 &COV1,
00896 const MAT2 &COV2,
00897 const MAT3 &CROSS_COV12 )
00898 {
00899 return std::sqrt( mahalanobisDistance( mean_diffs, COV1,COV2,CROSS_COV12 ));
00900 }
00901
00902
00903
00904
00905 template<class VECTORLIKE,class MATRIXLIKE>
00906 inline typename MATRIXLIKE::value_type
00907 mahalanobisDistance2(const VECTORLIKE &delta_mu,const MATRIXLIKE &cov)
00908 {
00909 ASSERTDEB_(cov.isSquare())
00910 ASSERTDEB_(cov.getColCount()==delta_mu.size())
00911 return multiply_HCHt_scalar(delta_mu,cov.inverse());
00912 }
00913
00914
00915
00916
00917 template<class VECTORLIKE,class MATRIXLIKE>
00918 inline typename MATRIXLIKE::value_type
00919 mahalanobisDistance(const VECTORLIKE &delta_mu,const MATRIXLIKE &cov)
00920 {
00921 return std::sqrt(mahalanobisDistance2(delta_mu,cov));
00922 }
00923
00924
00925
00926
00927 template <typename T>
00928 T productIntegralTwoGaussians(
00929 const std::vector<T> &mean_diffs,
00930 const CMatrixTemplateNumeric<T> &COV1,
00931 const CMatrixTemplateNumeric<T> &COV2
00932 )
00933 {
00934 const size_t vector_dim = mean_diffs.size();
00935 ASSERT_(vector_dim>=1)
00936
00937 CMatrixTemplateNumeric<T> C = COV1;
00938 C+= COV2;
00939 const T cov_det = C.det();
00940 CMatrixTemplateNumeric<T> C_inv;
00941 C.inv_fast(C_inv);
00942
00943 return std::pow( M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))
00944 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
00945 }
00946
00947
00948
00949
00950 template <typename T, size_t DIM>
00951 T productIntegralTwoGaussians(
00952 const std::vector<T> &mean_diffs,
00953 const CMatrixFixedNumeric<T,DIM,DIM> &COV1,
00954 const CMatrixFixedNumeric<T,DIM,DIM> &COV2
00955 )
00956 {
00957 ASSERT_(mean_diffs.size()==DIM);
00958
00959 CMatrixFixedNumeric<T,DIM,DIM> C = COV1;
00960 C+= COV2;
00961 const T cov_det = C.det();
00962 CMatrixFixedNumeric<T,DIM,DIM> C_inv(UNINITIALIZED_MATRIX);
00963 C.inv_fast(C_inv);
00964
00965 return std::pow( M_2PI, -0.5*DIM ) * (1.0/std::sqrt( cov_det ))
00966 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
00967 }
00968
00969
00970
00971
00972 template <typename T, class VECLIKE,class MATLIKE1, class MATLIKE2>
00973 void productIntegralAndMahalanobisTwoGaussians(
00974 const VECLIKE &mean_diffs,
00975 const MATLIKE1 &COV1,
00976 const MATLIKE2 &COV2,
00977 T &maha2_out,
00978 T &intprod_out,
00979 const MATLIKE1 *CROSS_COV12=NULL
00980 )
00981 {
00982 const size_t vector_dim = mean_diffs.size();
00983 ASSERT_(vector_dim>=1)
00984
00985 MATLIKE1 C = COV1;
00986 C+= COV2;
00987 if (CROSS_COV12) { C-=*CROSS_COV12; C-=*CROSS_COV12; }
00988 const T cov_det = C.det();
00989 MATLIKE1 C_inv;
00990 C.inv_fast(C_inv);
00991
00992 maha2_out = mean_diffs.multiply_HCHt_scalar(C_inv);
00993 intprod_out = std::pow( M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))*exp(-0.5*maha2_out);
00994 }
00995
00996
00997
00998
00999 template <typename T, class VECLIKE,class MATRIXLIKE>
01000 void mahalanobisDistance2AndLogPDF(
01001 const VECLIKE &diff_mean,
01002 const MATRIXLIKE &cov,
01003 T &maha2_out,
01004 T &log_pdf_out)
01005 {
01006 MRPT_START
01007 ASSERTDEB_(cov.isSquare())
01008 ASSERTDEB_(size_t(cov.getColCount())==size_t(diff_mean.size()))
01009 MATRIXLIKE C_inv;
01010 cov.inv(C_inv);
01011 maha2_out = multiply_HCHt_scalar(diff_mean,C_inv);
01012 log_pdf_out = static_cast<typename MATRIXLIKE::value_type>(-0.5)* (
01013 maha2_out+
01014 static_cast<typename MATRIXLIKE::value_type>(cov.getColCount())*::log(static_cast<typename MATRIXLIKE::value_type>(M_2PI))+
01015 ::log(cov.det())
01016 );
01017 MRPT_END
01018 }
01019
01020
01021
01022
01023 template <typename T, class VECLIKE,class MATRIXLIKE>
01024 inline void mahalanobisDistance2AndPDF(
01025 const VECLIKE &diff_mean,
01026 const MATRIXLIKE &cov,
01027 T &maha2_out,
01028 T &pdf_out)
01029 {
01030 mahalanobisDistance2AndLogPDF(diff_mean,cov,maha2_out,pdf_out);
01031 pdf_out = std::exp(pdf_out);
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 template <class T,class VECTOR>
01046 T interpolate(
01047 const T &x,
01048 const VECTOR &ys,
01049 const T &x0,
01050 const T &x1 )
01051 {
01052 MRPT_START
01053 ASSERT_(x1>x0); ASSERT_(!ys.empty());
01054 const size_t N = ys.size();
01055 if (x<=x0) return ys[0];
01056 if (x>=x1) return ys[N-1];
01057 const T Ax = (x1-x0)/T(N);
01058 const size_t i = int( (x-x0)/Ax );
01059 if (i>=N-1) return ys[N-1];
01060 const T Ay = ys[i+1]-ys[i];
01061 return ys[i] + (x-(x0+i*Ax))*Ay/Ax;
01062 MRPT_END
01063 }
01064
01065
01066
01067
01068
01069 double BASE_IMPEXP interpolate2points(const double x, const double x0, const double y0, const double x1, const double y1, bool wrap2pi = false);
01070
01071
01072
01073
01074
01075 double BASE_IMPEXP spline(const double t, const vector_double &x, const vector_double &y, bool wrap2pi = false);
01076
01077
01078
01079
01080
01081
01082
01083 template <typename NUMTYPE,class VECTORLIKE>
01084 NUMTYPE leastSquareLinearFit(const NUMTYPE t, const VECTORLIKE &x, const VECTORLIKE &y, bool wrap2pi = false)
01085 {
01086 MRPT_START
01087
01088
01089 ASSERT_(x.size()==y.size());
01090 ASSERT_(x.size()>1);
01091
01092 const size_t N = x.size();
01093
01094 typedef typename VECTORLIKE::value_type NUM;
01095
01096
01097 const NUM x_min = x.minimum();
01098 CMatrixTemplateNumeric<NUM> Xt(2,N);
01099 for (size_t i=0;i<N;i++)
01100 {
01101 Xt.set_unsafe(0,i, 1);
01102 Xt.set_unsafe(1,i, x[i]-x_min);
01103 }
01104
01105 CMatrixTemplateNumeric<NUM> XtX;
01106 XtX.multiply_AAt(Xt);
01107
01108 CMatrixTemplateNumeric<NUM> XtXinv;
01109 XtX.inv_fast(XtXinv);
01110
01111 CMatrixTemplateNumeric<NUM> XtXinvXt;
01112 XtXinvXt.multiply(XtXinv,Xt);
01113
01114 VECTORLIKE B;
01115 XtXinvXt.multiply_Ab(y,B);
01116
01117 ASSERT_(B.size()==2)
01118
01119 NUM ret = B[0] + B[1]*(t-x_min);
01120
01121
01122 if (!wrap2pi)
01123 return ret;
01124 else return mrpt::math::wrapToPi(ret);
01125
01126 MRPT_END
01127 }
01128
01129
01130
01131
01132
01133 template <class VECTORLIKE1,class VECTORLIKE2,class VECTORLIKE3>
01134 void leastSquareLinearFit(
01135 const VECTORLIKE1 &ts,
01136 VECTORLIKE2 &outs,
01137 const VECTORLIKE3 &x,
01138 const VECTORLIKE3 &y,
01139 bool wrap2pi = false)
01140 {
01141 MRPT_START
01142
01143
01144 ASSERT_(x.size()==y.size());
01145 ASSERT_(x.size()>1);
01146
01147 const size_t N = x.size();
01148
01149
01150 typedef typename VECTORLIKE3::value_type NUM;
01151 const NUM x_min = x.minimum();
01152 CMatrixTemplateNumeric<NUM> Xt(2,N);
01153 for (size_t i=0;i<N;i++)
01154 {
01155 Xt.set_unsafe(0,i, 1);
01156 Xt.set_unsafe(1,i, x[i]-x_min);
01157 }
01158
01159 CMatrixTemplateNumeric<NUM> XtX;
01160 XtX.multiply_AAt(Xt);
01161
01162 CMatrixTemplateNumeric<NUM> XtXinv;
01163 XtX.inv_fast(XtXinv);
01164
01165 CMatrixTemplateNumeric<NUM> XtXinvXt;
01166 XtXinvXt.multiply(XtXinv,Xt);
01167
01168 VECTORLIKE3 B;
01169 XtXinvXt.multiply_Ab(y,B);
01170
01171 ASSERT_(B.size()==2)
01172
01173 const size_t tsN = size_t(ts.size());
01174 outs.resize(tsN);
01175 if (!wrap2pi)
01176 for (size_t k=0;k<tsN;k++)
01177 outs[k] = B[0] + B[1]*(ts[k]-x_min);
01178 else
01179 for (size_t k=0;k<tsN;k++)
01180 outs[k] = mrpt::math::wrapToPi( B[0] + B[1]*(ts[k]-x_min) );
01181 MRPT_END
01182 }
01183
01184
01185
01186 }
01187
01188 }
01189
01190 #endif