10 #include <CTraitsTest.h> 11 #include <gtest/gtest.h> 17 #include <Eigen/Dense> 24 template class mrpt::CTraitsTest<CPose3D>;
37 auto I4 = CMatrixDouble44::Identity();
40 (HM.asEigen() * HMi.asEigen() - I4.asEigen()).array().abs().sum(),
44 << HMi <<
"inv(HM)*HM:\n" 45 << (HM * HMi) << endl;
50 const auto HMi_from_p1_inv =
62 <<
"p1: " << p1 <<
"p1_inv_inv: " << p1_inv_inv << endl;
64 EXPECT_NEAR((HMi_from_p1_inv - HMi).sum_abs(), 0, 1e-4)
65 <<
"HMi_from_p1_inv:\n" 66 << HMi_from_p1_inv <<
"HMi:\n" 72 const CPose3D p1_c_p2 = p1 + p2;
73 const CPose3D p1_i_p2 = p1 - p2;
75 const CPose3D p1_c_p2_i_p2 = p1_c_p2 - p1;
76 const CPose3D p2_c_p1_i_p2 = p2 + p1_i_p2;
86 <<
"p2 : " << p2 << endl
87 <<
"p1_c_p2_i_p2: " << p1_c_p2_i_p2 << endl;
97 <<
"p1 : " << p1 << endl
98 <<
"p2 : " << p2 << endl
99 <<
"p2 matrix : " << endl
101 <<
"p1_i_p2 : " << p1_i_p2 << endl
102 <<
"p1_i_p2 matrix: " << endl
104 <<
"p2_c_p1_i_p2: " << p2_c_p1_i_p2 << endl;
154 EXPECT_DOUBLE_EQ(p2d.
x(), p2d_bis.
x()) <<
"p2d: " << p2d << endl;
155 EXPECT_DOUBLE_EQ(p2d.
y(), p2d_bis.
y()) <<
"p2d: " << p2d << endl;
156 EXPECT_DOUBLE_EQ(p2d.
phi(), p2d_bis.
phi()) <<
"p2d: " << p2d << endl;
158 EXPECT_DOUBLE_EQ(p2d.
phi(), p3d.
yaw()) <<
"p2d: " << p2d << endl;
163 const CPose3D p1_plus_p2 = p1 + p2;
177 <<
"p2 : " << p2 << endl
178 <<
"p1 : " << p1 << endl
179 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
180 <<
"p1_plus_p2bis : " << p1_plus_p2bis << endl;
195 <<
"p2 : " << p2 << endl
196 <<
"p1 : " << p1 << endl
197 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
198 <<
"p1_plus_p2bis : " << p1_plus_p2bis << endl;
213 <<
"p2 : " << p2 << endl
214 <<
"p1 : " << p1 << endl
215 <<
"p1_plus_p2 : " << p1_plus_p2 << endl
216 <<
"p1_plus_p2bis : " << p1_plus_p2bis << endl;
227 p.x(), p.y(), p.z(), p1_plus_p2.
x(), p1_plus_p2.
y(),
248 std::abs(lx - p1_plus_p.
x()) + std::abs(ly - p1_plus_p.
y()) +
249 std::abs(lz - p1_plus_p.z()),
256 p1.inverseComposePoint(
257 p1_plus_p.
x(), p1_plus_p.
y(), p1_plus_p.z(), p_recov2.
x(),
258 p_recov2.
y(), p_recov2.z());
284 CPose3D q(x[0], x[1], x[2], x[3], x[4], x[5]);
285 const CPoint3D p(x[6 + 0], x[6 + 1], x[6 + 2]);
287 for (
int i = 0; i < 3; i++) Y[i] = pp[i];
295 CPose3D q(x[0], x[1], x[2], x[3], x[4], x[5]);
296 const CPoint3D p(x[6 + 0], x[6 + 1], x[6 + 2]);
304 const CPose3D& p1,
double x,
double y,
double z,
bool use_aprox =
false)
313 x, y, z, pp.
x, pp.
y, pp.
z, df_dpoint, df_dpose, std::nullopt,
321 for (
int i = 0; i < 6; i++) x_mean[i] = p1[i];
335 x_incrs, DUMMY, numJacobs);
337 num_df_dpose = numJacobs.
block<3, 6>(0, 0);
338 num_df_dpoint = numJacobs.
block<3, 3>(0, 6);
341 const double max_error = use_aprox ? 0.1 : 3e-3;
343 EXPECT_NEAR(0, (df_dpoint - num_df_dpoint).sum_abs(), max_error)
344 <<
"p1: " << p1 << endl
345 <<
"p: " << p << endl
346 <<
"Numeric approximation of df_dpoint: " << endl
347 << num_df_dpoint << endl
348 <<
"Implemented method: " << endl
351 << df_dpoint - num_df_dpoint << endl;
355 (df_dpose.
asEigen() - num_df_dpose.
asEigen()).array().abs().sum(),
357 <<
"p1: " << p1 << endl
358 <<
"p: " << p << endl
359 <<
"Numeric approximation of df_dpose: " << endl
360 << num_df_dpose.
asEigen() << endl
361 <<
"Implemented method: " << endl
371 <<
"p1: " << p1 << endl;
375 const CPose3D& p1,
double x,
double y,
double z)
390 for (
int i = 0; i < 6; i++) x_mean[i] = p1[i];
404 x_incrs, DUMMY, numJacobs);
406 num_df_dpose = numJacobs.
block<3, 6>(0, 0);
407 num_df_dpoint = numJacobs.
block<3, 3>(0, 6);
411 0, (df_dpoint - num_df_dpoint).asEigen().array().abs().
sum(), 3e-3)
412 <<
"p1: " << p1 << endl
413 <<
"p: " << p << endl
414 <<
"Numeric approximation of df_dpoint: " << endl
415 << num_df_dpoint << endl
416 <<
"Implemented method: " << endl
419 << df_dpoint - num_df_dpoint << endl;
423 (df_dpose.
asEigen() - num_df_dpose.
asEigen()).array().abs().sum(),
425 <<
"p1: " << p1 << endl
426 <<
"p: " << p << endl
427 <<
"Numeric approximation of df_dpose: " << endl
428 << num_df_dpose.
asEigen() << endl
429 <<
"Implemented method: " << endl
443 for (
size_t i = 0; i < 4; i++)
444 for (
size_t j = 0; j < 4; j++)
447 i == j ? 1.0 : 0.0, 1e-8)
448 <<
"Failed for (i,j)=" << i <<
"," << j << endl
449 <<
"Matrix is: " << endl
451 <<
"case was: " << label << endl;
461 for (
int i = 0; i < 3; i++) Y[i] = pp[i];
471 for (
int i = 0; i < 3; i++) Y[i] = pp[i];
480 x_l.
x, x_l.
y, x_l.
z, pp.
x, pp.
y, pp.
z, std::nullopt, std::nullopt,
487 for (
int i = 0; i < 6; i++) x_mean[i] = 0;
490 for (
int i = 0; i < 3; i++) P[i] = pp[i];
499 &func_compose_point_se3),
500 x_incrs, P, num_df_dse3);
504 0, (df_dse3.
asEigen() - num_df_dse3.
asEigen()).array().abs().sum(),
506 <<
"p: " << p << endl
507 <<
"x_l: " << x_l << endl
508 <<
"Numeric approximation of df_dse3: " << endl
509 << num_df_dse3.
asEigen() << endl
510 <<
"Implemented method: " << endl
522 x_g.
x, x_g.
y, x_g.
z, pp.
x, pp.
y, pp.
z, std::nullopt, std::nullopt,
529 for (
int i = 0; i < 6; i++) x_mean[i] = 0;
532 for (
int i = 0; i < 3; i++) P[i] = pp[i];
541 &func_invcompose_point_se3),
542 x_incrs, P, num_df_dse3);
546 0, (df_dse3.
asEigen() - num_df_dse3.
asEigen()).array().abs().sum(),
548 <<
"p: " << p << endl
549 <<
"x_g: " << x_g << endl
550 <<
"Numeric approximation of df_dse3: " << endl
551 << num_df_dse3.
asEigen() << endl
552 <<
"Implemented method: " << endl
573 for (
int i = 0; i < 6; i++) x_mean[i] = 0;
575 const double& dummy = 0.;
584 x_incrs, dummy, numJacobs);
591 double vals[12 * 6] = {
592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0,
594 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
596 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
598 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0};
605 << M.
asEigen() <<
"numJacobs:\n" 606 << numJacobs <<
"\n";
620 R.asEigen().jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
621 R = Rsvd.matrixU() * Rsvd.matrixV().transpose();
637 const double& dummy = 0.;
645 x_incrs, dummy, numJacobs);
649 (numJacobs.
asEigen() - theor_jacob.asEigen()).array().abs().sum(),
651 <<
"Pose: " << p << endl
656 << theor_jacob.
asEigen() << endl
658 << theor_jacob.asEigen() - numJacobs.
asEigen() << endl;
666 const CPose3D expe_D = incr + D;
688 x_incrs, p, numJacobs);
692 (numJacobs.
asEigen() - theor_jacob.asEigen())
697 <<
"Pose: " << p << endl
702 << theor_jacob.
asEigen() << endl
704 << theor_jacob.asEigen() - numJacobs.
asEigen() << endl;
712 const CPose3D expe_D = D + incr;
734 x_incrs, p, numJacobs);
738 (numJacobs.
asEigen() - theor_jacob.asEigen())
743 <<
"Pose: " << p << endl
748 << theor_jacob.
asEigen() << endl
750 << theor_jacob.asEigen() - numJacobs.
asEigen() << endl;
790 x_incrs,
params, numJacobs);
794 (numJacobs.
asEigen() - theor_jacob.asEigen())
799 <<
"Pose A: " <<
A << endl
800 <<
"Pose D: " << D << endl
804 << theor_jacob.
asEigen() << endl
806 << theor_jacob.asEigen() - numJacobs.
asEigen() << endl;
815 test_default_values(p,
"Default");
820 test_default_values(p,
"p=p2");
824 test_default_values(p1 + p2,
"p1+p2");
826 test_default_values(p,
"p=p1+p2");
831 test_default_values(p,
"p1-p2");
837 CPose3D p(1, 2, 3, 0.2, 0.3, 0.4);
848 CPose3D p(1, 2, 3, 0.2, 0.3, 0.4);
859 static const std::vector<mrpt::poses::CPose3D>
ptc = {
860 {.0, .0, .0, .0_deg, .0_deg, .0_deg},
861 {1.0, 2.0, 3.0, .0_deg, .0_deg, .0_deg},
862 {1.0, 2.0, 3.0, 10.0_deg, .0_deg, .0_deg},
863 {1.0, 2.0, 3.0, .0_deg, 1.0_deg, .0_deg},
864 {1.0, 2.0, 3.0, .0_deg, .0_deg, 1.0_deg},
865 {1.0, 2.0, 3.0, 80.0_deg, 5.0_deg, 5.0_deg},
866 {1.0, 2.0, 3.0, -20.0_deg, -30.0_deg, -40.0_deg},
867 {1.0, 2.0, 3.0, -45.0_deg, 10.0_deg, 70.0_deg},
868 {1.0, 2.0, 3.0, 40.0_deg, -5.0_deg, 25.0_deg},
869 {1.0, 2.0, 3.0, 40.0_deg, 20.0_deg, -15.0_deg},
870 {-6.0, 2.0, 3.0, 40.0_deg, 20.0_deg, 15.0_deg},
871 {6.0, -5.0, 3.0, 40.0_deg, 20.0_deg, 15.0_deg},
872 {6.0, 2.0, -9.0, 40.0_deg, 20.0_deg, 15.0_deg},
873 {0.0, 8.0, 5.0, -45.0_deg, 10.0_deg, 70.0_deg},
874 {1.0, 0.0, 5.0, -45.0_deg, 10.0_deg, 70.0_deg},
875 {1.0, 8.0, 0.0, -45.0_deg, 10.0_deg, 70.0_deg}};
880 for (
const auto& p :
ptc) test_inverse(p);
885 for (
const auto& p1 :
ptc)
886 for (
const auto& p2 :
ptc) test_compose(p1, p2);
890 for (
const auto& p1 :
ptc)
891 for (
const auto& p2 :
ptc) test_composeFrom(p1, p2);
896 for (
const auto& p :
ptc) test_to_from_2d(p.x(), p.y(), p.yaw());
901 for (
const auto& p :
ptc)
903 test_composePoint(p, 10, 11, 12);
904 test_composePoint(p, -5, 1, 2);
905 test_composePoint(p, 5, -1, 2);
906 test_composePoint(p, 5, 1, -2);
912 for (
const auto& p :
ptc)
914 test_composePointJacob(p, 10, 11, 12);
915 test_composePointJacob(p, -5, 1, 2);
921 test_composePointJacob(
924 test_composePointJacob(
927 test_composePointJacob(
930 test_composePointJacob(
937 for (
const auto& p :
ptc)
939 test_invComposePointJacob(p, 10, 11, 12);
940 test_invComposePointJacob(p, -5, 1, 2);
941 test_invComposePointJacob(p, 5, -1, 2);
942 test_invComposePointJacob(p, 5, 1, -2);
948 for (
const auto& p :
ptc)
950 test_composePointJacob_se3(p,
TPoint3D(0, 0, 0));
951 test_composePointJacob_se3(p,
TPoint3D(10, 11, 12));
952 test_composePointJacob_se3(p,
TPoint3D(-5.0, -15.0, 8.0));
957 for (
const auto& p :
ptc)
959 test_invComposePointJacob_se3(p,
TPoint3D(0, 0, 0));
960 test_invComposePointJacob_se3(p,
TPoint3D(10, 11, 12));
961 test_invComposePointJacob_se3(p,
TPoint3D(-5.0, -15.0, 8.0));
967 for (
const auto& p :
ptc) test_ExpLnEqual(p);
985 for (
const auto& p :
ptc) test_Jacob_dexpeD_de(p);
990 for (
const auto& p :
ptc) test_Jacob_dDexpe_de(p);
995 for (
const auto& p1 :
ptc)
996 for (
const auto& p2 :
ptc) test_Jacob_dAexpeD_de(p1, p2);
A compile-time fixed-size numeric matrix container.
static void func_compose_point_se3(const CVectorFixedDouble< 6 > &x, const CVectorFixedDouble< 3 > &P, CVectorFixedDouble< 3 > &Y)
TEST_F(Pose3DTests, DefaultValues)
void test_invComposePointJacob_se3(const CPose3D &p, const TPoint3D x_g)
static const std::vector< mrpt::poses::CPose3D > ptc
void inverseComposePoint(const double gx, const double gy, const double gz, double &lx, double &ly, double &lz, mrpt::optional_ref< mrpt::math::CMatrixDouble33 > out_jacobian_df_dpoint=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dpose=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dse3=std::nullopt) const
Computes the 3D point L such as .
void test_inverse(const CPose3D &p1)
void test_composePointJacob_se3(const CPose3D &p, const TPoint3D x_l)
void test_invComposePointJacob(const CPose3D &p1, double x, double y, double z)
void test_Jacob_dexpeD_de(const CPose3D &p)
static void func_jacob_expe_D(const CVectorFixedDouble< 6 > &eps, const CPose3D &D, CVectorFixedDouble< 12 > &Y)
static void func_inv_compose_point(const CVectorFixedDouble< 6+3 > &x, const double &dummy, CVectorFixedDouble< 3 > &Y)
double pitch() const
Get the PITCH angle (in radians)
void test_composePoint(const CPose3D &p1, double x, double y, double z)
double yaw() const
Get the YAW angle (in radians)
mrpt::vision::TStereoCalibParams params
void inverse()
Convert this pose into its inverse, saving the result in itself.
void test_to_from_2d(double x, double y, double phi)
static void func_jacob_Aexpe_D(const CVectorFixedDouble< 6 > &eps, const TParams_func_jacob_Aexpe_D ¶ms, CVectorFixedDouble< 12 > &Y)
void setRotationMatrix(const mrpt::math::CMatrixDouble33 &ROT)
Sets the 3x3 rotation matrix.
void check_jacob_expe_e_at_0()
static void func_jacob_LnT_T(const CVectorFixedDouble< 12 > &x, const double &dummy, CVectorFixedDouble< 6 > &Y)
This base provides a set of functions for maths stuff.
void test_ExpLnEqual(const CPose3D &p1)
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...
double phi() const
Get the phi angle of the 2D pose (in radians)
void test_Jacob_dAexpeD_de(const CPose3D &A, const CPose3D &D)
void getInverseHomogeneousMatrix(MATRIX44 &out_HM) const
Returns the corresponding 4x4 inverse homogeneous transformation matrix for this point or pose...
auto block(int start_row, int start_col)
non-const block(): Returns an Eigen::Block reference to the block
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
void test_composePointJacob(const CPose3D &p1, double x, double y, double z, bool use_aprox=false)
static void func_invcompose_point_se3(const CVectorFixedDouble< 6 > &x, const CVectorFixedDouble< 3 > &P, CVectorFixedDouble< 3 > &Y)
TPoint3D_< double > TPoint3D
Lightweight 3D point.
double x() const
Common members of all points & poses classes.
A class used to store a 3D point.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
double roll() const
Get the ROLL angle (in radians)
void estimateJacobian(const VECTORLIKE &x, const std::function< void(const VECTORLIKE &x, const USERPARAM &y, VECTORLIKE3 &out)> &functor, const VECTORLIKE2 &increments, const USERPARAM &userParam, MATRIXLIKE &out_Jacobian)
Estimate the Jacobian of a multi-dimensional function around a point "x", using finite differences of...
void test_compose(const CPose3D &p1, const CPose3D &p2)
void setFrom12Vector(const ARRAYORVECTOR &vec12)
Set pose from an array with these 12 elements: [r11 r21 r31 r12 r22 r32 r13 r23 r33 tx ty tz] where r...
Traits for SE(n), rigid-body transformations in R^n space.
void test_Jacob_dDexpe_de(const CPose3D &p)
void check_jacob_LnT_T(const CPose3D &p)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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).
EXPECT_EQ(out.image_pair_was_used.size(), NUM_IMGS)
static void func_jacob_D_expe(const CVectorFixedDouble< 6 > &eps, const CPose3D &D, CVectorFixedDouble< 12 > &Y)
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
static void func_compose_point(const CVectorFixedDouble< 6+3 > &x, const double &dummy, CVectorFixedDouble< 3 > &Y)
void test_composeFrom(const CPose3D &p1, const CPose3D &p2)
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::optional_ref< mrpt::math::CMatrixDouble33 > out_jacobian_df_dpoint=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dpose=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dse3=std::nullopt, 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...
MATRIX44 getHomogeneousMatrixVal() const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
EXPECT_NEAR(out.cam_params.rightCameraPose.x, 0.1194, 0.005)
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
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 func_jacob_expe_e(const CVectorFixedDouble< 6 > &x, const double &dummy, CVectorFixedDouble< 12 > &Y)
void test_default_values(const CPose3D &p, const std::string &label)
vector_t asVectorVal() const
Return the pose or point as a 1xN vector with all the components (see derived classes for each implem...
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.