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;
72 <<
"p2 : " << p2 << endl
73 <<
"p1_c_p2_i_p2: " << p1_c_p2_i_p2 << endl;
76 <<
"p1 : " << p1 << endl
77 <<
"p2 : " << p2 << endl
79 <<
"p1_i_p2 : " << p1_i_p2 << 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);
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(
TEST_F(Pose3DTests, DefaultValues)
void test_ExpLnEqual(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
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_compose_point_se3(const CArrayDouble< 6 > &x, const CArrayDouble< 3 > &P, CArrayDouble< 3 > &Y)
void test_invComposePointJacob(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x, double y, double z)
void test_composePointJacob_se3(const CPose3D &p, const TPoint3D x_l)
static void func_jacob_Aexpe_D(const CArrayDouble< 6 > &eps, const TParams_func_jacob_Aexpe_D ¶ms, CArrayDouble< 12 > &Y)
void test_default_values(const CPose3D &p, const std::string &label)
void test_composePoint(double x1, double y1, double z1, double yaw1, double pitch1, double roll1, double x, double y, double z)
static void func_jacob_expe_D(const CArrayDouble< 6 > &eps, const CPose3D &D, CArrayDouble< 12 > &Y)
static void func_inv_compose_point(const CArrayDouble< 6+3 > &x, const double &dummy, CArrayDouble< 3 > &Y)
static void func_jacob_LnT_T(const CArrayDouble< 12 > &x, const double &dummy, CArrayDouble< 6 > &Y)
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)
void check_jacob_LnT_T(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
void test_to_from_2d(double x, double y, double phi)
static void func_compose_point(const CArrayDouble< 6+3 > &x, const double &dummy, CArrayDouble< 3 > &Y)
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)
void test_inverse(double x1, double y1, double z1, double yaw1, double pitch1, double roll1)
void check_jacob_expe_e_at_0()
static void func_jacob_expe_e(const CArrayDouble< 6 > &x, const double &dummy, 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)
void test_invComposePointJacob_se3(const CPose3D &p, const TPoint3D x_g)
static void func_invcompose_point_se3(const CArrayDouble< 6 > &x, const CArrayDouble< 3 > &P, CArrayDouble< 3 > &Y)
A partial specialization of CArrayNumeric for double numbers.
A numeric matrix of compile-time fixed size.
A class used to store a 3D point.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
const double & phi() const
Get the phi angle of the 2D pose (in radians)
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
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.
mrpt::math::CMatrixDouble44 getHomogeneousMatrixVal() const
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).
void inverse()
Convert this pose into its inverse, saving the result in itself.
double yaw() const
Get the YAW angle (in radians)
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...
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...
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 ...
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 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...
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 .
double x() const
Common members of all points & poses classes.
void getInverseHomogeneousMatrix(mrpt::math::CMatrixDouble44 &out_HM) const
Returns the corresponding 4x4 inverse homogeneous transformation matrix for this point or pose.
mrpt::math::CVectorDouble getAsVectorVal() const
Return the pose or point as a 1xN vector with all the components (see derived classes for each implem...
GLenum const GLfloat * params
GLsizei const GLchar ** string
GLdouble GLdouble GLdouble GLdouble q
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
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...
This base provides a set of functions for maths stuff.
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
double z
X,Y,Z coordinates.