51 using namespace mrpt::utils;
81 void BASE_IMPEXP medianFilter(
const std::vector<double> &inV, std::vector<double> &outV,
const int &winSize,
const int &numberOfSigmas = 2 );
83 #ifdef HAVE_LONG_DOUBLE
93 template<
typename T,
typename VECTOR>
94 void linspace(T first,T last,
size_t count, VECTOR &out_vector)
98 out_vector.assign(count,last);
103 out_vector.resize(count);
104 const T incr = (last-first)/T(count-1);
106 for (
size_t i=0;i<count;i++,c+=incr)
107 out_vector[i] = static_cast<typename VECTOR::value_type>(c);
114 inline Eigen::Matrix<T,Eigen::Dynamic,1>
linspace(T first,T last,
size_t count)
116 Eigen::Matrix<T,Eigen::Dynamic,1> ret;
122 template<
class T,T STEP>
123 inline Eigen::Matrix<T,Eigen::Dynamic,1>
sequence(T first,
size_t length)
125 Eigen::Matrix<T,Eigen::Dynamic,1> ret(length);
126 if (!length)
return ret;
128 while (length--) { ret[i++]=first; first+=STEP; }
133 template<
class T,T STEP>
136 std::vector<T> ret(length);
137 if (!length)
return ret;
139 while (length--) { ret[i++]=first; first+=STEP; }
144 template<
class T>
inline Eigen::Matrix<T,Eigen::Dynamic,1>
ones(
size_t count)
146 Eigen::Matrix<T,Eigen::Dynamic,1> v(count);
152 template<
class T>
inline Eigen::Matrix<T,Eigen::Dynamic,1>
zeros(
size_t count)
154 Eigen::Matrix<T,Eigen::Dynamic,1> v(count);
168 a = fmod(a, static_cast<T>(
M_2PI) );
169 if (was_neg) a+=
static_cast<T
>(
M_2PI);
207 template<
class VEC1,
class VEC2>
211 const size_t N = v.size();
212 for (
size_t i=0;i<N;i++)
214 total = std::sqrt(total);
217 out_v = v * (1.0/total);
219 else out_v.assign(v.size(),0);
232 template<
class VECTOR_OF_VECTORS,
class MATRIXLIKE,
class VECTORLIKE,
class VECTORLIKE2,
class VECTORLIKE3>
234 const VECTOR_OF_VECTORS &elements,
235 MATRIXLIKE &covariances,
237 const VECTORLIKE2 *weights_mean,
238 const VECTORLIKE3 *weights_cov,
239 const bool *elem_do_wrap2pi = NULL
242 ASSERTMSG_(elements.size()!=0,
"No samples provided, so there is no way to deduce the output size.")
244 const size_t DIM = elements[0].size();
246 covariances.setSize(DIM,DIM);
247 const size_t nElms=elements.size();
248 const T NORM=1.0/nElms;
249 if (weights_mean) {
ASSERTDEB_(
size_t(weights_mean->size())==
size_t(nElms)) }
251 for (
size_t i=0;i<DIM;i++)
254 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
258 for (
size_t j=0;j<nElms;j++)
259 accum+= (*weights_mean)[j] * elements[j][i];
263 for (
size_t j=0;j<nElms;j++) accum+=elements[j][i];
269 double accum_L=0,accum_R=0;
270 double Waccum_L=0,Waccum_R=0;
271 for (
size_t j=0;j<nElms;j++)
273 double ang = elements[j][i];
274 const double w = weights_mean!=NULL ? (*weights_mean)[j] : NORM;
275 if (fabs( ang )>0.5*
M_PI)
277 if (ang<0) ang = (
M_2PI + ang);
287 if (Waccum_L>0) accum_L /= Waccum_L;
288 if (Waccum_R>0) accum_R /= Waccum_R;
290 accum = (accum_L* Waccum_L + accum_R * Waccum_R );
295 for (
size_t i=0;i<DIM;i++)
296 for (
size_t j=0;j<=i;j++)
301 ASSERTDEB_(
size_t(weights_cov->size())==
size_t(nElms))
302 for (
size_t k=0;k<nElms;k++)
304 const T Ai = (elements[k][i]-means[i]);
305 const T Aj = (elements[k][j]-means[j]);
306 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
307 elem+= (*weights_cov)[k] * Ai * Aj;
313 for (
size_t k=0;k<nElms;k++)
315 const T Ai = (elements[k][i]-means[i]);
316 const T Aj = (elements[k][j]-means[j]);
317 if (!elem_do_wrap2pi || !elem_do_wrap2pi[i])
323 covariances.get_unsafe(i,j) = elem;
324 if (i!=j) covariances.get_unsafe(j,i)=elem;
335 template<
class VECTOR_OF_VECTORS,
class MATRIXLIKE,
class VECTORLIKE>
336 void covariancesAndMean(
const VECTOR_OF_VECTORS &elements,MATRIXLIKE &covariances,VECTORLIKE &means,
const bool *elem_do_wrap2pi = NULL)
338 covariancesAndMeanWeighted<VECTOR_OF_VECTORS,MATRIXLIKE,VECTORLIKE,vector_double,vector_double>(elements,covariances,means,NULL,NULL,elem_do_wrap2pi);
350 template<
class VECTORLIKE1,
class VECTORLIKE2>
352 const VECTORLIKE1 &values,
353 const VECTORLIKE1 &weights,
355 VECTORLIKE2 &out_binCenters,
356 VECTORLIKE2 &out_binValues )
361 ASSERT_( values.size() == weights.size() );
363 TNum minBin =
minimum( values );
364 unsigned int nBins =
static_cast<unsigned>(ceil((
maximum( values )-minBin) / binWidth));
367 out_binCenters.resize(nBins);
368 out_binValues.clear(); out_binValues.resize(nBins,0);
369 TNum halfBin = TNum(0.5)*binWidth;;
370 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
371 for (
unsigned int i=0;i<nBins;i++)
373 binBorders[i+1] = binBorders[i]+binWidth;
374 out_binCenters[i] = binBorders[i]+halfBin;
380 for (itVal = values.begin(), itW = weights.begin(); itVal!=values.end(); ++itVal, ++itW )
382 int idx =
round(((*itVal)-minBin)/binWidth);
383 if (idx>=
int(nBins)) idx=nBins-1;
385 out_binValues[idx] += *itW;
390 out_binValues /= totalSum;
404 template<
class VECTORLIKE1,
class VECTORLIKE2>
406 const VECTORLIKE1 &values,
407 const VECTORLIKE1 &log_weights,
409 VECTORLIKE2 &out_binCenters,
410 VECTORLIKE2 &out_binValues )
415 ASSERT_( values.size() == log_weights.size() );
417 TNum minBin =
minimum( values );
418 unsigned int nBins =
static_cast<unsigned>(ceil((
maximum( values )-minBin) / binWidth));
421 out_binCenters.resize(nBins);
422 out_binValues.clear(); out_binValues.resize(nBins,0);
423 TNum halfBin = TNum(0.5)*binWidth;;
424 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
425 for (
unsigned int i=0;i<nBins;i++)
427 binBorders[i+1] = binBorders[i]+binWidth;
428 out_binCenters[i] = binBorders[i]+halfBin;
432 const TNum max_log_weight =
maximum(log_weights);
435 for (itVal = values.begin(), itW = log_weights.begin(); itVal!=values.end(); ++itVal, ++itW )
437 int idx =
round(((*itVal)-minBin)/binWidth);
438 if (idx>=
int(nBins)) idx=nBins-1;
440 const TNum w = exp(*itW-max_log_weight);
441 out_binValues[idx] += w;
446 out_binValues /= totalSum;
458 template <
class VECTOR_OF_VECTORS,
class VECTORLIKE>
461 const size_t N = data.size();
462 out_column.resize(N);
463 for (
size_t i=0;i<N;i++)
464 out_column[i]=data[i][colIndex];
496 long double F = ::pow((
long double)10.0,-(
long double)power10);
507 if ((a1.getColCount()!=a2.getColCount())|(a1.getRowCount()!=a2.getRowCount()))
512 T syy=0, sxy=0, sxx=0, m1=0, m2=0 ,n=a1.getRowCount()*a2.getColCount();
515 for (i=0;i<a1.getRowCount();i++)
517 for (j=0;j<a1.getColCount();j++)
526 for (i=0;i<a1.getRowCount();i++)
528 for (j=0;j<a1.getColCount();j++)
538 return sxy / sqrt(sxx * syy);
579 const float &stdCount,
580 const std::string &style = std::string(
"b"),
581 const size_t &nEllipsePoints = 30 );
594 const float &stdCount,
595 const std::string &style = std::string(
"b"),
596 const size_t &nEllipsePoints = 30 );
603 template <
class MATRIXLIKE1,
class MATRIXLIKE2>
620 out_inverse_M.setSize(4,4);
623 out_inverse_M.set_unsafe(0,0, M.get_unsafe(0,0));
624 out_inverse_M.set_unsafe(0,1, M.get_unsafe(1,0));
625 out_inverse_M.set_unsafe(0,2, M.get_unsafe(2,0));
627 out_inverse_M.set_unsafe(1,0, M.get_unsafe(0,1));
628 out_inverse_M.set_unsafe(1,1, M.get_unsafe(1,1));
629 out_inverse_M.set_unsafe(1,2, M.get_unsafe(2,1));
631 out_inverse_M.set_unsafe(2,0, M.get_unsafe(0,2));
632 out_inverse_M.set_unsafe(2,1, M.get_unsafe(1,2));
633 out_inverse_M.set_unsafe(2,2, M.get_unsafe(2,2));
635 const double tx = -M.get_unsafe(0,3);
636 const double ty = -M.get_unsafe(1,3);
637 const double tz = -M.get_unsafe(2,3);
639 const double tx_ = tx*M.get_unsafe(0,0)+ty*M.get_unsafe(1,0)+tz*M.get_unsafe(2,0);
640 const double ty_ = tx*M.get_unsafe(0,1)+ty*M.get_unsafe(1,1)+tz*M.get_unsafe(2,1);
641 const double tz_ = tx*M.get_unsafe(0,2)+ty*M.get_unsafe(1,2)+tz*M.get_unsafe(2,2);
643 out_inverse_M.set_unsafe(0,3, tx_ );
644 out_inverse_M.set_unsafe(1,3, ty_ );
645 out_inverse_M.set_unsafe(2,3, tz_ );
647 out_inverse_M.set_unsafe(3,0, 0);
648 out_inverse_M.set_unsafe(3,1, 0);
649 out_inverse_M.set_unsafe(3,2, 0);
650 out_inverse_M.set_unsafe(3,3, 1);
655 template <
class IN_ROTMATRIX,
class IN_XYZ,
class OUT_ROTMATRIX,
class OUT_XYZ>
657 const IN_ROTMATRIX & in_R,
658 const IN_XYZ & in_xyz,
659 OUT_ROTMATRIX & out_R,
664 ASSERT_( in_R.isSquare() &&
size(in_R,1)==3 && in_xyz.size()==3)
670 const T tx = -in_xyz[0];
671 const T ty = -in_xyz[1];
672 const T tz = -in_xyz[2];
674 out_xyz[0] = tx*in_R.get_unsafe(0,0)+ty*in_R.get_unsafe(1,0)+tz*in_R.get_unsafe(2,0);
675 out_xyz[1] = tx*in_R.get_unsafe(0,1)+ty*in_R.get_unsafe(1,1)+tz*in_R.get_unsafe(2,1);
676 out_xyz[2] = tx*in_R.get_unsafe(0,2)+ty*in_R.get_unsafe(1,2)+tz*in_R.get_unsafe(2,2);
679 out_R = in_R.adjoint();
684 template <
class MATRIXLIKE>
689 const double tx = -M(0,3);
690 const double ty = -M(1,3);
691 const double tz = -M(2,3);
692 M(0,3) = tx*M(0,0)+ty*M(1,0)+tz*M(2,0);
693 M(1,3) = tx*M(0,1)+ty*M(1,1)+tz*M(2,1);
694 M(2,3) = tx*M(0,2)+ty*M(1,2)+tz*M(2,2);
696 std::swap( M(1,0),M(0,1) );
697 std::swap( M(2,0),M(0,2) );
698 std::swap( M(1,2),M(2,1) );
710 template <
class VECTORLIKE,
class VECTORLIKE2,
class VECTORLIKE3,
class MATRIXLIKE,
class USERPARAM >
713 void (*functor) (
const VECTORLIKE &x,
const USERPARAM &y, VECTORLIKE3 &out),
714 const VECTORLIKE2 &increments,
715 const USERPARAM &userParam,
716 MATRIXLIKE &out_Jacobian )
719 ASSERT_(x.size()>0 && increments.size() == x.size());
722 const size_t n = x.size();
724 for (
size_t j=0;j<n;j++) {
ASSERT_( increments[j]>0 ) }
726 VECTORLIKE3 f_minus, f_plus;
730 for (
size_t j=0;j<n;j++)
733 x_mod[j]=x[j]+increments[j];
734 functor(x_mod,userParam, f_plus);
736 x_mod[j]=x[j]-increments[j];
737 functor(x_mod,userParam, f_minus);
740 const double Ax_2_inv = 0.5/increments[j];
746 out_Jacobian.setSize(m,n);
749 for (
size_t i=0;i<m;i++)
750 out_Jacobian.get_unsafe(i,j) = Ax_2_inv* (f_plus[i]-f_minus[i]);
765 template <
typename T,
typename At,
size_t N>
766 std::vector<T>&
loadVector( std::vector<T> &v, At (&theArray)[N] )
770 for (
size_t i=0; i < N; i++)
771 v[i] = static_cast<T>(theArray[i]);
775 template <
typename Derived,
typename At,
size_t N>
776 Eigen::EigenBase<Derived>&
loadVector( Eigen::EigenBase<Derived> &v, At (&theArray)[N] )
779 v.derived().resize(N);
780 for (
size_t i=0; i < N; i++)
781 (v.derived())[i] = static_cast<typename Derived::Scalar>(theArray[i]);
799 template <
size_t N,
typename T>
810 for (
size_t i=0;i<N-1;i++)
811 ret.push_back( va_arg(args,T) );
829 template<
class VECTORLIKE1,
class VECTORLIKE2,
class MAT>
831 const VECTORLIKE1 &X,
832 const VECTORLIKE2 &MU,
836 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
838 ASSERT_( X.size()==MU.size() );
839 ASSERT_( X.size()==
size(COV,1) && COV.isSquare() );
841 const size_t N = X.size();
843 for (
size_t i=0;i<N;i++) X_MU[i]=X[i]-MU[i];
852 template<
class VECTORLIKE1,
class VECTORLIKE2,
class MAT>
854 const VECTORLIKE1 &X,
855 const VECTORLIKE2 &MU,
865 template<
class VECTORLIKE,
class MAT1,
class MAT2,
class MAT3>
868 const VECTORLIKE &mean_diffs,
871 const MAT3 &CROSS_COV12 )
874 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
875 ASSERT_( !mean_diffs.empty() );
877 ASSERT_( COV1.isSquare() && COV2.isSquare() );
880 const size_t N =
size(COV1,1);
883 COV.substract_An(CROSS_COV12,2);
885 COV.inv_fast(COV_inv);
895 const VECTORLIKE &mean_diffs,
898 const MAT3 &CROSS_COV12 )
906 template<
class VECTORLIKE,
class MATRIXLIKE>
911 ASSERTDEB_(cov.getColCount()==delta_mu.size())
918 template<
class VECTORLIKE,
class MATRIXLIKE>
928 template <
typename T>
930 const std::vector<T> &mean_diffs,
935 const size_t vector_dim = mean_diffs.size();
940 const T cov_det = C.det();
944 return std::pow(
M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))
945 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
951 template <
typename T,
size_t DIM>
953 const std::vector<T> &mean_diffs,
958 ASSERT_(mean_diffs.size()==DIM);
962 const T cov_det = C.det();
966 return std::pow(
M_2PI, -0.5*DIM ) * (1.0/std::sqrt( cov_det ))
967 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
973 template <
typename T,
class VECLIKE,
class MATLIKE1,
class MATLIKE2>
975 const VECLIKE &mean_diffs,
976 const MATLIKE1 &COV1,
977 const MATLIKE2 &COV2,
980 const MATLIKE1 *CROSS_COV12=NULL
983 const size_t vector_dim = mean_diffs.size();
988 if (CROSS_COV12) { C-=*CROSS_COV12; C-=*CROSS_COV12; }
989 const T cov_det = C.det();
993 maha2_out = mean_diffs.multiply_HCHt_scalar(C_inv);
994 intprod_out = std::pow(
M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))*exp(-0.5*maha2_out);
1000 template <
typename T,
class VECLIKE,
class MATRIXLIKE>
1002 const VECLIKE &diff_mean,
1003 const MATRIXLIKE &
cov,
1009 ASSERTDEB_(
size_t(cov.getColCount())==
size_t(diff_mean.size()))
1024 template <
typename T,
class VECLIKE,
class MATRIXLIKE>
1026 const VECLIKE &diff_mean,
1027 const MATRIXLIKE &
cov,
1032 pdf_out = std::exp(pdf_out);
1046 template <
class T,
class VECTOR>
1055 const size_t N = ys.size();
1056 if (x<=x0)
return ys[0];
1057 if (x>=x1)
return ys[N-1];
1058 const T Ax = (x1-x0)/T(N);
1059 const size_t i = int( (x-x0)/Ax );
1060 if (i>=N-1)
return ys[N-1];
1061 const T Ay = ys[i+1]-ys[i];
1062 return ys[i] + (x-(x0+i*Ax))*Ay/Ax;
1070 double BASE_IMPEXP interpolate2points(
const double x,
const double x0,
const double y0,
const double x1,
const double y1,
bool wrap2pi =
false);
1084 template <
typename NUMTYPE,
class VECTORLIKE>
1093 const size_t N = x.size();
1098 const NUM x_min = x.minimum();
1100 for (
size_t i=0;i<N;i++)
1102 Xt.set_unsafe(0,i, 1);
1103 Xt.set_unsafe(1,i, x[i]-x_min);
1107 XtX.multiply_AAt(Xt);
1110 XtX.inv_fast(XtXinv);
1113 XtXinvXt.multiply(XtXinv,Xt);
1116 XtXinvXt.multiply_Ab(y,B);
1120 NUM ret = B[0] + B[1]*(t-x_min);
1134 template <
class VECTORLIKE1,
class VECTORLIKE2,
class VECTORLIKE3>
1136 const VECTORLIKE1 &ts,
1138 const VECTORLIKE3 &x,
1139 const VECTORLIKE3 &y,
1140 bool wrap2pi =
false)
1148 const size_t N = x.size();
1152 const NUM x_min = x.minimum();
1154 for (
size_t i=0;i<N;i++)
1156 Xt.set_unsafe(0,i, 1);
1157 Xt.set_unsafe(1,i, x[i]-x_min);
1161 XtX.multiply_AAt(Xt);
1164 XtX.inv_fast(XtXinv);
1167 XtXinvXt.multiply(XtXinv,Xt);
1170 XtXinvXt.multiply_Ab(y,B);
1174 const size_t tsN =
size_t(ts.size());
1177 for (
size_t k=0;k<tsN;k++)
1178 outs[k] = B[0] + B[1]*(ts[k]-x_min);
1180 for (
size_t k=0;k<tsN;k++)