#pragma once #include #include #include #include #include namespace basalt { template struct RelPoseLin { using Mat4 = Eigen::Matrix; using Mat6 = Eigen::Matrix; Mat4 T_t_h; Mat6 d_rel_d_h; Mat6 d_rel_d_t; EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; template class LandmarkBlock { public: struct Options { // use Householder instead of Givens for marginalization bool use_householder = true; // use_valid_projections_only: if true, set invalid projection's // residual and jacobian to 0; invalid means z <= 0 bool use_valid_projections_only = true; // if > 0, use huber norm with given threshold, else squared norm Scalar huber_parameter = 0; // Standard deviation of reprojection error to weight visual measurements Scalar obs_std_dev = 1; // ceres uses 1.0 / (1.0 + sqrt(SquaredColumnNorm)) // we use 1.0 / (eps + sqrt(SquaredColumnNorm)) Scalar jacobi_scaling_eps = 1e-6; }; enum State { Uninitialized = 0, Allocated, NumericalFailure, Linearized, Marginalized }; using Vec2 = Eigen::Matrix; using Vec3 = Eigen::Matrix; using Vec4 = Eigen::Matrix; using VecX = Eigen::Matrix; using Mat36 = Eigen::Matrix; using MatX = Eigen::Matrix; using RowMatX = Eigen::Matrix; using RowMat3 = Eigen::Matrix; virtual ~LandmarkBlock(){}; virtual bool isNumericalFailure() const = 0; virtual void allocateLandmark( Keypoint& lm, const Eigen::aligned_unordered_map, RelPoseLin>& relative_pose_lin, const Calibration& calib, const AbsOrderMap& aom, const Options& options, const std::map* rel_order = nullptr) = 0; // may set state to NumericalFailure --> linearization at this state is // unusable. Numeric check is only performed for residuals that were // considered to be used (valid), which depends on // use_valid_projections_only setting. virtual Scalar linearizeLandmark() = 0; virtual void performQR() = 0; // Sets damping and maintains upper triangular matrix for landmarks. virtual void setLandmarkDamping(Scalar lambda) = 0; // lambda < 0 means computing exact model cost change virtual void backSubstitute(const VecX& pose_inc, Scalar& l_diff) = 0; virtual void addQ2JpTQ2Jp_mult_x(VecX& res, const VecX& x_pose) const = 0; virtual void addQ2JpTQ2r(VecX& res) const = 0; virtual void addJp_diag2(VecX& res) const = 0; virtual void addQ2JpTQ2Jp_blockdiag( BlockDiagonalAccumulator& accu) const = 0; virtual void scaleJl_cols() = 0; virtual void scaleJp_cols(const VecX& jacobian_scaling) = 0; virtual void printStorage(const std::string& filename) const = 0; virtual State getState() const = 0; virtual size_t numReducedCams() const = 0; virtual void get_dense_Q2Jp_Q2r(MatX& Q2Jp, VecX& Q2r, size_t start_idx) const = 0; virtual void get_dense_Q2Jp_Q2r_rel( MatX& Q2Jp, VecX& Q2r, size_t start_idx, const std::map& rel_order) const = 0; virtual void add_dense_H_b(DenseAccumulator& accum) const = 0; virtual void add_dense_H_b(MatX& H, VecX& b) const = 0; virtual void add_dense_H_b_rel( MatX& H_rel, VecX& b_rel, const std::map& rel_order) const = 0; virtual const Eigen::PermutationMatrix& get_rel_permutation() const = 0; virtual Eigen::PermutationMatrix compute_rel_permutation( const std::map& rel_order) const = 0; virtual void add_dense_H_b_rel_2(MatX& H_rel, VecX& b_rel) const = 0; virtual TimeCamId getHostKf() const = 0; virtual size_t numQ2rows() const = 0; // factory method template static std::unique_ptr> createLandmarkBlock(); }; } // namespace basalt