diff --git a/include/base/factor/factor_autodiff_apriltag.h b/include/base/factor/factor_autodiff_apriltag.h index 3402cc497ec9c71f293dff2038be6a7c1d985b50..42d5068b1b1d155c44f617b4a7e650301a64e6e3 100644 --- a/include/base/factor/factor_autodiff_apriltag.h +++ b/include/base/factor/factor_autodiff_apriltag.h @@ -101,7 +101,36 @@ FactorAutodiffApriltag::~FactorAutodiffApriltag() template<typename T> bool FactorAutodiffApriltag::operator ()( const T* const _p_camera, const T* const _o_camera, const T* const _p_keyframe, const T* const _o_keyframe, const T* const _p_landmark, const T* const _o_landmark, T* _residuals) const { - //states + // Maps + Eigen::Map<const Eigen::Matrix<T,3,1>> p_r_c(_p_camera); + Eigen::Map<const Eigen::Quaternion<T>> q_r_c(_o_camera); + Eigen::Map<const Eigen::Matrix<T,3,1>> p_w_r(_p_keyframe); + Eigen::Map<const Eigen::Quaternion<T>> q_w_r(_o_keyframe); + Eigen::Map<const Eigen::Matrix<T,3,1>> p_w_l(_p_landmark); + Eigen::Map<const Eigen::Quaternion<T>> q_w_l(_o_landmark); + Eigen::Map<Eigen::Matrix<T,6,1>> residuals(_residuals); + + // Expected measurement + Eigen::Quaternion<T> q_c_w = (q_w_r * q_r_c).conjugate(); + Eigen::Quaternion<T> q_c_l = q_c_w * q_w_l; + Eigen::Matrix<T,3,1> p_c_l = q_c_w * (-(p_w_r + q_w_r * p_r_c) + p_w_l); + + // Measurement + Eigen::Vector3s p_c_l_meas(getMeasurement().head<3>()); + Eigen::Quaternions q_c_l_meas(getMeasurement().data() + 3 ); + Eigen::Quaternion<T> q_l_c_meas = q_c_l_meas.conjugate().cast<T>(); + //Eigen::Matrix<T,3,1> p_l_c_meas = -q_l_c_meas * p_c_l_meas.cast<T>(); + + // Error + Eigen::Matrix<T, 6, 1> err; + err.head(3) = q_l_c_meas * (p_c_l_meas.cast<T>() - p_c_l); + //err.tail(3) = wolf::log_q(q_l_c_meas * q_c_l); + err.tail(3) = T(2)*(q_l_c_meas * q_c_l).vec(); + + // Residual + residuals = getMeasurementSquareRootInformationUpper().cast<T>() * err; + + /*//states Eigen::Translation<T,3> p_camera (_p_camera[0] , _p_camera[1] , _p_camera[2]), p_keyframe (_p_keyframe[0], _p_keyframe[1], _p_keyframe[2]), p_landmark (_p_landmark[0], _p_landmark[1], _p_landmark[2]); @@ -113,7 +142,7 @@ template<typename T> bool FactorAutodiffApriltag::operator ()( const T* const _p Eigen::Translation3ds p_measured(getMeasurement().head(3)); Eigen::Quaternions q_measured(getMeasurement().data() + 3 ); // landmark wrt camera, measure - Eigen::Transform<T, 3, Eigen::Affine> c_M_l_meas = p_measured.cast<T>() * q_measured.cast<T>(); + Eigen::Transform<T, 3, Eigen::Affine> c_M_l_meas = p_c_l_meas.cast<T>() * q_measured.cast<T>(); // Create transformation matrices to compose // robot wrt world @@ -152,7 +181,7 @@ template<typename T> bool FactorAutodiffApriltag::operator ()( const T* const _p Eigen::Map<Eigen::Matrix<T, 6, 1>> res(_residuals); res = getFeature()->getMeasurementSquareRootInformationUpper().cast<T>() * err; - + */ return true; } diff --git a/test/gtest_factor_autodiff_apriltag.cpp b/test/gtest_factor_autodiff_apriltag.cpp index f88c461d526664424f0b18fad74451fde28da812..c815e26eb702748f38d3d4f916413e6fb76e0488 100644 --- a/test/gtest_factor_autodiff_apriltag.cpp +++ b/test/gtest_factor_autodiff_apriltag.cpp @@ -403,6 +403,90 @@ TEST_F(FactorAutodiffApriltag_class, solve_L1_O_perturbated) } +TEST_F(FactorAutodiffApriltag_class, solve_L1_PO_perturbated) +{ + FactorAutodiffApriltagPtr constraint = std::make_shared<FactorAutodiffApriltag>( + S, + F1, + lmk1, + f1, + false, + CTR_ACTIVE + ); + + FactorAutodiffApriltagPtr ctr0 = std::static_pointer_cast<FactorAutodiffApriltag>(f1->addFactor(constraint)); + lmk1->addConstrainedBy(constraint); + F1->addConstrainedBy(constraint); + f1->addConstrainedBy(constraint); + + // Change setup + Vector3s p_w_r, p_r_c, p_c_l, p_w_l; + Quaternions q_w_r, q_r_c, q_c_l, q_w_l; + p_w_r << 1, 2, 3; + p_r_c << 4, 5, 6; + p_c_l << 7, 8, 9; + q_w_r.coeffs() << 1, 2, 3, 4; q_w_r.normalize(); + q_r_c.coeffs() << 4, 5, 6, 7; q_r_c.normalize(); + q_c_l.coeffs() << 7, 8, 9, 0; q_c_l.normalize(); + + q_w_l = q_w_r * q_r_c * q_c_l; + p_w_l = p_w_r + q_w_r * (p_r_c + q_r_c * p_c_l); + + // Change feature + Vector7s meas; + meas << p_c_l, q_c_l.coeffs(); + f1->setMeasurement(meas); + + // Change Landmark + lmk1->getP()->setState(p_w_l); + lmk1->getO()->setState(q_w_l.coeffs()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), lmk1->getP()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), lmk1->getO()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(lmk1->getP()->stateUpdated()); + ASSERT_TRUE(lmk1->getO()->stateUpdated()); + + // Change Frame + F1->getP()->setState(p_w_r); + F1->getO()->setState(q_w_r.coeffs()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), F1->getP()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), F1->getO()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(F1->getP()->stateUpdated()); + ASSERT_TRUE(F1->getO()->stateUpdated()); + + // Change sensor extrinsics + S->getP()->setState(p_r_c); + S->getO()->setState(q_r_c.coeffs()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), S->getP()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(std::find(problem->getStateBlockPtrList().begin(), problem->getStateBlockPtrList().end(), S->getO()) != problem->getStateBlockPtrList().end()); + ASSERT_TRUE(S->getP()->stateUpdated()); + ASSERT_TRUE(S->getO()->stateUpdated()); + + Vector7s t_w_r, t_w_l; + t_w_r << p_w_r, q_w_r.coeffs(); + t_w_l << p_w_l, q_w_l.coeffs(); + ASSERT_MATRIX_APPROX(F1->getState(), t_w_r, 1e-6); + ASSERT_MATRIX_APPROX(lmk1->getState(), t_w_l, 1e-6); + + // unfix LMK, perturbate state + lmk1->unfix(); + Vector3s e0_pos = p_w_l + Vector3s::Random() * 0.25; + Quaternions e0_quat = q_w_l * exp_q(Vector3s::Random() * 0.1); + lmk1->getP()->setState(e0_pos); + lmk1->getO()->setState(e0_quat.coeffs()); + F1->fix(); + S->fixExtrinsics(); + +// solve + std::string report = ceres_manager->solve(SolverManager::ReportVerbosity::QUIET); // 0: nothing, 1: BriefReport, 2: FullReport + //WOLF_DEBUG("Landmark state after solve: "); + //WOLF_DEBUG(lmk1->getState().transpose()); + t_w_r << p_w_r, q_w_r.coeffs(); + t_w_l << p_w_l, q_w_l.coeffs(); + ASSERT_MATRIX_APPROX(F1->getState(), t_w_r, 1e-6); + ASSERT_MATRIX_APPROX(lmk1->getState(), t_w_l, 1e-6); + +} + //[Class methods] int main(int argc, char **argv)