InvDepthFactorVariant1.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /**
  2. * @file InvDepthFactorVariant1.h
  3. * @brief Inverse Depth Factor based on Civera09tro, Montiel06rss.
  4. * Landmarks are parameterized as (x,y,z,theta,phi,rho). The factor involves
  5. * a single pose and a landmark. The landmark parameterization contains the
  6. * reference point internally (and will thus be updated as well during optimization).
  7. * @author Chris Beall, Stephen Williams
  8. */
  9. #pragma once
  10. #include <gtsam/nonlinear/NonlinearFactor.h>
  11. #include <gtsam/geometry/PinholeCamera.h>
  12. #include <gtsam/geometry/Cal3_S2.h>
  13. #include <gtsam/geometry/Pose3.h>
  14. #include <gtsam/geometry/Point2.h>
  15. #include <gtsam/base/numericalDerivative.h>
  16. #include <boost/bind/bind.hpp>
  17. namespace gtsam {
  18. /**
  19. * Binary factor representing a visual measurement using an inverse-depth parameterization
  20. */
  21. class InvDepthFactorVariant1: public NoiseModelFactor2<Pose3, Vector6> {
  22. protected:
  23. // Keep a copy of measurement and calibration for I/O
  24. Point2 measured_; ///< 2D measurement
  25. Cal3_S2::shared_ptr K_; ///< shared pointer to calibration object
  26. public:
  27. /// shorthand for base class type
  28. typedef NoiseModelFactor2<Pose3, Vector6> Base;
  29. /// shorthand for this class
  30. typedef InvDepthFactorVariant1 This;
  31. /// shorthand for a smart pointer to a factor
  32. typedef boost::shared_ptr<This> shared_ptr;
  33. /// Default constructor
  34. InvDepthFactorVariant1() :
  35. measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) {
  36. }
  37. /**
  38. * Constructor
  39. * @param poseKey is the index of the camera pose
  40. * @param pointKey is the index of the landmark
  41. * @param measured is the 2 dimensional location of point in image (the measurement)
  42. * @param K shared pointer to the constant calibration
  43. * @param model is the standard deviation
  44. */
  45. InvDepthFactorVariant1(const Key poseKey, const Key landmarkKey,
  46. const Point2& measured, const Cal3_S2::shared_ptr& K, const SharedNoiseModel& model) :
  47. Base(model, poseKey, landmarkKey), measured_(measured), K_(K) {}
  48. /** Virtual destructor */
  49. ~InvDepthFactorVariant1() override {}
  50. /**
  51. * print
  52. * @param s optional string naming the factor
  53. * @param keyFormatter optional formatter useful for printing Symbols
  54. */
  55. void print(const std::string& s = "InvDepthFactorVariant1",
  56. const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
  57. Base::print(s, keyFormatter);
  58. traits<Point2>::Print(measured_, s + ".z");
  59. }
  60. /// equals
  61. bool equals(const NonlinearFactor& p, double tol = 1e-9) const override {
  62. const This *e = dynamic_cast<const This*>(&p);
  63. return e
  64. && Base::equals(p, tol)
  65. && traits<Point2>::Equals(this->measured_, e->measured_, tol)
  66. && this->K_->equals(*e->K_, tol);
  67. }
  68. Vector inverseDepthError(const Pose3& pose, const Vector6& landmark) const {
  69. try {
  70. // Calculate the 3D coordinates of the landmark in the world frame
  71. double x = landmark(0), y = landmark(1), z = landmark(2);
  72. double theta = landmark(3), phi = landmark(4), rho = landmark(5);
  73. Point3 world_P_landmark = Point3(x, y, z) + Point3(cos(theta)*cos(phi)/rho, sin(theta)*cos(phi)/rho, sin(phi)/rho);
  74. // Project landmark into Pose2
  75. PinholeCamera<Cal3_S2> camera(pose, *K_);
  76. return camera.project(world_P_landmark) - measured_;
  77. } catch( CheiralityException& e) {
  78. std::cout << e.what()
  79. << ": Inverse Depth Landmark [" << DefaultKeyFormatter(this->key2()) << "]"
  80. << " moved behind camera [" << DefaultKeyFormatter(this->key1()) <<"]"
  81. << std::endl;
  82. return Vector::Ones(2) * 2.0 * K_->fx();
  83. }
  84. return (Vector(1) << 0.0).finished();
  85. }
  86. /// Evaluate error h(x)-z and optionally derivatives
  87. Vector evaluateError(const Pose3& pose, const Vector6& landmark,
  88. boost::optional<Matrix&> H1=boost::none,
  89. boost::optional<Matrix&> H2=boost::none) const override {
  90. if (H1) {
  91. (*H1) = numericalDerivative11<Vector, Pose3>(
  92. std::bind(&InvDepthFactorVariant1::inverseDepthError, this,
  93. std::placeholders::_1, landmark),
  94. pose);
  95. }
  96. if (H2) {
  97. (*H2) = numericalDerivative11<Vector, Vector6>(
  98. std::bind(&InvDepthFactorVariant1::inverseDepthError, this, pose,
  99. std::placeholders::_1), landmark);
  100. }
  101. return inverseDepthError(pose, landmark);
  102. }
  103. /** return the measurement */
  104. const Point2& imagePoint() const {
  105. return measured_;
  106. }
  107. /** return the calibration object */
  108. const Cal3_S2::shared_ptr calibration() const {
  109. return K_;
  110. }
  111. private:
  112. /// Serialization function
  113. friend class boost::serialization::access;
  114. template<class ARCHIVE>
  115. void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
  116. ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
  117. ar & BOOST_SERIALIZATION_NVP(measured_);
  118. ar & BOOST_SERIALIZATION_NVP(K_);
  119. }
  120. };
  121. } // \ namespace gtsam