diff --git a/test/gtest_processor_motion_intrinsics_update.cpp b/test/gtest_processor_motion_intrinsics_update.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecb3d8048c0ed1e6fb8c26d77032c093baefe6db --- /dev/null +++ b/test/gtest_processor_motion_intrinsics_update.cpp @@ -0,0 +1,148 @@ +#include "core/utils/utils_gtest.h" + +#include "core/common/wolf.h" +#include "core/problem/problem.h" +#include <core/ceres_wrapper/solver_ceres.h> +#include "core/capture/capture_void.h" +#include "core/feature/feature_base.h" +#include "core/factor/factor_block_absolute.h" +#include "core/processor/processor_diff_drive.h" +#include "core/sensor/sensor_diff_drive.h" +#include "core/capture/capture_diff_drive.h" + +using namespace wolf; +using namespace Eigen; + + + +/** +Simplified test rolling along x axis only: +Delta_x = 2*pi*R*(ticks/ticks_per_wheel_revolution) + +If we take ticks_per_wheel_revolution = 2*pi, even simpler formulat: +Delta_x = R*ticks + +**/ + +class ProcessorDiffDriveTest : public testing::Test +{ + public: + ParamsSensorDiffDrivePtr intr_; + SensorDiffDrivePtr sensor_; + ParamsProcessorDiffDrivePtr params_; + ProcessorDiffDrivePtr processor_; + ProblemPtr problem_; + SolverCeresPtr solver_; + FrameBasePtr KF0_; + double radius; + + void SetUp() override + { + problem_ = Problem::create("PO", 2); + solver_ = std::make_shared<SolverCeres>(problem_); + + VectorComposite x_origin("PO", {Vector2d::Zero(), Vector1d::Zero()}); + VectorComposite std_origin("PO", {0.001*Vector2d::Ones(), 0.001*Vector1d::Ones()}); + + // ground truth of wheels radius + radius = 1; + // make a sensor first + intr_ = std::make_shared<ParamsSensorDiffDrive>(); + intr_->radius_left = 1.042; + intr_->radius_right = 1.042; + intr_->wheel_separation = 1.0; + intr_->ticks_per_wheel_revolution = 2*M_PI; + Vector3d extr(0,0,0); + sensor_ = std::static_pointer_cast<SensorDiffDrive>(problem_->installSensor("SensorDiffDrive", "sensor diff drive", extr, intr_)); + + // params and processor + params_ = std::make_shared<ParamsProcessorDiffDrive>(); + params_->voting_active = true; + params_->angle_turned = 1000000; + params_->dist_traveled = 200000000; + params_->max_buff_length = 1000000000; + params_->max_time_span = 2.999; // controls KF creation + params_->cov_det = 10000000; + + params_->unmeasured_perturbation_std = 1e-4; + processor_ = std::static_pointer_cast<ProcessorDiffDrive>(problem_->installProcessor("ProcessorDiffDrive", "processor diff drive", sensor_, params_)); + + KF0_ = problem_->setPriorFactor(x_origin, std_origin, 0, 0.01); + + processor_->setOrigin(KF0_); + } + + void TearDown() override{} + +}; + +TEST_F(ProcessorDiffDriveTest, test1) +{ + Matrix2d data_cov; data_cov . setIdentity(); + // Advances at constant speed on both wheels + double ticks = 1; + + Vector2d data; data << ticks, ticks; + auto C1 = std::make_shared<CaptureDiffDrive>(1, sensor_, data, data_cov, KF0_->getCaptureList().front()); C1->process(); + auto C2 = std::make_shared<CaptureDiffDrive>(2, sensor_, data, data_cov, KF0_->getCaptureList().front()); C2->process(); + auto C3 = std::make_shared<CaptureDiffDrive>(3, sensor_, data, data_cov, KF0_->getCaptureList().front()); C3->process(); + FrameBasePtr KF1 = problem_->getTrajectory()->getLastFrame(); + Vector2d state_pred1; state_pred1 << 3*ticks, 0; + auto CA1 = CaptureBase::emplace<CaptureVoid>(KF1, KF1->getTimeStamp(), nullptr); + auto FA1 = FeatureBase::emplace<FeatureBase>(CA1, "POSITION", state_pred1, pow(0.001, 2)*Matrix2d::Identity()); + FactorBase::emplace<FactorBlockAbsolute>(FA1, FA1, FA1->getFrame()->getP(), nullptr, false); + + problem_->print(4,true,true,true); + solver_->solve(); + problem_->print(4,true,true,true); + + // now, intrinsics are updated in KF0 and KF1 captures + auto C4 = std::make_shared<CaptureDiffDrive>(4, sensor_, data, data_cov, C3); C4->process(); + auto C5 = std::make_shared<CaptureDiffDrive>(5, sensor_, data, data_cov, C3); C5->process(); + auto C6 = std::make_shared<CaptureDiffDrive>(6, sensor_, data, data_cov, C3); C6->process(); + + FrameBasePtr KF2 = problem_->getTrajectory()->getLastFrame(); + Vector2d state_pred2; state_pred2 << 6*ticks, 0; + auto CA2 = CaptureBase::emplace<CaptureVoid>(KF2, KF2->getTimeStamp(), nullptr); + auto FA2 = FeatureBase::emplace<FeatureBase>(CA2, "POSITION", state_pred2, pow(0.001, 2)*Matrix2d::Identity()); + FactorBase::emplace<FactorBlockAbsolute>(FA2, FA2, FA2->getFrame()->getP(), nullptr, false); + + problem_->print(4,true,true,true); + solver_->solve(); + problem_->print(4,true,true,true); + + + // now, intrinsics are updated in KF0 and KF1 captures + auto C7 = std::make_shared<CaptureDiffDrive>(7, sensor_, data, data_cov, C6); C7->process(); + auto C8 = std::make_shared<CaptureDiffDrive>(8, sensor_, data, data_cov, C6); C8->process(); + auto C9 = std::make_shared<CaptureDiffDrive>(9, sensor_, data, data_cov, C6); C9->process(); + + FrameBasePtr KF3 = problem_->getTrajectory()->getLastFrame(); + Vector2d state_pred3; state_pred3 << 9*ticks, 0; + auto CA3 = CaptureBase::emplace<CaptureVoid>(KF3, KF3->getTimeStamp(), nullptr); + auto FA3 = FeatureBase::emplace<FeatureBase>(CA3, "POSITION", state_pred3, pow(0.001, 2)*Matrix2d::Identity()); + FactorBase::emplace<FactorBlockAbsolute>(FA3, FA3, FA3->getFrame()->getP(), nullptr, false); + + problem_->print(4,true,true,true); + solver_->solve(); + problem_->print(4,true,true,true); + + + + // problem_->getTrajectory()->getLastFrame() + // problem_->print(4,true,true,true); + // problem_->perturb(); + // problem_->print(4,true,true,true); + + + +} + + + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}