commit
						0a5690dfb3
					
				|  | @ -30,7 +30,7 @@ namespace gtsam { | |||
|  */ | ||||
| class GTSAM_EXPORT Cal3DS2 : public DerivedValue<Cal3DS2> { | ||||
| 
 | ||||
| private: | ||||
| protected: | ||||
| 
 | ||||
|   double fx_, fy_, s_, u0_, v0_ ; // focal length, skew and principal point
 | ||||
|   double k1_, k2_ ; // radial 2nd-order and 4th-order
 | ||||
|  |  | |||
|  | @ -0,0 +1,141 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | ||||
|  * Atlanta, Georgia 30332-0415 | ||||
|  * All Rights Reserved | ||||
|  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | ||||
| 
 | ||||
|  * See LICENSE for the license information | ||||
| 
 | ||||
|  * -------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @file Cal3Unify.cpp | ||||
|  * @date Mar 8, 2014 | ||||
|  * @author Jing Dong | ||||
|  */ | ||||
| 
 | ||||
| #include <gtsam/base/Vector.h> | ||||
| #include <gtsam/base/Matrix.h> | ||||
| #include <gtsam/geometry/Point2.h> | ||||
| #include <gtsam/geometry/Cal3Unified.h> | ||||
| 
 | ||||
| #include <cmath> | ||||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Cal3Unified::Cal3Unified(const Vector &v): | ||||
|     Base(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]), xi_(v[9]) {} | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Vector Cal3Unified::vector() const { | ||||
|   return (Vector(10) << Base::vector(), xi_); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| void Cal3Unified::print(const std::string& s) const { | ||||
|   Base::print(s); | ||||
|   gtsam::print((Vector)(Vector(1) << xi_), s + ".xi"); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| bool Cal3Unified::equals(const Cal3Unified& K, double tol) const { | ||||
|   if (fabs(fx_ - K.fx_) > tol || fabs(fy_ - K.fy_) > tol || fabs(s_ - K.s_) > tol || | ||||
|       fabs(u0_ - K.u0_) > tol || fabs(v0_ - K.v0_) > tol || fabs(k1_ - K.k1_) > tol || | ||||
|       fabs(k2_ - K.k2_) > tol || fabs(k3_ - K.k3_) > tol || fabs(k4_ - K.k4_) > tol || | ||||
|       fabs(xi_ - K.xi_) > tol) | ||||
|     return false; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Point2 Cal3Unified::uncalibrate(const Point2& p, | ||||
|        boost::optional<Matrix&> H1, | ||||
|        boost::optional<Matrix&> H2) const { | ||||
| 
 | ||||
|   // this part of code is modified from Cal3DS2,
 | ||||
|   // since the second part of this model (after project to normalized plane)
 | ||||
|   // is same as Cal3DS2
 | ||||
| 
 | ||||
|   // parameters
 | ||||
|   const double xi = xi_; | ||||
| 
 | ||||
|   // Part1: project 3D space to NPlane
 | ||||
|   const double xs = p.x(), ys = p.y();  // normalized points in 3D space
 | ||||
|   const double sqrt_nx = sqrt(xs * xs + ys * ys + 1.0); | ||||
|   const double xi_sqrt_nx = 1.0 / (1 + xi * sqrt_nx); | ||||
|   const double xi_sqrt_nx2 = xi_sqrt_nx * xi_sqrt_nx; | ||||
|   const double x = xs * xi_sqrt_nx, y = ys * xi_sqrt_nx; // points on NPlane
 | ||||
| 
 | ||||
|   // Part2: project NPlane point to pixel plane: use Cal3DS2
 | ||||
|   Point2 m(x,y); | ||||
|   Matrix H1base, H2base;    // jacobians from Base class
 | ||||
|   Point2 puncalib = Base::uncalibrate(m, H1base, H2base); | ||||
| 
 | ||||
|   // Inlined derivative for calibration
 | ||||
|   if (H1) { | ||||
|     // part1
 | ||||
|     Matrix DU = (Matrix(2,1) << -xs * sqrt_nx * xi_sqrt_nx2, | ||||
|         -ys * sqrt_nx * xi_sqrt_nx2); | ||||
|     Matrix DDS2U = H2base * DU; | ||||
| 
 | ||||
|     *H1 = collect(2, &H1base, &DDS2U); | ||||
|   } | ||||
|   // Inlined derivative for points
 | ||||
|   if (H2) { | ||||
|     // part1
 | ||||
|     const double denom = 1.0 * xi_sqrt_nx2 / sqrt_nx; | ||||
|     const double mid = -(xi * xs*ys) * denom; | ||||
|     Matrix DU = (Matrix(2, 2) << | ||||
|         (sqrt_nx + xi*(ys*ys + 1)) * denom, mid, | ||||
|         mid, (sqrt_nx + xi*(xs*xs + 1)) * denom); | ||||
| 
 | ||||
|     *H2 = H2base * DU; | ||||
|   } | ||||
| 
 | ||||
|   return puncalib; | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Point2 Cal3Unified::calibrate(const Point2& pi, const double tol) const { | ||||
| 
 | ||||
|   // calibrate point to Nplane use base class::calibrate()
 | ||||
|   Point2 pnplane = Base::calibrate(pi, tol); | ||||
| 
 | ||||
|   // call nplane to space
 | ||||
|   return this->nPlaneToSpace(pnplane); | ||||
| } | ||||
| /* ************************************************************************* */ | ||||
| Point2 Cal3Unified::nPlaneToSpace(const Point2& p) const { | ||||
| 
 | ||||
|   const double x = p.x(), y = p.y(); | ||||
|   const double xy2 = x * x + y * y; | ||||
|   const double sq_xy = (xi_ + sqrt(1 + (1 - xi_ * xi_) * xy2)) / (xy2 + 1); | ||||
| 
 | ||||
|   return Point2((sq_xy * x / (sq_xy - xi_)), (sq_xy * y / (sq_xy - xi_))); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Point2 Cal3Unified::spaceToNPlane(const Point2& p) const { | ||||
| 
 | ||||
|   const double x = p.x(), y = p.y(); | ||||
|   const double sq_xy = 1 + xi_ * sqrt(x * x + y * y + 1); | ||||
| 
 | ||||
|   return Point2((x / sq_xy), (y / sq_xy)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Cal3Unified Cal3Unified::retract(const Vector& d) const { | ||||
|   return Cal3Unified(vector() + d); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| Vector Cal3Unified::localCoordinates(const Cal3Unified& T2) const { | ||||
|   return T2.vector() - vector(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
| /* ************************************************************************* */ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,146 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | ||||
|  * Atlanta, Georgia 30332-0415 | ||||
|  * All Rights Reserved | ||||
|  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | ||||
| 
 | ||||
|  * See LICENSE for the license information | ||||
| 
 | ||||
|  * -------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @file Cal3Unify.h | ||||
|  * @brief Unified Calibration Model, see Mei07icra for details | ||||
|  * @date Mar 8, 2014 | ||||
|  * @author Jing Dong | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @addtogroup geometry | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <gtsam/geometry/Cal3DS2.h> | ||||
| #include <gtsam/geometry/Point2.h> | ||||
| 
 | ||||
| namespace gtsam { | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Calibration of a omni-directional camera with mirror + lens radial distortion | ||||
|  * @addtogroup geometry | ||||
|  * \nosubgrouping | ||||
|  */ | ||||
| class GTSAM_EXPORT Cal3Unified : public Cal3DS2 { | ||||
| 
 | ||||
|   typedef Cal3Unified This; | ||||
|   typedef Cal3DS2 Base; | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|   double xi_;  // mirror parameter
 | ||||
| 
 | ||||
|   // K = [ fx s u0 ; 0 fy v0 ; 0 0 1 ]
 | ||||
|   // Pn = [ P.x / (1 + xi * \sqrt{P.x^2 + P.y^2 + 1}), P.y / (1 + xi * \sqrt{P.x^2 + P.y^2 + 1})]
 | ||||
|   // rr = Pn.x^2 + Pn.y^2
 | ||||
|   // \hat{pn} = (1 + k1*rr + k2*rr^2 ) pn + [ 2*k3 pn.x pn.y + k4 (rr + 2 Pn.x^2) ;
 | ||||
|   //                      k3 (rr + 2 Pn.y^2) + 2*k4 pn.x pn.y  ]
 | ||||
|   // pi = K*pn
 | ||||
| 
 | ||||
| public: | ||||
|   //Matrix K() const ;
 | ||||
|   //Eigen::Vector4d k() const { return Base::k(); }
 | ||||
|   Vector vector() const ; | ||||
| 
 | ||||
|   /// @name Standard Constructors
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   /// Default Constructor with only unit focal length
 | ||||
|   Cal3Unified() : Base(), xi_(0) {} | ||||
| 
 | ||||
|   Cal3Unified(double fx, double fy, double s, double u0, double v0, | ||||
|       double k1, double k2, double k3 = 0.0, double k4 = 0.0, double xi = 0.0) : | ||||
|         Base(fx, fy, s, u0, v0, k1, k2, k3, k4), xi_(xi) {} | ||||
| 
 | ||||
|   /// @}
 | ||||
|   /// @name Advanced Constructors
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   Cal3Unified(const Vector &v) ; | ||||
| 
 | ||||
|   /// @}
 | ||||
|   /// @name Testable
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   /// print with optional string
 | ||||
|   void print(const std::string& s = "") const ; | ||||
| 
 | ||||
|   /// assert equality up to a tolerance
 | ||||
|   bool equals(const Cal3Unified& K, double tol = 10e-9) const; | ||||
| 
 | ||||
|   /// @}
 | ||||
|   /// @name Standard Interface
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   /// mirror parameter
 | ||||
|   inline double xi() const { return xi_;} | ||||
| 
 | ||||
|   /**
 | ||||
|    * convert intrinsic coordinates xy to image coordinates uv | ||||
|    * @param p point in intrinsic coordinates | ||||
|    * @param Dcal optional 2*9 Jacobian wrpt Cal3DS2 parameters | ||||
|    * @param Dp optional 2*2 Jacobian wrpt intrinsic coordinates | ||||
|    * @return point in image coordinates | ||||
|    */ | ||||
|   Point2 uncalibrate(const Point2& p, | ||||
|       boost::optional<Matrix&> Dcal = boost::none, | ||||
|       boost::optional<Matrix&> Dp = boost::none) const ; | ||||
| 
 | ||||
|   /// Conver a pixel coordinate to ideal coordinate
 | ||||
|   Point2 calibrate(const Point2& p, const double tol=1e-5) const; | ||||
| 
 | ||||
|   /// Convert a 3D point to normalized unit plane
 | ||||
|   Point2 spaceToNPlane(const Point2& p) const; | ||||
| 
 | ||||
|   /// Convert a normalized unit plane point to 3D space
 | ||||
|   Point2 nPlaneToSpace(const Point2& p) const; | ||||
| 
 | ||||
|   /// @}
 | ||||
|   /// @name Manifold
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   /// Given delta vector, update calibration
 | ||||
|   Cal3Unified retract(const Vector& d) const ; | ||||
| 
 | ||||
|   /// Given a different calibration, calculate update to obtain it
 | ||||
|   Vector localCoordinates(const Cal3Unified& T2) const ; | ||||
| 
 | ||||
|   /// Return dimensions of calibration manifold object
 | ||||
|   virtual size_t dim() const { return 10 ; } //TODO: make a final dimension variable (also, usually size_t in other classes e.g. Pose2)
 | ||||
| 
 | ||||
|   /// Return dimensions of calibration manifold object
 | ||||
|   static size_t Dim() { return 10; }  //TODO: make a final dimension variable
 | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|   /// @}
 | ||||
|   /// @name Advanced Interface
 | ||||
|   /// @{
 | ||||
| 
 | ||||
|   /** Serialization function */ | ||||
|   friend class boost::serialization::access; | ||||
|   template<class Archive> | ||||
|   void serialize(Archive & ar, const unsigned int version) | ||||
|   { | ||||
|     ar & boost::serialization::make_nvp("Cal3Unified", | ||||
|         boost::serialization::base_object<Cal3DS2>(*this)); | ||||
|     ar & BOOST_SERIALIZATION_NVP(xi_); | ||||
|   } | ||||
| 
 | ||||
|   /// @}
 | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -0,0 +1,102 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | ||||
|  * Atlanta, Georgia 30332-0415 | ||||
|  * All Rights Reserved | ||||
|  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | ||||
| 
 | ||||
|  * See LICENSE for the license information | ||||
| 
 | ||||
|  * -------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @file  testCal3Unify.cpp | ||||
|  * @brief Unit tests for transform derivatives | ||||
|  */ | ||||
| 
 | ||||
| #include <CppUnitLite/TestHarness.h> | ||||
| #include <gtsam/base/Testable.h> | ||||
| #include <gtsam/base/numericalDerivative.h> | ||||
| #include <gtsam/geometry/Cal3Unified.h> | ||||
| 
 | ||||
| using namespace gtsam; | ||||
| 
 | ||||
| GTSAM_CONCEPT_TESTABLE_INST(Cal3Unified) | ||||
| GTSAM_CONCEPT_MANIFOLD_INST(Cal3Unified) | ||||
| 
 | ||||
| /*
 | ||||
| ground truth from matlab, code : | ||||
| X = [0.5 0.7 1]'; | ||||
| V = [0.1, 1e-3, 2.0*1e-3, 3.0*1e-3, 4.0*1e-3, 0, 0, 100, 105, 320, 240]; | ||||
| [P, J] = spaceToImgPlane(X, V); | ||||
| matlab toolbox available at http://homepages.laas.fr/~cmei/index.php/Toolbox
 | ||||
| */ | ||||
| 
 | ||||
| static Cal3Unified K(100, 105, 0.0, 320, 240, 1e-3, 2.0*1e-3, 3.0*1e-3, 4.0*1e-3, 0.1); | ||||
| static Point2 p(0.5, 0.7); | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, uncalibrate) | ||||
| { | ||||
|   Point2 p_i(364.7791831734982, 305.6677211952602) ; | ||||
|   Point2 q = K.uncalibrate(p); | ||||
|   CHECK(assert_equal(q,p_i)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, spaceNplane) | ||||
| { | ||||
|   Point2 q = K.spaceToNPlane(p); | ||||
|   CHECK(assert_equal(Point2(0.441731600049497, 0.618424240069295), q)); | ||||
|   CHECK(assert_equal(p, K.nPlaneToSpace(q))); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, calibrate) | ||||
| { | ||||
|   Point2 pi = K.uncalibrate(p); | ||||
|   Point2 pn_hat = K.calibrate(pi); | ||||
|   CHECK( p.equals(pn_hat, 1e-8)); | ||||
| } | ||||
| 
 | ||||
| Point2 uncalibrate_(const Cal3Unified& k, const Point2& pt) { return k.uncalibrate(pt); } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, Duncalibrate1) | ||||
| { | ||||
|   Matrix computed; | ||||
|   K.uncalibrate(p, computed, boost::none); | ||||
|   Matrix numerical = numericalDerivative21(uncalibrate_, K, p, 1e-7); | ||||
|   CHECK(assert_equal(numerical,computed,1e-6)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, Duncalibrate2) | ||||
| { | ||||
|   Matrix computed; | ||||
|   K.uncalibrate(p, boost::none, computed); | ||||
|   Matrix numerical = numericalDerivative22(uncalibrate_, K, p, 1e-7); | ||||
|   CHECK(assert_equal(numerical,computed,1e-6)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, assert_equal) | ||||
| { | ||||
|   CHECK(assert_equal(K,K,1e-9)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| TEST( Cal3Unified, retract) | ||||
| { | ||||
|   Cal3Unified expected(100 + 2, 105 + 3, 0.0 + 4, 320 + 5, 240 + 6, | ||||
|       1e-3 + 7, 2.0*1e-3 + 8, 3.0*1e-3 + 9, 4.0*1e-3 + 10, 0.1 + 1); | ||||
|   Vector d(10); | ||||
|   d << 2, 3, 4, 5, 6, 7, 8, 9, 10, 1; | ||||
|   Cal3Unified actual = K.retract(d); | ||||
|   CHECK(assert_equal(expected,actual,1e-9)); | ||||
|   CHECK(assert_equal(d,K.localCoordinates(actual),1e-9)); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| int main() { TestResult tr; return TestRegistry::runAllTests(tr); } | ||||
| /* ************************************************************************* */ | ||||
		Loading…
	
		Reference in New Issue