12 #include <gtest/gtest.h> 28 void test_inverse(
double x1,
double y1,
double z1,
double yaw1,
double pitch1,
double roll1)
30 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
37 EXPECT_NEAR( (HM*HMi-I4).array().abs().
sum(), 0, 1e-3 ) <<
39 "inv(HM):\n" << HMi <<
40 "inv(HM)*HM:\n" << HM*HMi << endl;
51 "p1_inv_inv: " << p1_inv_inv << endl;
53 EXPECT_NEAR((HMi_from_p1_inv-HMi).array().abs().
sum(),0, 1e-4)
54 <<
"HMi_from_p1_inv:\n" << HMi_from_p1_inv
55 <<
"HMi:\n" << HMi << endl;
59 void test_compose(
double x1,
double y1,
double z1,
double yaw1,
double pitch1,
double roll1,
60 double x2,
double y2,
double z2,
double yaw2,
double pitch2,
double roll2 )
62 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
63 const CPose3D p2(x2,y2,z2,yaw2,pitch2,roll2);
65 const CPose3D p1_c_p2 = p1 + p2;
66 const CPose3D p1_i_p2 = p1 - p2;
68 const CPose3D p1_c_p2_i_p2 = p1_c_p2 - p1;
69 const CPose3D p2_c_p1_i_p2 = p2 + p1_i_p2;
71 EXPECT_NEAR(0, (p1_c_p2_i_p2.
getAsVectorVal()-p2.getAsVectorVal()).array().abs().sum(), 1e-5)
72 <<
"p2 : " << p2 << endl
73 <<
"p1_c_p2_i_p2: " << p1_c_p2_i_p2 << endl;
75 EXPECT_NEAR(0, (p2_c_p1_i_p2.
getAsVectorVal()-p1.getAsVectorVal()).array().abs().sum(), 1e-5)
76 <<
"p1 : " << p1 << endl
77 <<
"p2 : " << p2 << endl
79 <<
"p1_i_p2 : " << p1_i_p2 << endl
80 <<
"p1_i_p2 matrix: " << endl << p1_i_p2.getHomogeneousMatrixVal() << endl
81 <<
"p2_c_p1_i_p2: " << p2_c_p1_i_p2 << endl;
110 EXPECT_FLOAT_EQ( p2d.
x(), p2d_bis.
x() ) <<
"p2d: " << p2d << endl;
111 EXPECT_FLOAT_EQ( p2d.
y(), p2d_bis.
y() ) <<
"p2d: " << p2d << endl;
112 EXPECT_FLOAT_EQ( p2d.
phi(), p2d_bis.
phi() ) <<
"p2d: " << p2d << endl;
114 EXPECT_FLOAT_EQ( p2d.
phi(), p3d.
yaw() ) <<
"p2d: " << p2d << endl;
117 void test_composeFrom(
double x1,
double y1,
double z1,
double yaw1,
double pitch1,
double roll1,
118 double x2,
double y2,
double z2,
double yaw2,
double pitch2,
double roll2 )
120 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
121 const CPose3D p2(x2,y2,z2,yaw2,pitch2,roll2);
123 const CPose3D p1_plus_p2 = p1 + p2;
130 <<
"p2 : " << p2 << endl
131 <<
"p1 : " << p1 << endl
132 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
133 <<
"p1_plus_p2bis : " << p1_plus_p2bis<< endl;
141 <<
"p2 : " << p2 << endl
142 <<
"p1 : " << p1 << endl
143 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
144 <<
"p1_plus_p2bis : " << p1_plus_p2bis<< endl;
152 <<
"p2 : " << p2 << endl
153 <<
"p1 : " << p1 << endl
154 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
155 <<
"p1_plus_p2bis : " << p1_plus_p2bis<< endl;
160 double x,
double y,
double z)
162 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
167 p1.
composePoint(
p.x(),
p.y(),
p.z() ,p1_plus_p2.
x(), p1_plus_p2.
y(), p1_plus_p2.z());
178 EXPECT_NEAR(0, std::abs(
x-p1_plus_p.
x())+std::abs(
y-p1_plus_p.
y())+std::abs(
z-p1_plus_p.z()) , 1e-5);
184 p1.inverseComposePoint(p1_plus_p.
x(),p1_plus_p.
y(),p1_plus_p.z(), p_recov2.
x(),p_recov2.
y(),p_recov2.z() );
188 EXPECT_NEAR(0, (
p.getAsVectorVal()-p_recov.
getAsVectorVal()).array().abs().sum(), 1e-5);
197 for (
int i=0;i<3;i++) Y[i]=pp[i];
212 double x,
double y,
double z,
bool use_aprox =
false)
214 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
228 for (
int i=0;i<6;i++) x_mean[i]=p1[i];
235 x_incrs.assign(1e-7);
239 numJacobs.extractMatrix(0,0, num_df_dpose);
240 numJacobs.extractMatrix(0,6, num_df_dpoint);
243 const double max_eror = use_aprox ? 0.1 : 3e-3;
245 EXPECT_NEAR(0, (df_dpoint-num_df_dpoint).array().abs().
sum(), max_eror )
246 <<
"p1: " << p1 << endl
247 <<
"p: " <<
p << endl
248 <<
"Numeric approximation of df_dpoint: " << endl << num_df_dpoint << endl
249 <<
"Implemented method: " << endl << df_dpoint << endl
250 <<
"Error: " << endl << df_dpoint-num_df_dpoint << endl;
252 EXPECT_NEAR(0, (df_dpose-num_df_dpose).array().abs().
sum(), max_eror )
253 <<
"p1: " << p1 << endl
254 <<
"p: " <<
p << endl
255 <<
"Numeric approximation of df_dpose: " << endl << num_df_dpose << endl
256 <<
"Implemented method: " << endl << df_dpose << endl
257 <<
"Error: " << endl << df_dpose-num_df_dpose << endl;
261 void test_ExpLnEqual(
double x1,
double y1,
double z1,
double yaw1,
double pitch1,
double roll1)
263 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
271 double x,
double y,
double z)
273 const CPose3D p1(x1,y1,z1,yaw1,pitch1,roll1);
287 for (
int i=0;i<6;i++) x_mean[i]=p1[i];
294 x_incrs.assign(1e-7);
298 numJacobs.extractMatrix(0,0, num_df_dpose);
299 numJacobs.extractMatrix(0,6, num_df_dpoint);
302 EXPECT_NEAR(0, (df_dpoint-num_df_dpoint).array().abs().
sum(), 3e-3 )
303 <<
"p1: " << p1 << endl
304 <<
"p: " <<
p << endl
305 <<
"Numeric approximation of df_dpoint: " << endl << num_df_dpoint << endl
306 <<
"Implemented method: " << endl << df_dpoint << endl
307 <<
"Error: " << endl << df_dpoint-num_df_dpoint << endl;
309 EXPECT_NEAR(0, (df_dpose-num_df_dpose).array().abs().
sum(), 3e-3 )
310 <<
"p1: " << p1 << endl
311 <<
"p: " <<
p << endl
312 <<
"Numeric approximation of df_dpose: " << endl << num_df_dpose << endl
313 <<
"Implemented method: " << endl << df_dpose << endl
314 <<
"Error: " << endl << df_dpose-num_df_dpose << endl;
323 EXPECT_EQ(
p.yaw(),0);
324 EXPECT_EQ(
p.pitch(),0);
325 EXPECT_EQ(
p.roll(),0);
326 for (
size_t i=0;i<4;i++)
327 for (
size_t j=0;j<4;j++)
328 EXPECT_NEAR(
p.getHomogeneousMatrixVal()(i,j), i==j ? 1.0 : 0.0, 1e-8 )
329 <<
"Failed for (i,j)=" << i <<
"," << j << endl
330 <<
"Matrix is: " << endl <<
p.getHomogeneousMatrixVal() << endl
331 <<
"case was: " << label << endl;
339 for (
int i=0;i<3;i++) Y[i]=pp[i];
347 for (
int i=0;i<3;i++) Y[i]=pp[i];
356 p.composePoint(x_l.
x,x_l.
y,x_l.
z, pp.
x,pp.
y,pp.
z, NULL, NULL, &df_dse3);
362 for (
int i=0;i<6;i++) x_mean[i]=0;
365 for (
int i=0;i<3;i++) P[i]=pp[i];
368 x_incrs.assign(1e-9);
372 EXPECT_NEAR(0, (df_dse3-num_df_dse3).array().abs().
sum(), 3e-3 )
373 <<
"p: " <<
p << endl
374 <<
"x_l: " << x_l << endl
375 <<
"Numeric approximation of df_dse3: " << endl <<num_df_dse3 << endl
376 <<
"Implemented method: " << endl << df_dse3 << endl
377 <<
"Error: " << endl << df_dse3-num_df_dse3 << endl;
385 p.inverseComposePoint(x_g.
x,x_g.
y,x_g.
z, pp.
x,pp.
y,pp.
z, NULL, NULL, &df_dse3 );
391 for (
int i=0;i<6;i++) x_mean[i]=0;
394 for (
int i=0;i<3;i++) P[i]=pp[i];
397 x_incrs.assign(1e-9);
401 EXPECT_NEAR(0, (df_dse3-num_df_dse3).array().abs().
sum(), 3e-3 )
402 <<
"p: " <<
p << endl
403 <<
"x_g: " << x_g << endl
404 <<
"Numeric approximation of df_dse3: " << endl <<num_df_dse3 << endl
405 <<
"Implemented method: " << endl << df_dse3 << endl
406 <<
"Error: " << endl << df_dse3-num_df_dse3 << endl;
423 for (
int i=0;i<6;i++) x_mean[i]=0;
427 x_incrs.assign(1e-9);
436 double vals[12*6] = {
455 EXPECT_NEAR( (numJacobs-M).array().abs().maxCoeff(), 0, 1e-5) <<
"M:\n" << M <<
"numJacobs:\n" << numJacobs <<
"\n";
464 p.setFrom12Vector(
x);
471 const CPose3D p(x1,y1,z1,yaw1,pitch1,roll1);
474 p.ln_jacob(theor_jacob);
479 p.getAs12Vector(x_mean);
483 x_incrs.assign(1e-6);
487 EXPECT_NEAR( (numJacobs-theor_jacob).array().abs().
sum(), 0, 1e-3)
488 <<
"Pose: " <<
p << endl
489 <<
"Pose matrix:\n" <<
p.getHomogeneousMatrixVal()
490 <<
"Num. Jacob:\n" << numJacobs << endl
491 <<
"Theor. Jacob:\n" << theor_jacob << endl
492 <<
"ERR:\n" << theor_jacob-numJacobs << endl;
503 const CPose3D expe_D = incr + D;
512 const CPose3D p(x1,y1,z1,yaw1,pitch1,roll1);
514 Eigen::Matrix<double,12,6> theor_jacob;
523 x_incrs.assign(1e-6);
527 EXPECT_NEAR( (numJacobs-theor_jacob).array().abs().maxCoeff(), 0, 1e-3)
528 <<
"Pose: " <<
p << endl
529 <<
"Pose matrix:\n" <<
p.getHomogeneousMatrixVal()
530 <<
"Num. Jacob:\n" << numJacobs << endl
531 <<
"Theor. Jacob:\n" << theor_jacob << endl
532 <<
"ERR:\n" << theor_jacob-numJacobs << endl;
556 double x1,
double y1,
double z1,
double yaw1,
double pitch1,
double roll1,
557 double x2,
double y2,
double z2,
double yaw2,
double pitch2,
double roll2)
559 const CPose3D A(x1,y1,z1,yaw1,pitch1,roll1);
560 const CPose3D D(x2,y2,z2,yaw2,pitch2,roll2);
562 Eigen::Matrix<double,12,6> theor_jacob;
574 x_incrs.assign(1e-6);
578 EXPECT_NEAR( (numJacobs-theor_jacob).array().abs().maxCoeff(), 0, 1e-3)
579 <<
"Pose A: " << A << endl
580 <<
"Pose D: " << D << endl
581 <<
"Num. Jacob:\n" << numJacobs << endl
582 <<
"Theor. Jacob:\n" << theor_jacob << endl
583 <<
"ERR:\n" << theor_jacob-numJacobs << endl;
594 test_default_values(
p,
"Default");
599 test_default_values(
p,
"p=p2");
603 test_default_values(p1+p2,
"p1+p2");
605 test_default_values(
p,
"p=p1+p2");
610 test_default_values(
p,
"p1-p2");
617 EXPECT_NEAR(
p.x(),1, 1e-7);
618 EXPECT_NEAR(
p.y(),2, 1e-7);
619 EXPECT_NEAR(
p.z(),3, 1e-7);
620 EXPECT_NEAR(
p.yaw(),0.2, 1e-7);
621 EXPECT_NEAR(
p.pitch(),0.3, 1e-7);
622 EXPECT_NEAR(
p.roll(),0.4, 1e-7);
628 EXPECT_NEAR(
p[0],1, 1e-7);
629 EXPECT_NEAR(
p[1],2, 1e-7);
630 EXPECT_NEAR(
p[2],3, 1e-7);
631 EXPECT_NEAR(
p[3],0.2, 1e-7);
632 EXPECT_NEAR(
p[4],0.3, 1e-7);
633 EXPECT_NEAR(
p[5],0.4, 1e-7);
639 { .0, .0, .0, .0, .0, .0 },
640 { 1.0, 2.0, 3.0, .0, .0, .0 },
641 { 1.0, 2.0, 3.0, 10.0, .0, .0 },
642 { 1.0, 2.0, 3.0, .0, 1.0, .0 },
643 { 1.0, 2.0, 3.0, .0, .0, 1.0 },
644 { 1.0, 2.0, 3.0, 80.0, 5.0, 5.0 },
645 { 1.0, 2.0, 3.0,-20.0,-30.0,-40.0 },
646 { 1.0, 2.0, 3.0,-45.0, 10.0, 70.0 },
647 { 1.0, 2.0, 3.0, 40.0, -5.0, 25.0 },
648 { 1.0, 2.0, 3.0, 40.0, 20.0,-15.0 },
649 {-6.0, 2.0, 3.0, 40.0, 20.0, 15.0 },
650 { 6.0, -5.0, 3.0, 40.0, 20.0, 15.0 },
651 { 6.0, 2.0, -9.0, 40.0, 20.0, 15.0 },
652 { 0.0, 8.0, 5.0,-45.0, 10.0, 70.0 },
653 { 1.0, 0.0, 5.0,-45.0, 10.0, 70.0 },
654 { 1.0, 8.0, 0.0,-45.0, 10.0, 70.0 }
755 check_jacob_expe_e_at_0();
778 test_Jacob_dAexpeD_de(
double x() const
Common members of all points & poses classes.
TEST_F(Pose3DTests, DefaultValues)
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
static void func_jacob_expe_D(const CArrayDouble< 6 > &eps, const CPose3D &D, CArrayDouble< 12 > &Y)
void test_composeFrom(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x2, double y2, double z2, double yaw2, double pitch2, double roll2)
void test_Jacob_dexpeD_de(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
mrpt::math::CVectorDouble getAsVectorVal() const
Return the pose or point as a 1xN vector with all the components (see derived classes for each implem...
void test_invComposePointJacob_se3(const CPose3D &p, const TPoint3D x_g)
void test_Jacob_dAexpeD_de(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x2, double y2, double z2, double yaw2, double pitch2, double roll2)
GLdouble GLdouble GLdouble GLdouble q
void test_composePointJacob_se3(const CPose3D &p, const TPoint3D x_l)
double yaw() const
Get the YAW angle (in radians)
double z
X,Y,Z coordinates.
void test_ExpLnEqual(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
void inverse()
Convert this pose into its inverse, saving the result in itself.
void test_to_from_2d(double x, double y, double phi)
void test_composePoint(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x, double y, double z)
void check_jacob_expe_e_at_0()
static void jacob_dexpeD_de(const CPose3D &D, Eigen::Matrix< double, 12, 6 > &jacob)
The Jacobian d (e^eps * D) / d eps , with eps=increment in Lie Algebra.
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=NULL, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
void composeFrom(const CPose3D &A, const CPose3D &B)
Makes "this = A (+) B"; this method is slightly more efficient than "this= A + B;" since it avoids th...
mrpt::math::CMatrixDouble44 getHomogeneousMatrixVal() const
void test_invComposePointJacob(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x, double y, double z)
void getInverseHomogeneousMatrix(mrpt::math::CMatrixDouble44 &out_HM) const
Returns the corresponding 4x4 inverse homogeneous transformation matrix for this point or pose...
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
static void func_compose_point(const CArrayDouble< 6+3 > &x, const double &dummy, CArrayDouble< 3 > &Y)
GLsizei const GLchar ** string
static void func_compose_point_se3(const CArrayDouble< 6 > &x, const CArrayDouble< 3 > &P, CArrayDouble< 3 > &Y)
A class used to store a 3D point.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
static void func_inv_compose_point(const CArrayDouble< 6+3 > &x, const double &dummy, CArrayDouble< 3 > &Y)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void inverseComposePoint(const double gx, const double gy, const double gz, double &lx, double &ly, double &lz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=NULL) const
Computes the 3D point L such as .
static void func_jacob_LnT_T(const CArrayDouble< 12 > &x, const double &dummy, CArrayDouble< 6 > &Y)
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
const double & phi() const
Get the phi angle of the 2D pose (in radians)
A partial specialization of CArrayNumeric for double numbers.
static void func_jacob_Aexpe_D(const CArrayDouble< 6 > &eps, const TParams_func_jacob_Aexpe_D ¶ms, CArrayDouble< 12 > &Y)
void jacob_numeric_estimate(const VECTORLIKE &x, void(*functor)(const VECTORLIKE &x, const USERPARAM &y, VECTORLIKE3 &out), const VECTORLIKE2 &increments, const USERPARAM &userParam, MATRIXLIKE &out_Jacobian)
Numerical estimation of the Jacobian of a user-supplied function - this template redirects to mrpt::m...
void check_jacob_LnT_T(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
static void func_jacob_expe_e(const CArrayDouble< 6 > &x, const double &dummy, CArrayDouble< 12 > &Y)
void test_compose(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x2, double y2, double z2, double yaw2, double pitch2, double roll2)
static void func_invcompose_point_se3(const CArrayDouble< 6 > &x, const CArrayDouble< 3 > &P, CArrayDouble< 3 > &Y)
void getAs12Vector(ARRAYORVECTOR &vec12) const
Get the pose representation as an array with these 12 elements: [r11 r21 r31 r12 r22 r32 r13 r23 r33 ...
void ln(mrpt::math::CArrayDouble< 6 > &out_ln) const
Take the logarithm of the 3x4 matrix defined by this pose, generating the corresponding vector in the...
static CPose3D exp(const mrpt::math::CArrayNumeric< double, 6 > &vect, bool pseudo_exponential=false)
Exponentiate a Vector in the SE(3) Lie Algebra to generate a new CPose3D (static method).
GLenum const GLfloat * params
void test_inverse(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
static void jacob_dAexpeD_de(const CPose3D &A, const CPose3D &D, Eigen::Matrix< double, 12, 6 > &jacob)
The Jacobian d (A * e^eps * D) / d eps , with eps=increment in Lie Algebra.
void test_default_values(const CPose3D &p, const std::string &label)
void test_composePointJacob(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x, double y, double z, bool use_aprox=false)