diff --git a/include/base/constraint/constraint_analytic.h b/include/base/constraint/constraint_analytic.h index 3b5015be0841fab26b3e540dcda757987bdea753..2e3d110b133925f4032370c971e4bd344d8a1ae5 100644 --- a/include/base/constraint/constraint_analytic.h +++ b/include/base/constraint/constraint_analytic.h @@ -81,7 +81,6 @@ class ConstraintAnalytic: public ConstraintBase /** \brief Evaluate the constraint given the input parameters and returning the residuals and jacobians **/ - // TODO virtual bool evaluate(Scalar const* const* parameters, Scalar* residuals, Scalar** jacobians) const override { // load parameters evaluation value @@ -116,7 +115,7 @@ class ConstraintAnalytic: public ConstraintBase return true; }; - /** Returns the residual vetor and a vector of Jacobian matrix corresponding to each state block evaluated in the point provided in _states_ptr + /** Returns the residual vector and a vector of Jacobian matrix corresponding to each state block evaluated in the point provided in _states_ptr **/ // TODO virtual void evaluate(const std::vector<const Scalar*>& _states_ptr, Eigen::VectorXs& residual_, std::vector<Eigen::MatrixXs>& jacobians_) const override @@ -130,9 +129,9 @@ class ConstraintAnalytic: public ConstraintBase **/ virtual Eigen::VectorXs evaluateResiduals(const std::vector<Eigen::Map<const Eigen::VectorXs>>& _st_vector) const = 0; - /** \brief Returns the jacobians evaluated in the states provided + /** \brief Returns the normalized jacobians evaluated in the states * - * Returns the jacobians evaluated in the states provided in std::vector of mapped Eigen::VectorXs. + * Returns the normalized (by the measurement noise sqrt information) jacobians evaluated in the states provided in std::vector of mapped Eigen::VectorXs. * IMPORTANT: only fill the jacobians of the state blocks specified in _compute_jacobian. * * \param _st_vector is a vector containing the mapped eigen vectors of all state blocks involved in the constraint @@ -142,11 +141,10 @@ class ConstraintAnalytic: public ConstraintBase **/ virtual void evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXs>>& _st_vector, std::vector<Eigen::Map<Eigen::MatrixXs>>& jacobians, const std::vector<bool>& _compute_jacobian) const = 0; - /** \brief Returns the pure jacobians (without measurement noise) evaluated in the state blocks values + /** \brief Returns the jacobians (without measurement noise normalization) evaluated in the current state blocks values * - * Returns the pure jacobians (without measurement noise) evaluated in the state blocks values + * Returns the jacobians (without measurement noise normalization) evaluated in the current state blocks values * - * \param _st_vector is a vector containing the mapped eigen vectors of all state blocks involved in the constraint * \param jacobians is an output vector of mapped eigen matrices that sould contain the jacobians w.r.t each state block * **/ diff --git a/include/base/constraint/constraint_block_absolute.h b/include/base/constraint/constraint_block_absolute.h index 22b4ee1b1ebb371e6cc76ad5e8bd5392df6e64ee..85a76c664ab5c3113c91ec34ff1df2785e1b910e 100644 --- a/include/base/constraint/constraint_block_absolute.h +++ b/include/base/constraint/constraint_block_absolute.h @@ -9,6 +9,7 @@ #define CONSTRAINT_BLOCK_ABSOLUTE_H_ //Wolf includes +#include "base/constraint/constraint_analytic.h" #include "base/constraint/constraint_autodiff.h" #include "base/frame_base.h" @@ -17,43 +18,122 @@ namespace wolf { WOLF_PTR_TYPEDEFS(ConstraintBlockAbsolute); //class -class ConstraintBlockAbsolute: public ConstraintAutodiff<ConstraintBlockAbsolute,3,3> +class ConstraintBlockAbsolute : public ConstraintAnalytic { + private: + SizeEigen sb_size_; // the size of the state block + SizeEigen sb_constrained_start_; // the index of the first state element that is constrained + SizeEigen sb_constrained_size_; // the size of the state segment that is constrained + Eigen::MatrixXs J_; // Jacobian + public: - ConstraintBlockAbsolute(StateBlockPtr _sb_ptr, bool _apply_loss_function = false, ConstraintStatus _status = CTR_ACTIVE) : - ConstraintAutodiff<ConstraintBlockAbsolute,3,3>("BLOCK ABS", - nullptr, nullptr, nullptr, nullptr, nullptr, _apply_loss_function, _status, _sb_ptr) + /** \brief Constructor + * + * \param _sb_ptr the constrained state block + * \param _start_idx (default=0) the index of the first state element that is constrained + * \param _start_idx (default=-1) the size of the state segment that is constrained, -1 = all the + * + */ + ConstraintBlockAbsolute(StateBlockPtr _sb_ptr, + unsigned int _start_idx = 0, + int _size = -1, + bool _apply_loss_function = false, + ConstraintStatus _status = CTR_ACTIVE) : + ConstraintAnalytic("BLOCK ABS", + _apply_loss_function, + _status, + _sb_ptr), + sb_size_(_sb_ptr->getSize()), + sb_constrained_start_(_start_idx), + sb_constrained_size_(_size == -1 ? sb_size_ : _size) { - // + assert(sb_constrained_size_+sb_constrained_start_ <= sb_size_); + + // precompute Jacobian (Identity) + if (sb_constrained_start_ == 0) + J_ = Eigen::MatrixXs::Identity(sb_constrained_size_, sb_size_); + else + { + J_ = Eigen::MatrixXs::Zero(sb_constrained_size_,sb_size_); + J_.middleCols(sb_constrained_start_,sb_constrained_size_) = Eigen::MatrixXs::Identity(sb_constrained_size_, sb_constrained_size_); + } } virtual ~ConstraintBlockAbsolute() = default; - template<typename T> - bool operator ()(const T* const _sb, T* _residuals) const; - + /** \brief Returns the residual evaluated in the states provided + * + * Returns the residual evaluated in the states provided in std::vector of mapped Eigen::VectorXs + * + **/ + virtual Eigen::VectorXs evaluateResiduals(const std::vector<Eigen::Map<const Eigen::VectorXs> >& _st_vector) const; + + /** \brief Returns the normalized jacobians evaluated in the states + * + * Returns the normalized (by the measurement noise sqrt information) jacobians evaluated in the states provided in std::vector of mapped Eigen::VectorXs. + * IMPORTANT: only fill the jacobians of the state blocks specified in _compute_jacobian. + * + * \param _st_vector is a vector containing the mapped eigen vectors of all state blocks involved in the constraint + * \param jacobians is an output vector of mapped eigen matrices that sould contain the jacobians w.r.t each state block + * \param _compute_jacobian is a vector that specifies whether the ith jacobian sould be computed or not + * + **/ + virtual void evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXs> >& _st_vector, + std::vector<Eigen::Map<Eigen::MatrixXs> >& jacobians, + const std::vector<bool>& _compute_jacobian) const; + + /** \brief Returns the pure jacobians (without measurement noise) evaluated in the state blocks values + * + * Returns the pure jacobians (without measurement noise) evaluated in the current state blocks values + * + * \param jacobians is an output vector of mapped eigen matrices that sould contain the jacobians w.r.t each state block + * + **/ + virtual void evaluatePureJacobians(std::vector<Eigen::MatrixXs>& jacobians) const; + + /** \brief Returns the constraint residual size + **/ + virtual unsigned int getSize() const; }; -template<typename T> -inline bool ConstraintBlockAbsolute::operator ()(const T* const _sb, T* _residuals) const +inline Eigen::VectorXs ConstraintBlockAbsolute::evaluateResiduals(const std::vector<Eigen::Map<const Eigen::VectorXs> >& _st_vector) const { + assert(_st_vector.size() == 1 && "Wrong number of state blocks!"); + assert(_st_vector.front().size() >= getMeasurement().size() && "Wrong StateBlock size"); - // states - Eigen::Matrix<T, 3, 1> sb(_sb); + // residual + if (sb_constrained_size_ == _st_vector.front().size()) + return getMeasurementSquareRootInformationUpper() * (_st_vector.front() - getMeasurement()); + else + return getMeasurementSquareRootInformationUpper() * (_st_vector.front().segment(sb_constrained_start_,sb_constrained_size_) - getMeasurement()); +} - // measurements - Eigen::Vector3s measured_state(getMeasurement().data() + 0); +inline void ConstraintBlockAbsolute::evaluateJacobians( + const std::vector<Eigen::Map<const Eigen::VectorXs> >& _st_vector, + std::vector<Eigen::Map<Eigen::MatrixXs> >& jacobians, const std::vector<bool>& _compute_jacobian) const +{ + assert(_st_vector.size() == 1 && "Wrong number of state blocks!"); + assert(jacobians.size() == 1 && "Wrong number of jacobians!"); + assert(_compute_jacobian.size() == 1 && "Wrong number of _compute_jacobian booleans!"); + assert(_st_vector.front().size() == sb_size_ && "Wrong StateBlock size"); + assert(_st_vector.front().size() >= getMeasurement().size() && "StateBlock size and measurement size should match"); + + // normalized jacobian + if (_compute_jacobian.front()) + jacobians.front() = getMeasurementSquareRootInformationUpper() * J_; +} - // error - Eigen::Matrix<T, 3, 1> er; - er = measured_state.cast<T>() - sb; +inline void ConstraintBlockAbsolute::evaluatePureJacobians(std::vector<Eigen::MatrixXs>& jacobians) const +{ + assert(jacobians.size() == 1 && "Wrong number of jacobians!"); - // residual - Eigen::Map<Eigen::Matrix<T, 3, 1>> res(_residuals); - res = getFeaturePtr()->getMeasurementSquareRootInformationUpper().cast<T>() * er; + jacobians.front() = J_; +} - return true; +inline unsigned int ConstraintBlockAbsolute::getSize() const +{ + return sb_constrained_size_; } } // namespace wolf diff --git a/include/base/constraint/constraint_relative_2D_analytic.h b/include/base/constraint/constraint_relative_2D_analytic.h index a9655a9146e8f7dce7efc6378effd3c56a59cb66..125537e5a3dde3771d9d7c8da20c97c09b96f520 100644 --- a/include/base/constraint/constraint_relative_2D_analytic.h +++ b/include/base/constraint/constraint_relative_2D_analytic.h @@ -85,7 +85,6 @@ class ConstraintRelative2DAnalytic : public ConstraintAnalytic const std::vector<bool>& _compute_jacobian) const override; /** \brief Returns the pure jacobians (without measurement noise) evaluated in the state blocks values - * \param _st_vector is a vector containing the mapped eigen vectors of all state blocks involved in the constraint * \param jacobians is an output vector of mapped eigen matrices that sould contain the jacobians w.r.t each state block * **/ @@ -124,11 +123,11 @@ inline void ConstraintRelative2DAnalytic::evaluateJacobians( << -(_st_vector[2](0) - _st_vector[0](0)) * sin(_st_vector[1](0)) + (_st_vector[2](1) - _st_vector[0](1)) * cos(_st_vector[1](0)), -(_st_vector[2](0) - _st_vector[0](0)) * cos(_st_vector[1](0)) - (_st_vector[2](1) - _st_vector[0](1)) * sin(_st_vector[1](0)), -1; - jacobians[1] = getMeasurementSquareRootInformationUpper() * jacobians[0]; + jacobians[1] = getMeasurementSquareRootInformationUpper() * jacobians[1]; jacobians[2] << cos(_st_vector[1](0)), sin(_st_vector[1](0)), -sin(_st_vector[1](0)), cos(_st_vector[1](0)), 0, 0; - jacobians[2] = getMeasurementSquareRootInformationUpper() * jacobians[0]; + jacobians[2] = getMeasurementSquareRootInformationUpper() * jacobians[2]; jacobians[3] << 0, 0, 1; - jacobians[3] = getMeasurementSquareRootInformationUpper() * jacobians[0]; + jacobians[3] = getMeasurementSquareRootInformationUpper() * jacobians[3]; } inline void ConstraintRelative2DAnalytic::evaluatePureJacobians(std::vector<Eigen::MatrixXs>& jacobians) const diff --git a/include/base/processor/processor_base.h b/include/base/processor/processor_base.h index 6a1d23cfb3fd19a625407c4de20eb6d17784e371..23ac82daa6ff6ea65bc3172d4fa0726890e5dff1 100644 --- a/include/base/processor/processor_base.h +++ b/include/base/processor/processor_base.h @@ -110,13 +110,9 @@ struct ProcessorParamsBase ProcessorParamsBase() = default; ProcessorParamsBase(bool _voting_active, - Scalar _time_tolerance, - const std::string& _type, - const std::string& _name) + Scalar _time_tolerance) : voting_active(_voting_active) , time_tolerance(_time_tolerance) - , type(_type) - , name(_name) { // } @@ -129,9 +125,6 @@ struct ProcessorParamsBase /// a particular Capture of this processor to allow assigning /// this Capture to the Keyframe. Scalar time_tolerance = Scalar(0); - - std::string type; - std::string name; }; //class ProcessorBase diff --git a/include/base/sensor/sensor_GPS_fix.h b/include/base/sensor/sensor_GPS_fix.h index e74ff5e89f31b3fc0759f8d62bd76448c956c593..17db7c12c11574c9be64e7adac312d8a671587af 100644 --- a/include/base/sensor/sensor_GPS_fix.h +++ b/include/base/sensor/sensor_GPS_fix.h @@ -22,15 +22,6 @@ WOLF_PTR_TYPEDEFS(SensorGPSFix); class SensorGPSFix : public SensorBase { public: - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _p_ptr StateBlock pointer to the sensor position - * \param _o_ptr StateBlock pointer to the sensor orientation - * \param _noise noise standard deviation - * - **/ - SensorGPSFix(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const double& _noise); SensorGPSFix(const Eigen::VectorXs & _extrinsics, const IntrinsicsGPSFix& _intrinsics); SensorGPSFix(const Eigen::VectorXs & _extrinsics, IntrinsicsGPSFixPtr _intrinsics_ptr); diff --git a/include/base/sensor/sensor_IMU.h b/include/base/sensor/sensor_IMU.h index 17c1c873d921032c05700a558abf6151e3f3255b..2c8efa2c9312f62bca4d9d1c2578a458914403bb 100644 --- a/include/base/sensor/sensor_IMU.h +++ b/include/base/sensor/sensor_IMU.h @@ -46,17 +46,6 @@ class SensorIMU : public SensorBase public: - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _p_ptr StateBlock pointer to the sensor position wrt vehicle base - * \param _o_ptr StateBlock pointer to the sensor orientation wrt vehicle base - * \param params IntrinsicsIMU pointer to sensor properties - * \param _a_w_biases_ptr StateBlock pointer to the vector of acc and gyro biases - * - **/ - SensorIMU(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, IntrinsicsIMUPtr _params); - SensorIMU(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const IntrinsicsIMU& _params); SensorIMU(const Eigen::VectorXs& _extrinsics, const IntrinsicsIMU& _params); SensorIMU(const Eigen::VectorXs& _extrinsics, IntrinsicsIMUPtr _params); diff --git a/include/base/sensor/sensor_base.h b/include/base/sensor/sensor_base.h index 8707d13ac8bcac4b288f139dec53045625f02ac9..01df97dc63db1cbd6a02abce6625dc6b24247d47 100644 --- a/include/base/sensor/sensor_base.h +++ b/include/base/sensor/sensor_base.h @@ -24,9 +24,6 @@ namespace wolf { struct IntrinsicsBase { virtual ~IntrinsicsBase() = default; - - std::string type; - std::string name; }; class SensorBase : public NodeBase, public std::enable_shared_from_this<SensorBase> @@ -49,6 +46,8 @@ class SensorBase : public NodeBase, public std::enable_shared_from_this<SensorBa Eigen::VectorXs noise_std_; // std of sensor noise Eigen::MatrixXs noise_cov_; // cov matrix of noise + std::map<unsigned int,FeatureBasePtr> params_prior_map_; // Priors (value and covariance) of extrinsic & intrinsic state blocks (by index in state_block_vec_) + public: /** \brief Constructor with noise size * @@ -89,7 +88,6 @@ class SensorBase : public NodeBase, public std::enable_shared_from_this<SensorBa const bool _intr_dyn = false); virtual ~SensorBase(); - virtual void remove(); unsigned int id(); @@ -110,11 +108,16 @@ class SensorBase : public NodeBase, public std::enable_shared_from_this<SensorBa const std::vector<StateBlockPtr>& getStateBlockVec() const; std::vector<StateBlockPtr>& getStateBlockVec(); StateBlockPtr getStateBlockPtrStatic(unsigned int _i) const; - StateBlockPtr getStateBlockPtrDynamic(unsigned int _i); - StateBlockPtr getStateBlockPtrDynamic(unsigned int _i, const TimeStamp& _ts); + StateBlockPtr getStateBlockPtr(unsigned int _i); + StateBlockPtr getStateBlockPtr(unsigned int _i, const TimeStamp& _ts); void setStateBlockPtrStatic(unsigned int _i, const StateBlockPtr _sb_ptr); void resizeStateBlockVec(unsigned int _size); + bool isStateBlockDynamic(unsigned int _i, const TimeStamp& _ts, CaptureBasePtr& cap); + bool isStateBlockDynamic(unsigned int _i, CaptureBasePtr& cap); + bool isStateBlockDynamic(unsigned int _i, const TimeStamp& _ts); + bool isStateBlockDynamic(unsigned int _i); + StateBlockPtr getPPtr(const TimeStamp _ts); StateBlockPtr getOPtr(const TimeStamp _ts); StateBlockPtr getIntrinsicPtr(const TimeStamp _ts); @@ -133,6 +136,32 @@ class SensorBase : public NodeBase, public std::enable_shared_from_this<SensorBa void fixIntrinsics(); void unfixIntrinsics(); + /** \brief Add an absolute constraint to a parameter + * + * Add an absolute constraint to a parameter + * \param _i state block index (in state_block_vec_) of the parameter to be constrained + * \param _x prior value + * \param _cov covariance + * \param _start_idx state segment starting index (not used in quaternions) + * \param _size state segment size (-1: whole state) (not used in quaternions) + * + **/ + void addPriorParameter(const unsigned int _i, + const Eigen::VectorXs& _x, + const Eigen::MatrixXs& _cov, + unsigned int _start_idx = 0, + int _size = -1); + void addPriorP(const Eigen::VectorXs& _x, + const Eigen::MatrixXs& _cov, + unsigned int _start_idx = 0, + int _size = -1); + void addPriorO(const Eigen::VectorXs& _x, + const Eigen::MatrixXs& _cov); + void addPriorIntrinsics(const Eigen::VectorXs& _x, + const Eigen::MatrixXs& _cov, + unsigned int _start_idx = 0, + int _size = -1); + SizeEigen getCalibSize() const; Eigen::VectorXs getCalibration() const; @@ -196,6 +225,8 @@ inline StateBlockPtr SensorBase::getStateBlockPtrStatic(unsigned int _i) const inline void SensorBase::setStateBlockPtrStatic(unsigned int _i, const StateBlockPtr _sb_ptr) { + assert (_i < state_block_vec_.size() && "Setting a state block pointer out of the vector range!"); + assert((params_prior_map_.find(_i) == params_prior_map_.end() || _sb_ptr == nullptr) && "overwriting a state block that has an absolute constraint"); state_block_vec_[_i] = _sb_ptr; } @@ -252,6 +283,21 @@ inline void SensorBase::setHardwarePtr(const HardwareBasePtr _hw_ptr) hardware_ptr_ = _hw_ptr; } +inline void SensorBase::addPriorP(const Eigen::VectorXs& _x, const Eigen::MatrixXs& _cov, unsigned int _start_idx, int _size) +{ + addPriorParameter(0, _x, _cov, _start_idx, _size); +} + +inline void SensorBase::addPriorO(const Eigen::VectorXs& _x, const Eigen::MatrixXs& _cov) +{ + addPriorParameter(1, _x, _cov); +} + +inline void SensorBase::addPriorIntrinsics(const Eigen::VectorXs& _x, const Eigen::MatrixXs& _cov, unsigned int _start_idx, int _size) +{ + addPriorParameter(2, _x, _cov); +} + inline SizeEigen SensorBase::getCalibSize() const { return calib_size_; diff --git a/include/base/sensor/sensor_camera.h b/include/base/sensor/sensor_camera.h index 2214fc14a317f07c072f64462feac9870388dee6..c7db047c3c28808c9dd40374bdf93adcdd894a2f 100644 --- a/include/base/sensor/sensor_camera.h +++ b/include/base/sensor/sensor_camera.h @@ -12,10 +12,11 @@ WOLF_STRUCT_PTR_TYPEDEFS(IntrinsicsCamera); */ struct IntrinsicsCamera : public IntrinsicsBase { - unsigned int width; ///< Image width in pixels - unsigned int height; ///< Image height in pixels - Eigen::Vector4s pinhole_model; ///< k = [u_0, v_0, alpha_u, alpha_v] vector of pinhole intrinsic parameters - Eigen::VectorXs distortion; ///< d = [d_1, d_2, d_3, ...] radial distortion coefficients + unsigned int width; ///< Image width in pixels + unsigned int height; ///< Image height in pixels + Eigen::Vector4s pinhole_model_raw; ///< k = [u_0, v_0, alpha_u, alpha_v] vector of pinhole intrinsic parameters + Eigen::Vector4s pinhole_model_rectified;///< k = [u_0, v_0, alpha_u, alpha_v] vector of pinhole intrinsic parameters + Eigen::VectorXs distortion; ///< d = [d_1, d_2, d_3, ...] radial distortion coefficients virtual ~IntrinsicsCamera() = default; }; @@ -26,26 +27,20 @@ WOLF_PTR_TYPEDEFS(SensorCamera); class SensorCamera : public SensorBase { public: - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _p_ptr StateBlock pointer to the sensor position wrt vehicle base - * \param _o_ptr StateBlock pointer to the sensor orientation wrt vehicle base - * \param _intr_ptr contains intrinsic values for the camera - * \param _img_width image height in pixels - * \param _img_height image width in pixels - * - **/ - SensorCamera(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, StateBlockPtr _intr_ptr, int _img_width, int _img_height); SensorCamera(const Eigen::VectorXs & _extrinsics, const IntrinsicsCamera& _intrinsics); SensorCamera(const Eigen::VectorXs & _extrinsics, IntrinsicsCameraPtr _intrinsics_ptr); virtual ~SensorCamera(); - Eigen::VectorXs getDistortionVector(){return distortion_;} - Eigen::VectorXs getCorrectionVector(){return correction_;} - Eigen::Matrix3s getIntrinsicMatrix() {return K_;} + Eigen::VectorXs getDistortionVector() { return distortion_; } + Eigen::VectorXs getCorrectionVector() { return correction_; } + Eigen::Matrix3s getIntrinsicMatrix() { return K_; } + + bool isUsingRawImages() { return using_raw_; } + bool useRawImages(); + bool useRectifiedImages(); + int getImgWidth(){return img_width_;} int getImgHeight(){return img_height_;} @@ -57,7 +52,9 @@ class SensorCamera : public SensorBase int img_height_; Eigen::VectorXs distortion_; Eigen::VectorXs correction_; + Eigen::Vector4s pinhole_model_raw_, pinhole_model_rectified_; Eigen::Matrix3s K_; + bool using_raw_; virtual Eigen::Matrix3s setIntrinsicMatrix(Eigen::Vector4s _pinhole_model); @@ -70,6 +67,24 @@ class SensorCamera : public SensorBase }; +inline bool SensorCamera::useRawImages() +{ + getIntrinsicPtr()->setState(pinhole_model_raw_); + K_ = setIntrinsicMatrix(pinhole_model_raw_); + using_raw_ = true; + + return true; +} + +inline bool SensorCamera::useRectifiedImages() +{ + getIntrinsicPtr()->setState(pinhole_model_rectified_); + K_ = setIntrinsicMatrix(pinhole_model_rectified_); + using_raw_ = false; + + return true; +} + } // namespace wolf #endif // SENSOR_CAMERA_H diff --git a/include/base/sensor/sensor_odom_2D.h b/include/base/sensor/sensor_odom_2D.h index 75110b2cd69595555c9a6969f3e3cbbefbf13065..f1528ec377f88f854ee905fbde29e0db5c381265 100644 --- a/include/base/sensor/sensor_odom_2D.h +++ b/include/base/sensor/sensor_odom_2D.h @@ -26,16 +26,6 @@ class SensorOdom2D : public SensorBase Scalar k_rot_to_rot_; ///< ratio of rotation variance to rotation, for odometry noise calculation public: - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _p_ptr StateBlock pointer to the sensor position wrt vehicle base - * \param _o_ptr StateBlock pointer to the sensor orientation wrt vehicle base - * \param _disp_noise_factor displacement noise factor - * \param _rot_noise_factor rotation noise factor - * - **/ - SensorOdom2D(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const Scalar& _disp_noise_factor, const Scalar& _rot_noise_factor); SensorOdom2D(Eigen::VectorXs _extrinsics, const IntrinsicsOdom2D& _intrinsics); SensorOdom2D(Eigen::VectorXs _extrinsics, IntrinsicsOdom2DPtr _intrinsics); diff --git a/include/base/sensor/sensor_odom_3D.h b/include/base/sensor/sensor_odom_3D.h index 76c9a3d5b9e9314e8e45f50f3520175ba03e893b..be3694b2da8b69ad7201d57251f0246deb6dba92 100644 --- a/include/base/sensor/sensor_odom_3D.h +++ b/include/base/sensor/sensor_odom_3D.h @@ -38,14 +38,6 @@ class SensorOdom3D : public SensorBase Scalar min_rot_var_; public: - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _p_ptr StateBlock pointer to the sensor position wrt vehicle base - * \param _o_ptr StateBlock pointer to the sensor orientation wrt vehicle base - * \param _params shared_ptr to a struct with parameters - **/ - SensorOdom3D(StateBlockPtr _p_ptr, StateQuaternionPtr _q_ptr, IntrinsicsOdom3DPtr params); SensorOdom3D(const Eigen::VectorXs& _extrinsics_pq, const IntrinsicsOdom3D& params); SensorOdom3D(const Eigen::VectorXs& _extrinsics_pq, IntrinsicsOdom3DPtr params); diff --git a/src/constraint/constraint_analytic.cpp b/src/constraint/constraint_analytic.cpp index 23ab82362dc7391747099d82b705c6d13b5896c8..9cfb538b1647487968e1e35e73db4af4603bc857 100644 --- a/src/constraint/constraint_analytic.cpp +++ b/src/constraint/constraint_analytic.cpp @@ -7,9 +7,19 @@ ConstraintAnalytic::ConstraintAnalytic(const std::string& _tp, bool _apply_loss_function, ConstraintStatus _status, StateBlockPtr _state0Ptr, StateBlockPtr _state1Ptr, StateBlockPtr _state2Ptr, StateBlockPtr _state3Ptr, StateBlockPtr _state4Ptr, StateBlockPtr _state5Ptr, StateBlockPtr _state6Ptr, StateBlockPtr _state7Ptr, StateBlockPtr _state8Ptr, StateBlockPtr _state9Ptr ) : - ConstraintBase(_tp, _apply_loss_function, _status), - state_ptr_vector_({_state0Ptr, _state1Ptr, _state2Ptr, _state3Ptr, _state4Ptr, - _state5Ptr, _state6Ptr, _state7Ptr, _state8Ptr, _state9Ptr}) + ConstraintBase(_tp, _apply_loss_function, _status), + state_ptr_vector_({_state0Ptr, _state1Ptr, _state2Ptr, _state3Ptr, _state4Ptr, + _state5Ptr, _state6Ptr, _state7Ptr, _state8Ptr, _state9Ptr}), + state_block_sizes_vector_({_state0Ptr ? (unsigned int) _state0Ptr->getSize() : 0, + _state1Ptr ? (unsigned int) _state1Ptr->getSize() : 0, + _state2Ptr ? (unsigned int) _state2Ptr->getSize() : 0, + _state3Ptr ? (unsigned int) _state3Ptr->getSize() : 0, + _state4Ptr ? (unsigned int) _state4Ptr->getSize() : 0, + _state5Ptr ? (unsigned int) _state5Ptr->getSize() : 0, + _state6Ptr ? (unsigned int) _state6Ptr->getSize() : 0, + _state7Ptr ? (unsigned int) _state7Ptr->getSize() : 0, + _state8Ptr ? (unsigned int) _state8Ptr->getSize() : 0, + _state9Ptr ? (unsigned int) _state9Ptr->getSize() : 0}) { resizeVectors(); } @@ -23,9 +33,19 @@ ConstraintAnalytic::ConstraintAnalytic(const std::string& _tp, bool _apply_loss_function, ConstraintStatus _status, StateBlockPtr _state0Ptr, StateBlockPtr _state1Ptr, StateBlockPtr _state2Ptr, StateBlockPtr _state3Ptr, StateBlockPtr _state4Ptr, StateBlockPtr _state5Ptr, StateBlockPtr _state6Ptr, StateBlockPtr _state7Ptr, StateBlockPtr _state8Ptr, StateBlockPtr _state9Ptr ) : - ConstraintBase(_tp, _frame_other_ptr, _capture_other_ptr, _feature_other_ptr, _landmark_other_ptr, _processor_ptr, _apply_loss_function, _status), - state_ptr_vector_({_state0Ptr, _state1Ptr, _state2Ptr, _state3Ptr, _state4Ptr, - _state5Ptr, _state6Ptr, _state7Ptr, _state8Ptr, _state9Ptr}) + ConstraintBase(_tp, _frame_other_ptr, _capture_other_ptr, _feature_other_ptr, _landmark_other_ptr, _processor_ptr, _apply_loss_function, _status), + state_ptr_vector_({_state0Ptr, _state1Ptr, _state2Ptr, _state3Ptr, _state4Ptr, + _state5Ptr, _state6Ptr, _state7Ptr, _state8Ptr, _state9Ptr}), + state_block_sizes_vector_({_state0Ptr ? (unsigned int) _state0Ptr->getSize() : 0, + _state1Ptr ? (unsigned int) _state1Ptr->getSize() : 0, + _state2Ptr ? (unsigned int) _state2Ptr->getSize() : 0, + _state3Ptr ? (unsigned int) _state3Ptr->getSize() : 0, + _state4Ptr ? (unsigned int) _state4Ptr->getSize() : 0, + _state5Ptr ? (unsigned int) _state5Ptr->getSize() : 0, + _state6Ptr ? (unsigned int) _state6Ptr->getSize() : 0, + _state7Ptr ? (unsigned int) _state7Ptr->getSize() : 0, + _state8Ptr ? (unsigned int) _state8Ptr->getSize() : 0, + _state9Ptr ? (unsigned int) _state9Ptr->getSize() : 0}) { resizeVectors(); } @@ -58,17 +78,15 @@ JacobianMethod ConstraintAnalytic::getJacobianMethod() const void ConstraintAnalytic::resizeVectors() { - for (unsigned int ii = 1; ii<state_ptr_vector_.size(); ii++) - { - if (state_ptr_vector_.at(ii) != nullptr) - state_block_sizes_vector_.push_back(state_ptr_vector_.at(ii)->getSize()); + assert(state_ptr_vector_[0] != nullptr && "at least one not null state block pointer required"); - else + for (unsigned int ii = 1; ii<state_ptr_vector_.size(); ii++) + if (state_ptr_vector_.at(ii) == nullptr) { state_ptr_vector_.resize(ii); + state_block_sizes_vector_.resize(ii); break; } - } } } // namespace wolf diff --git a/src/examples/test_wolf_factories.cpp b/src/examples/test_wolf_factories.cpp index 4108864a7319361776556d02a9efe43277643623..3ada8333437f02034267943e68a4ab2c8bf57517 100644 --- a/src/examples/test_wolf_factories.cpp +++ b/src/examples/test_wolf_factories.cpp @@ -62,7 +62,7 @@ int main(void) IntrinsicsBasePtr intr_cam_ptr = IntrinsicsFactory::get().create("CAMERA", wolf_config + "/camera_params_ueye_sim.yaml"); ProcessorParamsBasePtr params_ptr = ProcessorParamsFactory::get().create("IMAGE FEATURE", wolf_config + "/processor_image_feature.yaml"); - cout << "CAMERA with intrinsics : " << (static_pointer_cast<IntrinsicsCamera>(intr_cam_ptr))->pinhole_model.transpose() << endl; + cout << "CAMERA with intrinsics : " << (static_pointer_cast<IntrinsicsCamera>(intr_cam_ptr))->pinhole_model_raw.transpose() << endl; // cout << "Processor IMAGE image width : " << (static_pointer_cast<ProcessorParamsImage>(params_ptr))->image.width << endl; cout << "\n==================== Install Sensors ====================" << endl; diff --git a/src/problem.cpp b/src/problem.cpp index 40ef35f2f1b2c7a044736b85cce3c5f98a4d492c..d96a1d29065a18815bd99eb65245856e89cde66d 100644 --- a/src/problem.cpp +++ b/src/problem.cpp @@ -4,17 +4,14 @@ #include "base/trajectory_base.h" #include "base/map_base.h" #include "base/sensor/sensor_base.h" -#include "base/factory.h" +#include "base/processor/processor_motion.h" +#include "base/processor/processor_tracker.h" +#include "base/capture/capture_pose.h" +#include "base/constraint/constraint_base.h" #include "base/sensor/sensor_factory.h" #include "base/processor/processor_factory.h" -#include "base/constraint/constraint_base.h" #include "base/state_block.h" -#include "base/processor/processor_motion.h" -#include "base/sensor/sensor_GPS.h" -#include "base/processor/processor_tracker.h" -//#include "processors/processor_tracker_feature_trifocal.h" -#include "base/capture/capture_pose.h" // IRI libs includes @@ -749,7 +746,7 @@ void Problem::print(int depth, bool constr_by, bool metric, bool state_blocks) { if (i==0) cout << " Extr " << (S->isExtrinsicDynamic() ? "[Dyn]" : "[Sta]") << " = ["; if (i==2) cout << " Intr " << (S->isIntrinsicDynamic() ? "[Dyn]" : "[Sta]") << " = ["; - auto sb = S->getStateBlockPtrDynamic(i); + auto sb = S->getStateBlockPtr(i); if (sb) { cout << (sb->isFixed() ? " Fix( " : " Est( ") << sb->getState().transpose() << " )"; diff --git a/src/processor/processor_base.cpp b/src/processor/processor_base.cpp index aa259d706262904969e9e27245a50e06456584a0..60569422e15f307d04dc9f6f8c350eea313643af 100644 --- a/src/processor/processor_base.cpp +++ b/src/processor/processor_base.cpp @@ -8,7 +8,7 @@ namespace wolf { unsigned int ProcessorBase::processor_id_count_ = 0; ProcessorBase::ProcessorBase(const std::string& _type, ProcessorParamsBasePtr _params) : - NodeBase("PROCESSOR", _type, _params->name), + NodeBase("PROCESSOR", _type), processor_id_(++processor_id_count_), params_(_params), sensor_ptr_() diff --git a/src/processor/processor_odom_2D.cpp b/src/processor/processor_odom_2D.cpp index c375d52faca184c57b3dad8976aac24c9decaca5..2c5bfe456d0d31e1be0460faf0c8df78b2922556 100644 --- a/src/processor/processor_odom_2D.cpp +++ b/src/processor/processor_odom_2D.cpp @@ -21,7 +21,7 @@ void ProcessorOdom2D::computeCurrentDelta(const Eigen::VectorXs& _data, const Ei assert(_data_cov.rows() == data_size_ && "Wrong _data_cov size"); assert(_data_cov.cols() == data_size_ && "Wrong _data_cov size"); - // data is [dtheta, dr] + // data is [dr, dtheta] // delta is [dx, dy, dtheta] // motion model is 1/2 turn + straight + 1/2 turn _delta(0) = cos(_data(1) / 2) * _data(0); diff --git a/src/processor/processor_tracker_feature_trifocal.cpp b/src/processor/processor_tracker_feature_trifocal.cpp index 03cd93f17f9a21b33493cc1cf76a45046061cb4a..30018991042f601481d15289a0bf008aa9dc6501 100644 --- a/src/processor/processor_tracker_feature_trifocal.cpp +++ b/src/processor/processor_tracker_feature_trifocal.cpp @@ -37,7 +37,6 @@ ProcessorTrackerFeatureTrifocal::ProcessorTrackerFeatureTrifocal(ProcessorParams prev_origin_ptr_(nullptr), initialized_(false) { - setName(_params_tracker_feature_trifocal->name); assert(!(params_tracker_feature_trifocal_->yaml_file_params_vision_utils.empty()) && "Missing YAML file with vision_utils parameters!"); assert(file_exists(params_tracker_feature_trifocal_->yaml_file_params_vision_utils) && "Cannot setup processor: vision_utils' YAML file does not exist."); diff --git a/src/sensor/sensor_GPS_fix.cpp b/src/sensor/sensor_GPS_fix.cpp index 788dc06dc58023d6502d01a2d01029b0bf96af5f..427dc45182c9c5efa9319a0e56ca9bebf21922eb 100644 --- a/src/sensor/sensor_GPS_fix.cpp +++ b/src/sensor/sensor_GPS_fix.cpp @@ -4,12 +4,6 @@ namespace wolf { -SensorGPSFix::SensorGPSFix(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const double& _noise) : - SensorBase("GPS FIX", _p_ptr, _o_ptr, nullptr, Eigen::VectorXs::Constant(1,_noise)) -{ - // -} - SensorGPSFix::SensorGPSFix(const Eigen::VectorXs & _extrinsics, const IntrinsicsGPSFix& _intrinsics) : SensorBase("GPS FIX", std::make_shared<StateBlock>(_extrinsics.head(3), true), std::make_shared<StateQuaternion>(_extrinsics.tail(4), true), nullptr, _intrinsics.noise_std) { @@ -17,7 +11,8 @@ SensorGPSFix::SensorGPSFix(const Eigen::VectorXs & _extrinsics, const Intrinsics && "Bad extrinsic vector size. Should be 2 for 2D, 3 for 3D."); } -SensorGPSFix::SensorGPSFix(const Eigen::VectorXs & _extrinsics, IntrinsicsGPSFixPtr _intrinsics_ptr) : SensorGPSFix(_extrinsics, *_intrinsics_ptr) +SensorGPSFix::SensorGPSFix(const Eigen::VectorXs & _extrinsics, IntrinsicsGPSFixPtr _intrinsics_ptr) : + SensorGPSFix(_extrinsics, *_intrinsics_ptr) { // } @@ -33,8 +28,8 @@ SensorBasePtr SensorGPSFix::create(const std::string& _unique_name, const Eigen: { assert((_extrinsics.size() == 2 || _extrinsics.size() == 3) && "Bad extrinsic vector size. Should be 2 for 2D, 3 for 3D."); - StateBlockPtr pos_ptr = std::make_shared<StateBlock>(_extrinsics, true); - SensorGPSFixPtr sen = std::make_shared<SensorGPSFix>(pos_ptr, nullptr, 0); + SensorGPSFixPtr sen = std::make_shared<SensorGPSFix>(_extrinsics, std::static_pointer_cast<IntrinsicsGPSFix>(_intrinsics)); + sen->getPPtr()->fix(); sen->setName(_unique_name); return sen; } diff --git a/src/sensor/sensor_IMU.cpp b/src/sensor/sensor_IMU.cpp index 94a30bb4347f0f42c137393b7e9df4b08cda1ae0..f97edf645e607b08534ca421db1bd09070bf8d70 100644 --- a/src/sensor/sensor_IMU.cpp +++ b/src/sensor/sensor_IMU.cpp @@ -4,24 +4,6 @@ namespace wolf { -SensorIMU::SensorIMU(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const IntrinsicsIMU& _params) : - SensorBase("IMU", _p_ptr, _o_ptr, std::make_shared<StateBlock>(6, false, nullptr), (Eigen::Vector6s()<<_params.a_noise,_params.a_noise,_params.a_noise,_params.w_noise,_params.w_noise,_params.w_noise).finished(), false, true), - a_noise(_params.a_noise), - w_noise(_params.w_noise), - ab_initial_stdev(_params.ab_initial_stdev), - wb_initial_stdev(_params.wb_initial_stdev), - ab_rate_stdev(_params.ab_rate_stdev), - wb_rate_stdev(_params.wb_rate_stdev) -{ - // -} - -SensorIMU::SensorIMU(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, IntrinsicsIMUPtr _params) : - SensorIMU(_p_ptr, _o_ptr, *_params) -{ - // -} - SensorIMU::SensorIMU(const Eigen::VectorXs& _extrinsics, IntrinsicsIMUPtr _params) : SensorIMU(_extrinsics, *_params) { diff --git a/src/sensor/sensor_base.cpp b/src/sensor/sensor_base.cpp index a05fec1ceb4b1b90912dd4ec380212848c68f98b..92616d53373d40c081638ddf0433a83692d575ae 100644 --- a/src/sensor/sensor_base.cpp +++ b/src/sensor/sensor_base.cpp @@ -1,5 +1,9 @@ #include "base/sensor/sensor_base.h" #include "base/state_block.h" +#include "base/state_quaternion.h" +#include "base/constraint/constraint_block_absolute.h" +#include "base/constraint/constraint_quaternion_absolute.h" + namespace wolf { @@ -62,30 +66,6 @@ SensorBase::~SensorBase() removeStateBlocks(); } -void SensorBase::remove() -{ - if (!is_removing_) - { - is_removing_ = true; - SensorBasePtr this_S = shared_from_this(); // protect it while removing links - - // Remove State Blocks - removeStateBlocks(); - - // remove from upstream - auto H = hardware_ptr_.lock(); - if (H) - H->getSensorList().remove(this_S); - - // remove downstream processors - while (!processor_list_.empty()) - { - processor_list_.front()->remove(); - } - } - -} - void SensorBase::removeStateBlocks() { for (unsigned int i = 0; i < state_block_vec_.size(); i++) @@ -162,6 +142,50 @@ void SensorBase::unfixIntrinsics() updateCalibSize(); } +void SensorBase::addPriorParameter(const unsigned int _i, const Eigen::VectorXs& _x, const Eigen::MatrixXs& _cov, unsigned int _start_idx, int _size) +{ + assert(!isStateBlockDynamic(_i) && "SensorBase::addPriorParameter only allowed for static parameters"); + assert(_i < state_block_vec_.size() && "State block not found"); + + StateBlockPtr _sb = getStateBlockPtrStatic(_i); + bool is_quaternion = (std::dynamic_pointer_cast<StateQuaternion>(_sb) != nullptr); + + assert(((!is_quaternion && _x.size() == _cov.rows() && _x.size() == _cov.cols()) || + (is_quaternion && _x.size() == 4 &&_cov.rows() == 3 && _cov.cols() == 3)) && "bad prior/covariance dimensions"); + assert((_size == -1 && _start_idx == 0) || (_size+_start_idx <= _sb->getSize())); + assert(_size == -1 || _size == _x.size()); + assert(!(_size != -1 && is_quaternion) && "prior of a segment of state not available for quaternion"); + + // set StateBlock state + if (_size == -1) + _sb->setState(_x); + else + { + Eigen::VectorXs new_x = _sb->getState(); + new_x.segment(_start_idx,_size) = _x; + _sb->setState(new_x); + } + + // remove previous prior (if any) + if (params_prior_map_.find(_i) != params_prior_map_.end()) + params_prior_map_[_i]->remove(); + + // create feature + FeatureBasePtr ftr_prior = std::make_shared<FeatureBase>("ABSOLUTE",_x,_cov); + + // set feature problem + ftr_prior->setProblem(getProblem()); + + // create & add constraint absolute + if (is_quaternion) + ftr_prior->addConstraint(std::make_shared<ConstraintQuaternionAbsolute>(_sb)); + else + ftr_prior->addConstraint(std::make_shared<ConstraintBlockAbsolute>(_sb, _start_idx, _size)); + + // store feature in params_prior_map_ + params_prior_map_[_i] = ftr_prior; +} + void SensorBase::registerNewStateBlocks() { if (getProblem() != nullptr) @@ -238,32 +262,32 @@ CaptureBasePtr SensorBase::lastCapture(const TimeStamp& _ts) StateBlockPtr SensorBase::getPPtr(const TimeStamp _ts) { - return getStateBlockPtrDynamic(0, _ts); + return getStateBlockPtr(0, _ts); } StateBlockPtr SensorBase::getOPtr(const TimeStamp _ts) { - return getStateBlockPtrDynamic(1, _ts); + return getStateBlockPtr(1, _ts); } StateBlockPtr SensorBase::getIntrinsicPtr(const TimeStamp _ts) { - return getStateBlockPtrDynamic(2, _ts); + return getStateBlockPtr(2, _ts); } StateBlockPtr SensorBase::getPPtr() { - return getStateBlockPtrDynamic(0); + return getStateBlockPtr(0); } StateBlockPtr SensorBase::getOPtr() { - return getStateBlockPtrDynamic(1); + return getStateBlockPtr(1); } StateBlockPtr SensorBase::getIntrinsicPtr() { - return getStateBlockPtrDynamic(2); + return getStateBlockPtr(2); } SizeEigen SensorBase::computeCalibSize() const @@ -315,32 +339,62 @@ ProcessorBasePtr SensorBase::addProcessor(ProcessorBasePtr _proc_ptr) return _proc_ptr; } -StateBlockPtr SensorBase::getStateBlockPtrDynamic(unsigned int _i) +StateBlockPtr SensorBase::getStateBlockPtr(unsigned int _i) +{ + CaptureBasePtr cap; + + if (isStateBlockDynamic(_i, cap)) + return cap->getStateBlockPtr(_i); + + return getStateBlockPtrStatic(_i); +} + +StateBlockPtr SensorBase::getStateBlockPtr(unsigned int _i, const TimeStamp& _ts) +{ + CaptureBasePtr cap; + + if (isStateBlockDynamic(_i, _ts, cap)) + return cap->getStateBlockPtr(_i); + + return getStateBlockPtrStatic(_i); +} + +bool SensorBase::isStateBlockDynamic(unsigned int _i, CaptureBasePtr& cap) { if ((_i<2 && this->extrinsicsInCaptures()) || (_i>=2 && intrinsicsInCaptures())) { - CaptureBasePtr cap = lastKeyCapture(); - if (cap) - return cap->getStateBlockPtr(_i); - else - return getStateBlockPtrStatic(_i); + cap = lastKeyCapture(); + + return cap != nullptr; } else - return getStateBlockPtrStatic(_i); + return false; } -StateBlockPtr SensorBase::getStateBlockPtrDynamic(unsigned int _i, const TimeStamp& _ts) +bool SensorBase::isStateBlockDynamic(unsigned int _i, const TimeStamp& _ts, CaptureBasePtr& cap) { if ((_i<2 && this->extrinsicsInCaptures()) || (_i>=2 && intrinsicsInCaptures())) { - CaptureBasePtr cap = lastCapture(_ts); - if (cap) - return cap->getStateBlockPtr(_i); - else - return getStateBlockPtrStatic(_i); + cap = lastCapture(_ts); + + return cap != nullptr; } else - return getStateBlockPtrStatic(_i); + return false; +} + +bool SensorBase::isStateBlockDynamic(unsigned int _i) +{ + CaptureBasePtr cap; + + return isStateBlockDynamic(_i,cap); +} + +bool SensorBase::isStateBlockDynamic(unsigned int _i, const TimeStamp& _ts) +{ + CaptureBasePtr cap; + + return isStateBlockDynamic(_i,_ts,cap); } void SensorBase::setProblem(ProblemPtr _problem) diff --git a/src/sensor/sensor_camera.cpp b/src/sensor/sensor_camera.cpp index 3a3dae9bd4a3064517c150cbe808a4a24b43061f..6e20ff960177e9be75bef2dfc4342cdb96b23bc8 100644 --- a/src/sensor/sensor_camera.cpp +++ b/src/sensor/sensor_camera.cpp @@ -7,23 +7,18 @@ namespace wolf { -SensorCamera::SensorCamera(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, StateBlockPtr _intr_ptr, // - int _img_width, int _img_height) : - SensorBase("CAMERA", _p_ptr, _o_ptr, _intr_ptr, 2), // - img_width_(_img_width), img_height_(_img_height) -{ - // -} - SensorCamera::SensorCamera(const Eigen::VectorXs& _extrinsics, const IntrinsicsCamera& _intrinsics) : - SensorBase("CAMERA", std::make_shared<StateBlock>(_extrinsics.head(3), true), std::make_shared<StateQuaternion>(_extrinsics.tail(4), true), std::make_shared<StateBlock>(_intrinsics.pinhole_model, true), 1), + SensorBase("CAMERA", std::make_shared<StateBlock>(_extrinsics.head(3), true), std::make_shared<StateQuaternion>(_extrinsics.tail(4), true), std::make_shared<StateBlock>(_intrinsics.pinhole_model_raw, true), 1), img_width_(_intrinsics.width), // img_height_(_intrinsics.height), // distortion_(_intrinsics.distortion), // - correction_(distortion_.size()+2) // make correction vector of the same size as distortion vector + correction_(distortion_.size() + 1), // make correction vector slightly larger in size than the distortion vector + pinhole_model_raw_(_intrinsics.pinhole_model_raw), // + pinhole_model_rectified_(_intrinsics.pinhole_model_rectified), // + using_raw_(true) { assert(_extrinsics.size() == 7 && "Wrong intrinsics vector size. Should be 7 for 3D"); - K_ = setIntrinsicMatrix(_intrinsics.pinhole_model); + useRawImages(); pinhole::computeCorrectionModel(getIntrinsicPtr()->getState(), distortion_, correction_); } @@ -69,7 +64,6 @@ SensorBasePtr SensorCamera::create(const std::string& _unique_name, // // Register in the SensorFactory #include "base/sensor/sensor_factory.h" -//#include "base/factory.h" namespace wolf { WOLF_REGISTER_SENSOR("CAMERA", SensorCamera) diff --git a/src/sensor/sensor_odom_2D.cpp b/src/sensor/sensor_odom_2D.cpp index 7f0abaed4648650da90136d189c34b9d5a7c66f4..c698db52f69d668ca7bab3c522087cb168047d10 100644 --- a/src/sensor/sensor_odom_2D.cpp +++ b/src/sensor/sensor_odom_2D.cpp @@ -4,14 +4,6 @@ namespace wolf { -SensorOdom2D::SensorOdom2D(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, const Scalar& _disp_noise_factor, const Scalar& _rot_noise_factor) : - SensorBase("ODOM 2D", _p_ptr, _o_ptr, nullptr, 2), - k_disp_to_disp_(_disp_noise_factor), - k_rot_to_rot_(_rot_noise_factor) -{ - // -} - SensorOdom2D::SensorOdom2D(Eigen::VectorXs _extrinsics, const IntrinsicsOdom2D& _intrinsics) : SensorBase("ODOM 2D", std::make_shared<StateBlock>(_extrinsics.head(2), true), std::make_shared<StateAngle>(_extrinsics(2), true), nullptr, 2), k_disp_to_disp_(_intrinsics.k_disp_to_disp), diff --git a/src/sensor/sensor_odom_3D.cpp b/src/sensor/sensor_odom_3D.cpp index aa6efc42b82aac106dbb39c509bcb382d77cd2b8..0a5c2d7961b5d36e171e6b9d29fafdc30580a74e 100644 --- a/src/sensor/sensor_odom_3D.cpp +++ b/src/sensor/sensor_odom_3D.cpp @@ -12,18 +12,6 @@ namespace wolf { -SensorOdom3D::SensorOdom3D(StateBlockPtr _p_ptr, StateQuaternionPtr _o_ptr, IntrinsicsOdom3DPtr _params) : - SensorBase("ODOM 3D", _p_ptr, _o_ptr, nullptr, 6), - k_disp_to_disp_(_params->k_disp_to_disp), - k_disp_to_rot_(_params->k_disp_to_rot), - k_rot_to_rot_(_params->k_rot_to_rot), - min_disp_var_(_params->min_disp_var), - min_rot_var_(_params->min_rot_var) -{ - noise_cov_ = (Eigen::Vector6s() << min_disp_var_, min_disp_var_, min_disp_var_, min_rot_var_, min_rot_var_, min_rot_var_).finished().asDiagonal(); - setNoiseCov(noise_cov_); // sets also noise_std_ -} - SensorOdom3D::SensorOdom3D(const Eigen::VectorXs& _extrinsics_pq, const IntrinsicsOdom3D& _intrinsics) : SensorBase("ODOM 3D", std::make_shared<StateBlock>(_extrinsics_pq.head(3), true), std::make_shared<StateQuaternion>(_extrinsics_pq.tail(4), true), nullptr, 6), k_disp_to_disp_(_intrinsics.k_disp_to_disp), diff --git a/src/yaml/processor_IMU_yaml.cpp b/src/yaml/processor_IMU_yaml.cpp index 38b83b82f3908983df2f0ad27867bbfe818064a2..2cfc70f46321ea3af69d657b47540258b4b17ebd 100644 --- a/src/yaml/processor_IMU_yaml.cpp +++ b/src/yaml/processor_IMU_yaml.cpp @@ -26,18 +26,10 @@ static ProcessorParamsBasePtr createProcessorIMUParams(const std::string & _file if (config["processor type"].as<std::string>() == "IMU") { - - // YAML:: to Eigen:: - using namespace Eigen; - std::string processor_type = config["processor type"] .as<std::string>(); - std::string processor_name = config["processor name"] .as<std::string>(); - YAML::Node kf_vote = config["keyframe vote"]; ProcessorParamsIMUPtr params = std::make_shared<ProcessorParamsIMU>(); - params->type = processor_type; - params->name = processor_name; params->max_time_span = kf_vote["max time span"] .as<Scalar>(); params->max_buff_length = kf_vote["max buffer length"] .as<SizeEigen >(); params->dist_traveled = kf_vote["dist traveled"] .as<Scalar>(); diff --git a/src/yaml/processor_odom_3D_yaml.cpp b/src/yaml/processor_odom_3D_yaml.cpp index af8934b07d182dab640a70b7f53511ce75abb447..5c2172ea9f26c3561f7fc48c5c56d4be7695ed1c 100644 --- a/src/yaml/processor_odom_3D_yaml.cpp +++ b/src/yaml/processor_odom_3D_yaml.cpp @@ -26,18 +26,10 @@ static ProcessorParamsBasePtr createProcessorOdom3DParams(const std::string & _f if (config["processor type"].as<std::string>() == "ODOM 3D") { - - // YAML:: to Eigen:: - using namespace Eigen; - std::string processor_type = config["processor type"] .as<std::string>(); - std::string processor_name = config["processor name"] .as<std::string>(); - YAML::Node kf_vote = config["keyframe vote"]; ProcessorParamsOdom3DPtr params = std::make_shared<ProcessorParamsOdom3D>(); - params->type = processor_type; - params->name = processor_name; params->max_time_span = kf_vote["max time span"] .as<Scalar>(); params->max_buff_length = kf_vote["max buffer length"] .as<SizeEigen >(); params->dist_traveled = kf_vote["dist traveled"] .as<Scalar>(); diff --git a/src/yaml/processor_tracker_feature_trifocal_yaml.cpp b/src/yaml/processor_tracker_feature_trifocal_yaml.cpp index fd110aa0e142745558c4f3ec69ee71ea525c76cb..2337df07c51f3dd1027d5e1b6004ca426221b722 100644 --- a/src/yaml/processor_tracker_feature_trifocal_yaml.cpp +++ b/src/yaml/processor_tracker_feature_trifocal_yaml.cpp @@ -33,9 +33,6 @@ static ProcessorParamsBasePtr createProcessorParamsTrackerFeatureTrifocal(const { ProcessorParamsTrackerFeatureTrifocalPtr params = std::make_shared<ProcessorParamsTrackerFeatureTrifocal>(); - params->type = config["processor type"].as<std::string>(); - params->name = config["processor name"].as<std::string>(); - YAML::Node vision_utils = config ["vision_utils"]; params->yaml_file_params_vision_utils = vision_utils["YAML file params"].as<std::string>(); diff --git a/src/yaml/sensor_IMU_yaml.cpp b/src/yaml/sensor_IMU_yaml.cpp index c64914c6054aca6cd27513085289903dabdf051c..cc3dbb649b7d2c14c92ec4e78f2d43c0c343b254 100644 --- a/src/yaml/sensor_IMU_yaml.cpp +++ b/src/yaml/sensor_IMU_yaml.cpp @@ -27,23 +27,17 @@ static IntrinsicsBasePtr createIntrinsicsIMU(const std::string & _filename_dot_y if (config["sensor type"].as<std::string>() == "IMU") { - - // YAML:: to Eigen:: - using namespace Eigen; - std::string sensor_type = config["sensor type"] .as<std::string>(); - std::string sensor_name = config["sensor name"] .as<std::string>(); - - YAML::Node variances = config["motion variances"]; - YAML::Node kf_vote = config["keyframe vote"]; + YAML::Node variances = config["motion variances"]; + YAML::Node kf_vote = config["keyframe vote"]; IntrinsicsIMUPtr params = std::make_shared<IntrinsicsIMU>(); - params->a_noise = variances["a_noise"] .as<Scalar>(); - params->w_noise = variances["w_noise"] .as<Scalar>(); - params->ab_initial_stdev = variances["ab_initial_stdev"] .as<Scalar>(); - params->wb_initial_stdev = variances["wb_initial_stdev"] .as<Scalar>(); - params->ab_rate_stdev = variances["ab_rate_stdev"] .as<Scalar>(); - params->wb_rate_stdev = variances["wb_rate_stdev"] .as<Scalar>(); + params->a_noise = variances["a_noise"] .as<Scalar>(); + params->w_noise = variances["w_noise"] .as<Scalar>(); + params->ab_initial_stdev = variances["ab_initial_stdev"] .as<Scalar>(); + params->wb_initial_stdev = variances["wb_initial_stdev"] .as<Scalar>(); + params->ab_rate_stdev = variances["ab_rate_stdev"] .as<Scalar>(); + params->wb_rate_stdev = variances["wb_rate_stdev"] .as<Scalar>(); return params; } diff --git a/src/yaml/sensor_camera_yaml.cpp b/src/yaml/sensor_camera_yaml.cpp index d1a76b78b6a58c46f68480d8efd1a5b0fe4ce663..5e5e3df19cd91a8735f6625ecd2d551deb7e7b77 100644 --- a/src/yaml/sensor_camera_yaml.cpp +++ b/src/yaml/sensor_camera_yaml.cpp @@ -24,40 +24,58 @@ static IntrinsicsBasePtr createIntrinsicsCamera(const std::string & _filename_do { YAML::Node camera_config = YAML::LoadFile(_filename_dot_yaml); - if ("CAMERA") //camera_config["sensor type"]) + // if (camera_config["sensor type"].as<std::string>() == "CAMERA") // this does not work: camera YAML files are ROS-styled + if (camera_config["camera_matrix"]) // check that at least this field exists to validate YAML file of the correct type { // YAML:: to Eigen:: using namespace Eigen; - std::string sensor_type = "CAMERA"; //camera_config["sensor type"] .as<std::string>(); - std::string sensor_name = camera_config["camera_name"] .as<std::string>(); unsigned int width = camera_config["image_width"] .as<unsigned int>(); unsigned int height = camera_config["image_height"] .as<unsigned int>(); - VectorXd intrinsic = camera_config["camera_matrix"]["data"] .as<VectorXd>(); VectorXd distortion = camera_config["distortion_coefficients"]["data"] .as<VectorXd>(); + VectorXd intrinsic = camera_config["camera_matrix"]["data"] .as<VectorXd>(); + VectorXd projection = camera_config["projection_matrix"]["data"] .as<VectorXd>(); // Eigen:: to wolf:: std::shared_ptr<IntrinsicsCamera> intrinsics_cam = std::make_shared<IntrinsicsCamera>(); - intrinsics_cam->type = sensor_type; - intrinsics_cam->name = sensor_name; - intrinsics_cam->pinhole_model[0] = intrinsic[2]; - intrinsics_cam->pinhole_model[1] = intrinsic[5]; - intrinsics_cam->pinhole_model[2] = intrinsic[0]; - intrinsics_cam->pinhole_model[3] = intrinsic[4]; + + intrinsics_cam->width = width; + intrinsics_cam->height = height; + + intrinsics_cam->pinhole_model_raw[0] = intrinsic[2]; + intrinsics_cam->pinhole_model_raw[1] = intrinsic[5]; + intrinsics_cam->pinhole_model_raw[2] = intrinsic[0]; + intrinsics_cam->pinhole_model_raw[3] = intrinsic[4]; + + intrinsics_cam->pinhole_model_rectified[0] = projection[2]; + intrinsics_cam->pinhole_model_rectified[1] = projection[6]; + intrinsics_cam->pinhole_model_rectified[2] = projection[0]; + intrinsics_cam->pinhole_model_rectified[3] = projection[5]; + assert (distortion.size() == 5 && "Distortion size must be size 5!"); - assert (distortion(2) == 0 && distortion(3) == 0 && "Cannot handle tangential distortion. Please re-calibrate without tangential distortion!"); + + WOLF_WARN_COND( distortion(2) != 0 || distortion(3) != 0 , "Wolf does not handle tangential distortion. Please consider re-calibrating without tangential distortion!"); + if (distortion(4) == 0) - intrinsics_cam->distortion = distortion.head<2>(); + if (distortion(1) == 0) + if (distortion(0) == 0) + intrinsics_cam->distortion.resize(0); + else + { + intrinsics_cam->distortion.resize(1); + intrinsics_cam->distortion = distortion.head<1>(); + } + else + { + intrinsics_cam->distortion.resize(2); + intrinsics_cam->distortion = distortion.head<2>(); + } else { - unsigned int dist_size = distortion.size() - 2; - unsigned int dist_tail_size = dist_size - 2; - intrinsics_cam->distortion.resize(dist_size); + intrinsics_cam->distortion.resize(3); intrinsics_cam->distortion.head<2>() = distortion.head<2>(); - intrinsics_cam->distortion.tail(dist_tail_size) = distortion.tail(dist_tail_size); + intrinsics_cam->distortion.tail<1>() = distortion.tail<1>(); } - intrinsics_cam->width = width; - intrinsics_cam->height = height; //========================================= // ===== this part for debugging only ===== @@ -83,7 +101,7 @@ static IntrinsicsBasePtr createIntrinsicsCamera(const std::string & _filename_do return intrinsics_cam; } - std::cout << "Bad configuration file. No sensor type found." << std::endl; + std::cout << "Bad configuration file. No or bad sensor type found." << std::endl; return nullptr; } diff --git a/src/yaml/sensor_laser_2D_yaml.cpp b/src/yaml/sensor_laser_2D_yaml.cpp index 6a6b3f4ae06efdec4b8b48750a4e8f3bde22328c..e687c14463b746d147d791338afc5e34120fe8f3 100644 --- a/src/yaml/sensor_laser_2D_yaml.cpp +++ b/src/yaml/sensor_laser_2D_yaml.cpp @@ -22,9 +22,9 @@ namespace { // intrinsics creator IntrinsicsBasePtr createIntrinsicsLaser2D(const std::string& _filename_dot_yaml) { - // TODO: Parse YAML <-- maybe we want this out of this file? + // If required: Parse YAML + IntrinsicsLaser2DPtr params; // dummy - params->type = "LASER 2D"; // fill this one just for the fun of it return params; } diff --git a/src/yaml/sensor_odom_3D_yaml.cpp b/src/yaml/sensor_odom_3D_yaml.cpp index f423169a9a013c2c2251f8bc10c7597abe13a079..63a7baa2c4cad96e3ca297950df76611fb4ed7ba 100644 --- a/src/yaml/sensor_odom_3D_yaml.cpp +++ b/src/yaml/sensor_odom_3D_yaml.cpp @@ -26,14 +26,7 @@ static IntrinsicsBasePtr createIntrinsicsOdom3D(const std::string & _filename_do if (config["sensor type"].as<std::string>() == "ODOM 3D") { - - // YAML:: to Eigen:: - using namespace Eigen; - std::string sensor_type = config["sensor type"] .as<std::string>(); - std::string sensor_name = config["sensor name"] .as<std::string>(); - YAML::Node variances = config["motion variances"]; - YAML::Node kf_vote = config["keyframe vote"]; IntrinsicsOdom3DPtr params = std::make_shared<IntrinsicsOdom3D>(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cd99f0476dfe9eacbf0b7b63566f9306def8e554..47e53807a4afa37b9fe04e6cb80fb702ad007986 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -102,6 +102,10 @@ wolf_add_gtest(gtest_SE3 gtest_SE3.cpp) wolf_add_gtest(gtest_sensor_base gtest_sensor_base.cpp) target_link_libraries(gtest_sensor_base ${PROJECT_NAME}) +# shared_from_this test +wolf_add_gtest(gtest_shared_from_this gtest_shared_from_this.cpp) +target_link_libraries(gtest_shared_from_this ${PROJECT_NAME}) + # SolverManager test wolf_add_gtest(gtest_solver_manager gtest_solver_manager.cpp) target_link_libraries(gtest_solver_manager ${PROJECT_NAME}) @@ -164,6 +168,10 @@ target_link_libraries(gtest_IMU ${PROJECT_NAME}) wolf_add_gtest(gtest_make_posdef gtest_make_posdef.cpp) target_link_libraries(gtest_make_posdef ${PROJECT_NAME}) +# Parameter prior test +wolf_add_gtest(gtest_param_prior gtest_param_prior.cpp) +target_link_libraries(gtest_param_prior ${PROJECT_NAME}) + # Pinhole test wolf_add_gtest(gtest_pinhole gtest_pinhole.cpp) target_link_libraries(gtest_pinhole ${PROJECT_NAME}) @@ -194,9 +202,10 @@ target_link_libraries(gtest_odom_2D ${PROJECT_NAME}) wolf_add_gtest(gtest_odom_3D gtest_odom_3D.cpp) target_link_libraries(gtest_odom_3D ${PROJECT_NAME}) -# shared_from_this test -wolf_add_gtest(gtest_shared_from_this gtest_shared_from_this.cpp) -target_link_libraries(gtest_shared_from_this ${PROJECT_NAME}) +# SensorBase test +wolf_add_gtest(gtest_sensor_camera gtest_sensor_camera.cpp) +target_link_libraries(gtest_sensor_camera ${PROJECT_NAME}) + # ------- Now Core classes Serialization ---------- diff --git a/test/gtest_constraint_absolute.cpp b/test/gtest_constraint_absolute.cpp index 53252fc5fdf43c5c58b29105245038d38be0d748..f5f03b27dc0d5e1a11b5e8301c5178f6d1929088 100644 --- a/test/gtest_constraint_absolute.cpp +++ b/test/gtest_constraint_absolute.cpp @@ -25,18 +25,17 @@ Vector10s pose9toPose10(Vector9s _pose9) // Input pose9 and covariance Vector9s pose(Vector9s::Random()); Vector10s pose10 = pose9toPose10(pose); -Vector9s data_var((Vector9s() << 0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2).finished()); -Eigen::Matrix<wolf::Scalar, 9, 9> data_cov = data_var.asDiagonal(); +Eigen::Matrix<wolf::Scalar, 9, 9> data_cov = 0.2 * Eigen::Matrix<Scalar,9,9>::Identity(); // perturbated priors Vector10s x0 = pose9toPose10(pose + Vector9s::Random()*0.25); // Problem and solver -ProblemPtr problem = Problem::create("POV 3D"); -CeresManager ceres_mgr(problem); +ProblemPtr problem_ptr = Problem::create("POV 3D"); +CeresManager ceres_mgr(problem_ptr); // Two frames -FrameBasePtr frm0 = problem->emplaceFrame(KEY_FRAME, problem->zeroState(), TimeStamp(0)); +FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY_FRAME, problem_ptr->zeroState(), TimeStamp(0)); // Capture, feature and constraint CaptureBasePtr cap0 = frm0->addCapture(std::make_shared<CaptureMotion>("IMU ABS", 0, nullptr, pose10, 10, 9, nullptr)); @@ -47,22 +46,13 @@ CaptureBasePtr cap0 = frm0->addCapture(std::make_shared<CaptureMotion>("IMU ABS" * Both features and constraints are created in the TEST(). Hence, tests will not interfere each others. */ -TEST(ConstraintBlockAbs, ctr_block_abs_p_check) +TEST(ConstraintBlockAbs, ctr_block_abs_p) { FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("POSITION", pose10.head<3>(), data_cov.topLeftCorner<3,3>())); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getPPtr())) - ); - ASSERT_TRUE(problem->check(0)); -} + fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getPPtr())); + + ASSERT_TRUE(problem_ptr->check(0)); -TEST(ConstraintBlockAbs, ctr_block_abs_p_solve) -{ - FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("POSITION", pose10.head<3>(), data_cov.topLeftCorner<3,3>())); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getPPtr())) - ); - // Unfix frame 0, perturb frm0 frm0->unfix(); frm0->setState(x0); @@ -71,24 +61,31 @@ TEST(ConstraintBlockAbs, ctr_block_abs_p_solve) std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only orientation is constrained - ASSERT_MATRIX_APPROX(frm0->getState().head<3>(), pose10.head<3>(), 1e-6); + ASSERT_MATRIX_APPROX(frm0->getPPtr()->getState(), pose10.head<3>(), 1e-6); } -TEST(ConstraintBlockAbs, ctr_block_abs_v_check) +TEST(ConstraintBlockAbs, ctr_block_abs_p_tail2) { - FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("VELOCITY", pose10.tail<3>(), data_cov.bottomRightCorner<3,3>())); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getVPtr())) - ); - ASSERT_TRUE(problem->check(0)); + FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("POSITION TAIL 2", pose10.segment<2>(1), data_cov.bottomRightCorner<2,2>())); + fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getPPtr(),1,2)); + + // Unfix frame 0, perturb frm0 + frm0->unfix(); + frm0->setState(x0); + + // solve for frm0 + std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); + + //only orientation is constrained + ASSERT_MATRIX_APPROX(frm0->getPPtr()->getState().tail<2>(), pose10.segment<2>(1), 1e-6); } -TEST(ConstraintBlockAbs, ctr_block_abs_v_solve) +TEST(ConstraintBlockAbs, ctr_block_abs_v) { FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("VELOCITY", pose10.tail<3>(), data_cov.bottomRightCorner<3,3>())); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getVPtr())) - ); + fea0->addConstraint(std::make_shared<ConstraintBlockAbsolute>(fea0->getFramePtr()->getVPtr())); + + ASSERT_TRUE(problem_ptr->check(0)); // Unfix frame 0, perturb frm0 frm0->unfix(); @@ -98,24 +95,15 @@ TEST(ConstraintBlockAbs, ctr_block_abs_v_solve) std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only velocity is constrained - ASSERT_MATRIX_APPROX(frm0->getState().tail<3>(), pose10.tail<3>(), 1e-6); + ASSERT_MATRIX_APPROX(frm0->getVPtr()->getState(), pose10.tail<3>(), 1e-6); } -TEST(ConstraintQuatAbs, ctr_block_abs_o_check) +TEST(ConstraintQuatAbs, ctr_block_abs_o) { FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("QUATERNION", pose10.segment<4>(3), data_cov.block<3,3>(3,3))); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintQuaternionAbsolute>(fea0->getFramePtr()->getOPtr())) - ); - ASSERT_TRUE(problem->check(0)); -} + fea0->addConstraint(std::make_shared<ConstraintQuaternionAbsolute>(fea0->getFramePtr()->getOPtr())); -TEST(ConstraintQuatAbs, ctr_block_abs_o_solve) -{ - FeatureBasePtr fea0 = cap0->addFeature(std::make_shared<FeatureBase>("QUATERNION", pose10.segment<4>(3), data_cov.block<3,3>(3,3))); - ConstraintBlockAbsolutePtr ctr0 = std::static_pointer_cast<ConstraintBlockAbsolute>( - fea0->addConstraint(std::make_shared<ConstraintQuaternionAbsolute>(fea0->getFramePtr()->getOPtr())) - ); + ASSERT_TRUE(problem_ptr->check(0)); // Unfix frame 0, perturb frm0 frm0->unfix(); @@ -125,7 +113,7 @@ TEST(ConstraintQuatAbs, ctr_block_abs_o_solve) std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only velocity is constrained - ASSERT_MATRIX_APPROX(frm0->getState().segment<4>(3), pose10.segment<4>(3), 1e-6); + ASSERT_MATRIX_APPROX(frm0->getOPtr()->getState(), pose10.segment<4>(3), 1e-6); } int main(int argc, char **argv) diff --git a/test/gtest_constraint_autodiff.cpp b/test/gtest_constraint_autodiff.cpp index 5138bb89960eba132e32d9153a53c02bc603e700..9305f71ea64703cc29ecb741c38f017f4afdd85d 100644 --- a/test/gtest_constraint_autodiff.cpp +++ b/test/gtest_constraint_autodiff.cpp @@ -23,7 +23,10 @@ TEST(CaptureAutodiff, ConstructorOdom2d) FrameBasePtr fr2_ptr(std::make_shared<FrameBase>(TimeStamp(0), std::make_shared<StateBlock>(2), std::make_shared<StateBlock>(1))); // SENSOR - SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(std::make_shared<StateBlock>(2), std::make_shared<StateBlock>(1), 0.1, 0.1); + IntrinsicsOdom2D intrinsics_odo; + intrinsics_odo.k_disp_to_disp = 0.1; + intrinsics_odo.k_rot_to_rot = 0.1; + SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(Vector3s::Zero(), intrinsics_odo); // CAPTURE CaptureVoidPtr capture_ptr = std::make_shared<CaptureVoid>(TimeStamp(0), sensor_ptr); @@ -55,7 +58,10 @@ TEST(CaptureAutodiff, ResidualOdom2d) FrameBasePtr fr2_ptr(std::make_shared<FrameBase>(TimeStamp(0), std::make_shared<StateBlock>(f2_pose.head<2>()), std::make_shared<StateBlock>(f2_pose.tail<1>()))); // SENSOR - SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(std::make_shared<StateBlock>(2), std::make_shared<StateBlock>(1), 0.1, 0.1); + IntrinsicsOdom2D intrinsics_odo; + intrinsics_odo.k_disp_to_disp = 0.1; + intrinsics_odo.k_rot_to_rot = 0.1; + SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(Vector3s::Zero(), intrinsics_odo); // CAPTURE CaptureVoidPtr capture_ptr = std::make_shared<CaptureVoid>(TimeStamp(0), sensor_ptr); @@ -99,7 +105,10 @@ TEST(CaptureAutodiff, JacobianOdom2d) FrameBasePtr fr2_ptr(std::make_shared<FrameBase>(TimeStamp(0), std::make_shared<StateBlock>(f2_pose.head<2>()), std::make_shared<StateBlock>(f2_pose.tail<1>()))); // SENSOR - SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(std::make_shared<StateBlock>(2), std::make_shared<StateBlock>(1), 0.1, 0.1); + IntrinsicsOdom2D intrinsics_odo; + intrinsics_odo.k_disp_to_disp = 0.1; + intrinsics_odo.k_rot_to_rot = 0.1; + SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(Vector3s::Zero(), intrinsics_odo); // CAPTURE CaptureVoidPtr capture_ptr = std::make_shared<CaptureVoid>(TimeStamp(0), sensor_ptr); @@ -178,7 +187,10 @@ TEST(CaptureAutodiff, AutodiffVsAnalytic) FrameBasePtr fr2_ptr(std::make_shared<FrameBase>(TimeStamp(0), std::make_shared<StateBlock>(f2_pose.head<2>()), std::make_shared<StateBlock>(f2_pose.tail<1>()))); // SENSOR - SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(std::make_shared<StateBlock>(2), std::make_shared<StateBlock>(1), 0.1, 0.1); + IntrinsicsOdom2D intrinsics_odo; + intrinsics_odo.k_disp_to_disp = 0.1; + intrinsics_odo.k_rot_to_rot = 0.1; + SensorOdom2DPtr sensor_ptr = std::make_shared<SensorOdom2D>(Vector3s::Zero(), intrinsics_odo); // CAPTURE CaptureVoidPtr capture_ptr = std::make_shared<CaptureVoid>(TimeStamp(0), sensor_ptr); diff --git a/test/gtest_constraint_odom_3D.cpp b/test/gtest_constraint_odom_3D.cpp index d71050ec6534cd1e0ed1c01a94f35fd927ba6e93..945d49fbf7aeb42564f64cc06c45cd4408ffda7e 100644 --- a/test/gtest_constraint_odom_3D.cpp +++ b/test/gtest_constraint_odom_3D.cpp @@ -33,12 +33,12 @@ Vector7s x0 = data2delta(Vector6s::Random()*0.25); Vector7s x1 = data2delta(data + Vector6s::Random()*0.25); // Problem and solver -ProblemPtr problem = Problem::create("PO 3D"); -CeresManager ceres_mgr(problem); +ProblemPtr problem_ptr = Problem::create("PO 3D"); +CeresManager ceres_mgr(problem_ptr); // Two frames -FrameBasePtr frm0 = problem->emplaceFrame(KEY_FRAME, problem->zeroState(), TimeStamp(0)); -FrameBasePtr frm1 = problem->emplaceFrame(KEY_FRAME, delta, TimeStamp(1)); +FrameBasePtr frm0 = problem_ptr->emplaceFrame(KEY_FRAME, problem_ptr->zeroState(), TimeStamp(0)); +FrameBasePtr frm1 = problem_ptr->emplaceFrame(KEY_FRAME, delta, TimeStamp(1)); // Capture, feature and constraint from frm1 to frm0 CaptureBasePtr cap1 = frm1->addCapture(std::make_shared<CaptureMotion>("ODOM 3D", 1, nullptr, delta, 7, 6, nullptr)); @@ -50,7 +50,7 @@ ConstraintBasePtr dummy = frm0->addConstrainedBy(ctr1); TEST(ConstraintOdom3D, check_tree) { - ASSERT_TRUE(problem->check(0)); + ASSERT_TRUE(problem_ptr->check(0)); } TEST(ConstraintOdom3D, expectation) @@ -83,7 +83,7 @@ TEST(ConstraintOdom3D, fix_1_solve) // solve for frm0 std::string brief_report = ceres_mgr.solve(SolverManager::ReportVerbosity::BRIEF); - ASSERT_MATRIX_APPROX(frm0->getState(), problem->zeroState(), 1e-6); + ASSERT_MATRIX_APPROX(frm0->getState(), problem_ptr->zeroState(), 1e-6); } int main(int argc, char **argv) diff --git a/test/gtest_frame_base.cpp b/test/gtest_frame_base.cpp index e5a4d4f3c837e855929bd3f24fff98692227194e..98e032cb3ea7b0ba8f5bb975c1ed7a7adc43f4e5 100644 --- a/test/gtest_frame_base.cpp +++ b/test/gtest_frame_base.cpp @@ -52,7 +52,8 @@ TEST(FrameBase, LinksBasic) ASSERT_FALSE(F->getProblem()); // ASSERT_THROW(f->getPreviousFrame(), std::runtime_error); // protected by assert() // ASSERT_EQ(f->getStatus(), ST_ESTIMATED); // protected - ASSERT_FALSE(F->getCaptureOf(make_shared<SensorOdom2D>(nullptr, nullptr, 1,1))); + SensorOdom2DPtr S = make_shared<SensorOdom2D>(Vector3s::Zero(), IntrinsicsOdom2D()); + ASSERT_FALSE(F->getCaptureOf(S)); ASSERT_TRUE(F->getCaptureList().empty()); ASSERT_TRUE(F->getConstrainedByList().empty()); ASSERT_EQ(F->getHits() , (unsigned int) 0); @@ -63,7 +64,10 @@ TEST(FrameBase, LinksToTree) // Problem with 2 frames and one motion constraint between them ProblemPtr P = Problem::create("PO 2D"); TrajectoryBasePtr T = P->getTrajectoryPtr(); - SensorOdom2DPtr S = make_shared<SensorOdom2D>(make_shared<StateBlock>(2), make_shared<StateBlock>(1), 1,1); + IntrinsicsOdom2D intrinsics_odo; + intrinsics_odo.k_disp_to_disp = 1; + intrinsics_odo.k_rot_to_rot = 1; + SensorOdom2DPtr S = make_shared<SensorOdom2D>(Vector3s::Zero(), intrinsics_odo); P->getHardwarePtr()->addSensor(S); FrameBasePtr F1 = make_shared<FrameBase>(1, make_shared<StateBlock>(2), make_shared<StateBlock>(1)); T->addFrame(F1); diff --git a/test/gtest_param_prior.cpp b/test/gtest_param_prior.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bb1eccbc1cac0070a412b63e7ebcf3a62d238b1 --- /dev/null +++ b/test/gtest_param_prior.cpp @@ -0,0 +1,85 @@ +/* + * gtest_param_prior.cpp + * + * Created on: Feb 6, 2019 + * Author: jvallve + */ + +#include "utils_gtest.h" +#include "base/logging.h" + +#include "base/problem.h" +#include "base/ceres_wrapper/ceres_manager.h" +#include "base/sensor/sensor_odom_3D.h" + +#include <iostream> + +using namespace wolf; + +ProblemPtr problem_ptr = Problem::create("PO 3D"); +CeresManagerPtr ceres_mgr_ptr = std::make_shared<CeresManager>(problem_ptr); +Eigen::Vector7s initial_extrinsics((Eigen::Vector7s() << 1, 2, 3, 1, 0, 0, 0).finished()); +Eigen::Vector7s prior_extrinsics((Eigen::Vector7s() << 10, 20, 30, 0, 0, 0, 1).finished()); +Eigen::Vector7s prior2_extrinsics((Eigen::Vector7s() << 100, 200, 300, 0, 0, 0, 1).finished()); + +SensorOdom3DPtr odom_sensor_ptr_ = std::static_pointer_cast<SensorOdom3D>(problem_ptr->installSensor("ODOM 3D", "odometer", initial_extrinsics, std::make_shared<IntrinsicsOdom3D>())); + +TEST(ParameterPrior, initial_extrinsics) +{ + ASSERT_TRUE(problem_ptr->check(0)); + ASSERT_TRUE(odom_sensor_ptr_->getPPtr()); + ASSERT_TRUE(odom_sensor_ptr_->getOPtr()); + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getPPtr()->getState(),initial_extrinsics.head(3),1e-9); + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getOPtr()->getState(),initial_extrinsics.tail(4),1e-9); +} + +TEST(ParameterPrior, prior_p) +{ + odom_sensor_ptr_->addPriorP(prior_extrinsics.head(3),Eigen::Matrix3s::Identity()); + + std::string report = ceres_mgr_ptr->solve(SolverManager::ReportVerbosity::BRIEF); + + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getPPtr()->getState(),prior_extrinsics.head(3),1e-6); +} + +TEST(ParameterPrior, prior_o) +{ + odom_sensor_ptr_->addPriorO(prior_extrinsics.tail(4),Eigen::Matrix3s::Identity()); + + std::string report = ceres_mgr_ptr->solve(SolverManager::ReportVerbosity::BRIEF); + + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getOPtr()->getState(),prior_extrinsics.tail(4),1e-6); +} + +TEST(ParameterPrior, prior_p_overwrite) +{ + odom_sensor_ptr_->addPriorP(prior2_extrinsics.head(3),Eigen::Matrix3s::Identity()); + + std::string report = ceres_mgr_ptr->solve(SolverManager::ReportVerbosity::BRIEF); + + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getPPtr()->getState(),prior2_extrinsics.head(3),1e-6); +} + +TEST(ParameterPrior, prior_p_segment) +{ + odom_sensor_ptr_->addPriorP(prior_extrinsics.segment(1,2),Eigen::Matrix2s::Identity(),1,2); + + std::string report = ceres_mgr_ptr->solve(SolverManager::ReportVerbosity::BRIEF); + + ASSERT_MATRIX_APPROX(odom_sensor_ptr_->getPPtr()->getState().segment(1,2),prior_extrinsics.segment(1,2),1e-6); +} + +TEST(ParameterPrior, prior_o_segment) +{ + // constraining segment of quaternion is not allowed + ASSERT_DEATH(odom_sensor_ptr_->addPriorParameter(1, prior_extrinsics.segment(1,2),Eigen::Matrix2s::Identity(),1,2),""); +} + + + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/test/gtest_processor_tracker_feature_trifocal.cpp b/test/gtest_processor_tracker_feature_trifocal.cpp index d182bb4f376f579e498e6bc281ecf1d845a39315..d94815f9210090c887bebde5d416ce8fbeaf0e4f 100644 --- a/test/gtest_processor_tracker_feature_trifocal.cpp +++ b/test/gtest_processor_tracker_feature_trifocal.cpp @@ -81,7 +81,7 @@ TEST(ProcessorTrackerFeatureTrifocal, KeyFrameCallback) intr); ProcessorParamsTrackerFeatureTrifocalPtr params_tracker_feature_trifocal = std::make_shared<ProcessorParamsTrackerFeatureTrifocal>(); - params_tracker_feature_trifocal->name = "trifocal"; +// params_tracker_feature_trifocal->name = "trifocal"; params_tracker_feature_trifocal->pixel_noise_std = 1.0; params_tracker_feature_trifocal->voting_active = true; params_tracker_feature_trifocal->min_features_for_keyframe = 5; diff --git a/test/gtest_sensor_camera.cpp b/test/gtest_sensor_camera.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14b24deb1a0e23b39dc9bb55d1cf24355bd1a357 --- /dev/null +++ b/test/gtest_sensor_camera.cpp @@ -0,0 +1,123 @@ +/** + * \file gtest_sensor_camera.cpp + * + * Created on: Feb 7, 2019 + * \author: jsola + */ + + +#include "utils_gtest.h" + +#include "src/sensor/sensor_camera.cpp" +#include "base/sensor/sensor_factory.h" + +using namespace wolf; + +TEST(SensorCamera, Img_size) +{ + Eigen::VectorXs extrinsics(7); extrinsics << 0,0,0, 0,0,0,1; + IntrinsicsCamera params; + params.width = 640; + params.height = 480; + SensorCameraPtr cam = std::make_shared<SensorCamera>(extrinsics, params); + + ASSERT_EQ(cam->getImgWidth() , 640); + ASSERT_EQ(cam->getImgHeight(), 480); + + cam->setImgWidth(100); + ASSERT_EQ(cam->getImgWidth() , 100); + + cam->setImgHeight(100); + ASSERT_EQ(cam->getImgHeight(), 100); +} + +TEST(SensorCamera, Intrinsics_Raw_Rectified) +{ + Eigen::VectorXs extrinsics(7); extrinsics << 0,0,0, 0,0,0,1; + IntrinsicsCamera params; + params.pinhole_model_raw << 321, 241, 321, 321; + params.pinhole_model_rectified << 320, 240, 320, 320; + SensorCameraPtr cam = std::make_shared<SensorCamera>(extrinsics, params); + + Eigen::Matrix3s K_raw, K_rectified; + K_raw << 321, 0, 321, 0, 321, 241, 0, 0, 1; + K_rectified << 320, 0, 320, 0, 320, 240, 0, 0, 1; + Eigen::Vector4s k_raw(321,241,321,321); + Eigen::Vector4s k_rectified(320,240,320,320); + + // default is raw + ASSERT_TRUE(cam->isUsingRawImages()); + ASSERT_MATRIX_APPROX(K_raw, cam->getIntrinsicMatrix(), 1e-8); + ASSERT_MATRIX_APPROX(k_raw, cam->getIntrinsicPtr()->getState(), 1e-8); + + cam->useRectifiedImages(); + ASSERT_FALSE(cam->isUsingRawImages()); + ASSERT_MATRIX_APPROX(K_rectified, cam->getIntrinsicMatrix(), 1e-8); + ASSERT_MATRIX_APPROX(k_rectified, cam->getIntrinsicPtr()->getState(), 1e-8); + + cam->useRawImages(); + ASSERT_TRUE(cam->isUsingRawImages()); + ASSERT_MATRIX_APPROX(K_raw, cam->getIntrinsicMatrix(), 1e-8); + ASSERT_MATRIX_APPROX(k_raw, cam->getIntrinsicPtr()->getState(), 1e-8); +} + +TEST(SensorCamera, Distortion) +{ + Eigen::VectorXs extrinsics(7); extrinsics << 0,0,0, 0,0,0,1; + IntrinsicsCamera params; + params.width = 640; + params.height = 480; + params.pinhole_model_raw << 321, 241, 321, 321; + params.pinhole_model_rectified << 320, 240, 320, 320; + params.distortion = Eigen::Vector3s( -0.3, 0.096, 0 ); + SensorCameraPtr cam = std::make_shared<SensorCamera>(extrinsics, params); + + Eigen::Vector3s d(-0.3, 0.096, 0); + + ASSERT_MATRIX_APPROX(d, cam->getDistortionVector(), 1e-8); +} + +TEST(SensorCamera, Correction_zero) +{ + Eigen::VectorXs extrinsics(7); extrinsics << 0,0,0, 0,0,0,1; + IntrinsicsCamera params; + params.width = 640; + params.height = 480; + params.pinhole_model_raw << 321, 241, 321, 321; + params.pinhole_model_rectified << 320, 240, 320, 320; + params.distortion = Eigen::Vector3s( 0, 0, 0 ); + SensorCameraPtr cam = std::make_shared<SensorCamera>(extrinsics, params); + + Eigen::MatrixXs c(cam->getCorrectionVector().size(), 1); + c.setZero(); + + ASSERT_GE(cam->getCorrectionVector().size(), cam->getDistortionVector().size()); + ASSERT_MATRIX_APPROX(c, cam->getCorrectionVector(), 1e-8); +} + +TEST(SensorCamera, create) +{ + Eigen::VectorXs extrinsics(7); extrinsics << 0,0,0, 0,0,0,1; + IntrinsicsCameraPtr params = std::make_shared<IntrinsicsCamera>(); + params->width = 640; + params->height = 480; + params->pinhole_model_raw << 321, 241, 321, 321; + params->pinhole_model_rectified << 320, 240, 320, 320; + params->distortion = Eigen::Vector3s( 0, 0, 0 ); + + SensorBasePtr sen = SensorCamera::create("camera", extrinsics, params); + + ASSERT_NE(sen, nullptr); + + SensorCameraPtr cam = std::static_pointer_cast<SensorCamera>(sen); + + ASSERT_NE(cam, nullptr); + ASSERT_EQ(cam->getImgWidth(), 640); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +