diff --git a/src/problem.cpp b/src/problem.cpp index 8c639c114c44031bfcb73a7dadd915b296ec43fb..f22844b1cd3474c15fae7cc4ba6bb0a7ae2b915c 100644 --- a/src/problem.cpp +++ b/src/problem.cpp @@ -326,7 +326,7 @@ void Problem::keyFrameCallback(FrameBasePtr _keyframe_ptr, ProcessorBasePtr _pro //std::cout << "Problem::keyFrameCallback: processor " << _processor_ptr->getName() << std::endl; for (auto sensor : hardware_ptr_->getSensorList()) for (auto processor : sensor->getProcessorList()) - if (processor->id() != _processor_ptr->id()) + if (processor && (processor != _processor_ptr) ) processor->keyFrameCallback(_keyframe_ptr, _time_tolerance); } diff --git a/src/processor_motion.cpp b/src/processor_motion.cpp index 0e10ad72a2af54de99ed6dab4c286032800e3afb..fc9e6624f46dddcc0c21eabf8d475bab786c6171 100644 --- a/src/processor_motion.cpp +++ b/src/processor_motion.cpp @@ -180,7 +180,7 @@ FrameBasePtr ProcessorMotion::setOrigin(const Eigen::VectorXs& _x_origin, const void ProcessorMotion::setOrigin(FrameBasePtr _origin_frame) { - + assert(_origin_frame && "ProcessorMotion::setOrigin: Provided frame pointer is nullptr."); assert(_origin_frame->getTrajectoryPtr() != nullptr && "ProcessorMotion::setOrigin: origin frame must be in the trajectory."); assert(_origin_frame->isKey() && "ProcessorMotion::setOrigin: origin frame must be KEY FRAME."); diff --git a/src/test/gtest_IMU.cpp b/src/test/gtest_IMU.cpp index 405aaad9e0d4ec9de7836cbb6c458da28dbbb18d..c2711bf2755617b80b9a1442f663251d79454a69 100644 --- a/src/test/gtest_IMU.cpp +++ b/src/test/gtest_IMU.cpp @@ -9,7 +9,8 @@ #include "wolf.h" #include "sensor_imu.h" #include "processor_imu.h" -//#include "processor_odom_3D.h" +#include "sensor_odom_3D.h" +#include "processor_odom_3D.h" #include "ceres_wrapper/ceres_manager.h" #include "utils_gtest.h" @@ -63,7 +64,7 @@ class Process_Constraint_IMU : public testing::Test VectorXs D_preint, x1_preint; // preintegrated with processor_imu VectorXs D_corrected, x1_corrected; // corrected with processor_imu VectorXs D_optim, x1_optim; // optimized using constraint_imu - VectorXs D_optim_imu, x1_optim_imu; // corrected with imu_tools osing optimized bias + VectorXs D_optim_imu, x1_optim_imu; // corrected with imu_tools using optimized bias VectorXs x0_optim; // optimized using constraint_imu // Delta correction Jacobian and step @@ -222,15 +223,18 @@ class Process_Constraint_IMU : public testing::Test // Initial configuration of variables bool configureAll() { + // variables DT = num_integrations * dt; q0 .normalize(); x0 << p0, q0.coeffs(), v0; P0 .setIdentity() * 0.01; + motion << a, w; + + // wolf objects KF_0 = problem->setPrior(x0, P0, t0); C_0 = processor_imu->getOriginPtr(); CM_1 = processor_imu->getLastPtr(); KF_1 = CM_1->getFramePtr(); - motion << a, w; processor_imu->getLastPtr()->setCalibrationPreint(bias_preint); @@ -310,10 +314,12 @@ class Process_Constraint_IMU : public testing::Test { // ===================================== SET KF in Wolf tree FrameBasePtr KF = problem->emplaceFrame(KEY_FRAME, x1_exact, t); + + // ===================================== IMU CALLBACK processor_imu->keyFrameCallback(KF, 0.01); KF_1 = problem->getLastKeyFramePtr(); - C_1 = KF_1->getCaptureList().back(); + C_1 = KF_1->getCaptureList().front(); // front is IMU CM_1 = static_pointer_cast<CaptureMotion>(C_1); // ===================================== SET BOUNDARY CONDITIONS @@ -382,6 +388,52 @@ class Process_Constraint_IMU : public testing::Test }; +class Process_Constraint_IMU_ODO : public Process_Constraint_IMU +{ + public: + // Wolf objects + SensorOdom3DPtr sensor_odo; + ProcessorOdom3DPtr processor_odo; + + virtual void SetUp( ) + { + Process_Constraint_IMU::SetUp(); + + string wolf_root = _WOLF_ROOT_DIR; + + SensorBasePtr sensor = problem->installSensor ("ODOM 3D", "Odometer", (Vector7s()<<0,0,0,0,0,0,1).finished(), wolf_root + "/src/examples/sensor_odom_3D.yaml" ); + ProcessorBasePtr processor = problem->installProcessor("ODOM 3D", "Odometer", "Odometer" , wolf_root + "/src/examples/processor_odom_3D.yaml"); + sensor_odo = static_pointer_cast<SensorOdom3D>(sensor); + processor_odo = static_pointer_cast<ProcessorOdom3D>(processor); + + // prevent this processor from voting by setting high thresholds : + processor_odo->setAngleTurned(2.0); + processor_odo->setDistTraveled(1.0); + processor_odo->setMaxBuffLength(10); + processor_odo->setMaxTimeSpan(1.0); + } + + void integrateOdo() + { + Vector6s data; + Vector3s p1 = x1_exact.head(3); + Quaternions q1 (x1_exact.data() + 3); + Vector3s dp = q0.conjugate() * (p1 - p0); + Vector3s dth = wolf::log_q( q0.conjugate() * q1 ); + data << dp, dth; + + CaptureOdom3DPtr capture_odo = make_shared<CaptureOdom3D>(t, sensor_odo, data, sensor_odo->getNoiseCov()); + + sensor_odo->process(capture_odo); + } + + void buildOdoProblem() + { + processor_odo->keyFrameCallback(KF_1, 0.1); + } + +}; + TEST_F(Process_Constraint_IMU, Var_B1_B2_Invar_P1_Q1_V1_P2_Q2_V2) { @@ -430,29 +482,29 @@ TEST_F(Process_Constraint_IMU, Var_B1_B2_Invar_P1_Q1_V1_P2_Q2_V2) // ===================================== PRINT RESULTS - // print(); +// print(); // ===================================== CHECK ALL (SEE CLASS DEFINITION FOR THE MEANING OF ALL VARIABLES) // check delta and state integrals - ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected_imu, x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected_imu , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); // check optimal solutions - ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); - ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0, 1e-8 ); - ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim_imu, x1_exact , 1e-5 ); - ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0, 1e-8 ); + ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); + ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim_imu , x1_exact , 1e-5 ); + ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0 , 1e-8 ); } @@ -510,23 +562,23 @@ TEST_F(Process_Constraint_IMU, Var_P1_Q1_V1_B1_B2_Invar_P2_Q2_V2) // ===================================== CHECK ALL (SEE CLASS DEFINITION FOR THE MEANING OF ALL VARIABLES) // check delta and state integrals - ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected_imu, x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected_imu , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); // check optimal solutions - ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); - ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0, 1e-8 ); - ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim_imu, x1_exact , 1e-5 ); - ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0, 1e-8 ); + ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); + ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim_imu , x1_exact , 1e-5 ); + ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0 , 1e-8 ); } @@ -587,24 +639,180 @@ TEST_F(Process_Constraint_IMU, Var_P1_Q1_B1_V2_B2_Invar_V1_P2_Q2) // PQv_B__pqV_ // ===================================== CHECK ALL (SEE CLASS DEFINITION FOR THE MEANING OF ALL VARIABLES) // check delta and state integrals - ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); - ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected_imu, x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected_imu , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); + + // check optimal solutions + ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); + ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim_imu , x1_exact , 1e-5 ); + ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + +} + + +TEST_F(Process_Constraint_IMU_ODO, Var_P0_Q0_V0_B0_P1_Q1_B1__Invar_V1) +{ + + // ================================================================================================================ // + // ==================================== INITIAL CONDITIONS -- USER OPTIONS ======================================== // + // ================================================================================================================ // + // + // ---------- time + t0 = 0; + dt = 0.01; + num_integrations = 50; + + // ---------- initial pose + p0 << 0,0,0; + q0.coeffs() << 0,0,0,1; + v0 << 0,0,0; + + // ---------- bias + bias_real << .001, .002, .003, -.001, -.002, -.003; + bias_preint = -bias_real; + + // ---------- motion params + a << 1,2,3; + w << 1,2,3; + + // ---------- fix boundaries + p0_fixed = false; + q0_fixed = false; + v0_fixed = false; + p1_fixed = false; + q1_fixed = false; + v1_fixed = true; + // + // ===================================== INITIAL CONDITIONS -- USER INPUT ENDS HERE =============================== // + // ================================================================================================================ // + + + // ===================================== RUN ALL but do not solve yet + configureAll(); + integrateAll(); + integrateOdo(); + buildProblem(); + buildOdoProblem(); + +// problem->print(4,1,1,1); + + // ===================================== SOLVE + string report = solveProblem(1); + WOLF_TRACE(report); + + + // ===================================== PRINT RESULTS +// print(); + + + // ===================================== CHECK ALL (SEE CLASS DEFINITION FOR THE MEANING OF ALL VARIABLES) + + // check delta and state integrals + ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected_imu , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); // check optimal solutions - ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); - ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0, 1e-8 ); - ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); - ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); - ASSERT_MATRIX_APPROX(x1_optim_imu, x1_exact , 1e-5 ); - ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0, 1e-8 ); + ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); + ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim_imu , x1_exact , 1e-5 ); + ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0 , 1e-8 ); +} + + +TEST_F(Process_Constraint_IMU_ODO, Var_P0_Q0_B0_P1_Q1_V1_B1__Invar_V0) +{ + // ================================================================================================================ // + // ==================================== INITIAL CONDITIONS -- USER OPTIONS ======================================== // + // ================================================================================================================ // + // + // ---------- time + t0 = 0; + dt = 0.01; + num_integrations = 50; + + // ---------- initial pose + p0 << 0,0,0; + q0.coeffs() << 0,0,0,1; + v0 << 0,0,0; + + // ---------- bias + bias_real << .001, .002, .003, -.001, -.002, -.003; + bias_preint = -bias_real; + + // ---------- motion params + a << 1,2,3; + w << 1,2,3; + + // ---------- fix boundaries + p0_fixed = false; + q0_fixed = false; + v0_fixed = true; + p1_fixed = false; + q1_fixed = false; + v1_fixed = false; + // + // ===================================== INITIAL CONDITIONS -- USER INPUT ENDS HERE =============================== // + // ================================================================================================================ // + + + // ===================================== RUN ALL but do not solve yet + configureAll(); + integrateAll(); + integrateOdo(); + buildProblem(); + buildOdoProblem(); + +// problem->print(4,1,1,1); + + // ===================================== SOLVE + string report = solveProblem(1); + WOLF_TRACE(report); + + + // ===================================== PRINT RESULTS +// print(); + + + // ===================================== CHECK ALL (SEE CLASS DEFINITION FOR THE MEANING OF ALL VARIABLES) + + // check delta and state integrals + ASSERT_MATRIX_APPROX(D_preint , D_preint_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected , D_corrected_imu , 1e-8 ); + ASSERT_MATRIX_APPROX(D_corrected_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_corrected , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected_imu , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_corrected , x1_exact , 1e-5 ); + + // check optimal solutions + ASSERT_MATRIX_APPROX(x0_optim , x0 , 1e-5 ); + ASSERT_NEAR(x0_optim.segment(3,4).norm(), 1.0 , 1e-8 ); + ASSERT_MATRIX_APPROX(bias_0 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(bias_1 , bias_real , 1e-4 ); + ASSERT_MATRIX_APPROX(D_optim , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim , x1_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(D_optim_imu , D_exact , 1e-5 ); + ASSERT_MATRIX_APPROX(x1_optim_imu , x1_exact , 1e-5 ); + ASSERT_NEAR(x1_optim.segment(3,4).norm(), 1.0 , 1e-8 ); } @@ -612,7 +820,8 @@ TEST_F(Process_Constraint_IMU, Var_P1_Q1_B1_V2_B2_Invar_V1_P2_Q2) // PQv_B__pqV_ int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); - ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU.*"; +// ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU.*"; +// ::testing::GTEST_FLAG(filter) = "Process_Constraint_IMU_ODO.*"; return RUN_ALL_TESTS(); }