diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h index 9d306d5983883edea43f8712f07484d2086df065..f147738f20d34703ec0850fc1430892284e0137b 100644 --- a/include/core/problem/problem.h +++ b/include/core/problem/problem.h @@ -271,6 +271,9 @@ class Problem : public std::enable_shared_from_this<Problem> // Zero state provider Eigen::VectorXd zeroState ( ) const; bool priorIsSet() const; + // Perturb state + void perturb(double amplitude = 0.01); + // Map branch ----------------------------------------- MapBasePtr getMap() const; diff --git a/include/core/sensor/sensor_base.h b/include/core/sensor/sensor_base.h index 676a83bc5c9ade574e1b10b2a21a6bf2740cd3cd..1c099cb9be4827705bd43d229714ea1dabf24ed0 100644 --- a/include/core/sensor/sensor_base.h +++ b/include/core/sensor/sensor_base.h @@ -181,6 +181,9 @@ class SensorBase : public NodeBase, public HasStateBlocks, public std::enable_sh StateBlockPtr getStateBlockDynamic(const char _key) const { return getStateBlockDynamic(std::string(1,_key)); } StateBlockPtr getStateBlockDynamic(const char _key, const TimeStamp& _ts) const { return getStateBlockDynamic(std::string(1,_key), _ts); } + // Declare a state block as dynamic or static (with _dymanic = false) + void setStateBlockDynamic(const std::string& _key, bool _dynamic = true); + bool isStateBlockDynamic(const std::string& _key) const; bool isStateBlockInCapture(const std::string& _key, const TimeStamp& _ts, CaptureBasePtr& _cap) const; bool isStateBlockInCapture(const std::string& _key, CaptureBasePtr& _cap) const; @@ -197,7 +200,6 @@ class SensorBase : public NodeBase, public HasStateBlocks, public std::enable_sh protected: void removeStateBlocks(); virtual void registerNewStateBlocks() const; - void setStateBlockDynamic(const std::string& _key, bool _dynamic = true); public: diff --git a/src/capture/capture_base.cpp b/src/capture/capture_base.cpp index fbb54972b09b78f0a0e6a6e66701396a481d9cfc..54e5d2a3cdedb301a7580e691cad9543df3c24c2 100644 --- a/src/capture/capture_base.cpp +++ b/src/capture/capture_base.cpp @@ -140,7 +140,7 @@ const std::string& CaptureBase::getStructure() const StateBlockPtr CaptureBase::getStateBlock(const std::string& _key) const { - if (getSensor() and getSensor()->getStateBlock(_key)) + if (getSensor() and getSensor()->hasStateBlock(_key)) { if (getSensor()->isStateBlockDynamic(_key)) return HasStateBlocks::getStateBlock(_key); diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp index 482fdf08bf67cc4f26929b840871ae044ceefa42..d075d8162f862407c10d73c6f2d6c067d39e90b6 100644 --- a/src/problem/problem.cpp +++ b/src/problem/problem.cpp @@ -1386,6 +1386,26 @@ std::string Problem::printToString(int depth, bool constr_by, bool metric, bool result << endl; return result.str(); } + +void Problem::perturb(double amplitude) +{ + // Sensors + for (auto& S : getHardware()->getSensorList()) + S->perturb(amplitude); + + // Frames and Captures + for (auto& F : getTrajectory()->getFrameList()) + { + F->perturb(amplitude); + for (auto& C : F->getCaptureList()) + C->perturb(amplitude); + } + + // Landmarks + for (auto& L : getMap()->getLandmarkList()) + L->perturb(amplitude); +} + bool Problem::check(int verbose_level) const { using std::cout; diff --git a/test/gtest_problem.cpp b/test/gtest_problem.cpp index 17f39d09f7ae18275245856e1ad66dcaa3d33bfd..f1c7424d93ade98b8f836d23262aad75474d9ad6 100644 --- a/test/gtest_problem.cpp +++ b/test/gtest_problem.cpp @@ -16,6 +16,11 @@ #include "dummy/processor_tracker_feature_dummy.h" #include "core/solver/solver_manager.h" +#include "core/sensor/sensor_diff_drive.h" +#include "core/processor/processor_diff_drive.h" +#include "core/capture/capture_diff_drive.h" +#include "core/state_block/state_quaternion.h" + #include <iostream> using namespace wolf; @@ -317,6 +322,97 @@ TEST(Problem, Covariances) } +TEST(Problem, perturb) +{ + auto problem = Problem::create("PO", 2); + + // make a sensor first + auto intr = std::make_shared<ParamsSensorDiffDrive>(); + intr->radius_left = 1.0; + intr->radius_right = 1.0; + intr->wheel_separation = 1.0; + intr->ticks_per_wheel_revolution = 100; + Vector3d extr(0,0,0); + auto sensor = std::static_pointer_cast<SensorDiffDrive>(problem->installSensor("SensorDiffDrive", "sensor diff drive", extr, intr)); + sensor->setStateBlockDynamic("I", true); + + Vector3d pose; pose << 0,0,0; + + for (TimeStamp t = 0.0; t < 2.0; t += 1.0) + { + for ( int i = 0; i < 2; i++) + { + auto F = problem->emplaceFrame(KEY, pose, t); + if (i==0) F->fix(); + + for (int j = 0; j< 2 ; j++) + { + auto sb = std::make_shared<StateBlock>(Vector3d(1,1,1)); + auto cap = CaptureBase::emplace<CaptureBase>(F, "CaptureBase", t, sensor, nullptr, nullptr, sb); + } + } + } + + for (int l = 0; l < 2; l++) + { + auto sb1 = std::make_shared<StateBlock>(Vector2d(1,2)); + auto sb2 = std::make_shared<StateBlock>(Vector1d(3)); + auto L = LandmarkBase::emplace<LandmarkBase>(problem->getMap(), "LandmarkBase", sb1, sb2); + if (l==0) L->fix(); + } + + /// PRINT, PERTURB, AND PRINT AGAIN + problem->print(2,0,1,1); + + problem->perturb(0.2); + + problem->print(2,0,1,1); + + + //// CHECK ALL STATE BLOCKS /// + + double prec = 1e-2; + + for (auto S : problem->getHardware()->getSensorList()) + { + ASSERT_TRUE (S->getP()->getState().isApprox(Vector2d(0,0), prec) ); + ASSERT_TRUE (S->getO()->getState().isApprox(Vector1d(0), prec) ); + ASSERT_FALSE(S->getIntrinsic()->getState().isApprox(Vector3d(1,1,1), prec) ); + } + + for (auto F : problem->getTrajectory()->getFrameList()) + { + if (F->isFixed()) // fixed + { + ASSERT_TRUE (F->getP()->getState().isApprox(Vector2d(0,0), prec) ); + ASSERT_TRUE (F->getO()->getState().isApprox(Vector1d(0), prec) ); + } + else + { + ASSERT_FALSE(F->getP()->getState().isApprox(Vector2d(0,0), prec) ); + ASSERT_FALSE(F->getO()->getState().isApprox(Vector1d(0), prec) ); + } + for (auto C : F->getCaptureList()) + { + // all are estimated + ASSERT_FALSE(C->getSensorIntrinsic()->getState().isApprox(Vector3d(1,1,1), prec) ); + } + } + for (auto L : problem->getMap()->getLandmarkList()) + { + if ( L->isFixed() ) // fixed + { + ASSERT_TRUE (L->getP()->getState().isApprox(Vector2d(1,2), prec) ); + ASSERT_TRUE (L->getO()->getState().isApprox(Vector1d(3), prec) ); + } + else + { + ASSERT_FALSE(L->getP()->getState().isApprox(Vector2d(1,2), prec) ); + ASSERT_FALSE(L->getO()->getState().isApprox(Vector1d(3), prec) ); + } + } +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv);