Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cal3 Base Class #626

Merged
merged 18 commits into from
Dec 3, 2020
Merged

Cal3 Base Class #626

merged 18 commits into from
Dec 3, 2020

Conversation

varunagrawal
Copy link
Collaborator

I went ahead and created the common base class for all calibration models, which is Cal3.
This base class helps remove A LOT of redundancy and copy-pasta. I also took advantage of this opportunity to modernize the code as much as possible, using better conventions (such as base-class equality checking and std::fabs).

Also did a lot of formatting for parts that I've touched. As a result, this is a big PR and may need to go through multiple iterations.

@varunagrawal varunagrawal added enhancement Improvement to GTSAM design Design choices cleanup Help clean up old/obsolete aspects of GTSAM refactor Refactoring of code to remove rot labels Dec 1, 2020
@varunagrawal varunagrawal self-assigned this Dec 1, 2020
Copy link
Member

@jlblancoc jlblancoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good! I just left some random comments...


/* ************************************************************************* */
Cal3::Cal3(const std::string& path)
: fx_(320), fy_(320), s_(0), u0_(320), v0_(140) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer double fx_ = 320.0f; etc. in the .h (C++11 feature) instead of here at the .cpp. It's easier for the reader to see what are the defaults, and makes harder to be inconsistent between different ctors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like your suggestion, but the default constructor uses fx_ = 1, fy_ = 1 etc. Should I replace that with the defaults from this constuctor (from string path)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... good point. I think you should leave them like double fx_ = 1.0; etc. for consistency with the default ctor, then here in this ctor from a file, the defaults actually shouldn't matter since at the ctor should either: a) return with the new values from the file, or b) throw an exception if error loading... right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true. Let me update that really quick.

: fx_(320), fy_(320), s_(0), u0_(320), v0_(140) {
char buffer[200];
buffer[0] = 0;
sprintf(buffer, "%s/calibration_info.txt", path.c_str());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security issue: potential out-of-buffer write.
Why not?

const auto buffer = path  + std::string("/calibration_info.txt");

(would be shorter with c++14's s-operator, but gtsam uses c++11 only).

gtsam/geometry/Cal3.cpp Show resolved Hide resolved
/// @{

/// Create a default calibration that leaves coordinates unchanged
Cal3() : fx_(1), fy_(1), s_(0), u0_(0), v0_(0) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refer to comment above. If defaults are like double fx_ = 1; then : Cal3() = default;.


/// constructor from vector
Cal3(const Vector& d)
: fx_(d(0)), fy_(d(1)), s_(d(2)), u0_(d(3)), v0_(d(4)) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw is unexpected vector length?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! I updated all the vector constructors to have fixed size vectors so this is caught at compile-time (aka no nasty surprises).

/// @name Advanced Constructors
/// @{

/// load calibration from location (default name is calibration_info.txt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document expected file content format...

#endif

/// return inverted calibration matrix inv(K)
Matrix3 matrix_inverse() const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method name is all lowercase, principalPoint is camel case... (??).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah great catch. It would be an API change, but renaming it to inverse() makes more sense?

Copy link
Member

@dellaert dellaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bunch of comments, but awe-inspiring nice PR !

Cal3::Cal3(double fov, int w, int h)
: s_(0), u0_((double)w / 2.0), v0_((double)h / 2.0) {
double a = fov * M_PI / 360.0; // fov/2 in radians
// old formula: fx_ = (double) w * tan(a);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I should just kill that.

#endif

/// Return inverted calibration matrix inv(K)
Matrix3 inverse() const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to cpp?

double u0_, v0_; ///< image center, not a parameter to be optimized but a constant
double tol_; ///< tolerance value when calibrating
private:
double f_ = 1.0f; ///< focal length
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we still have this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cal3Bundler doesn't use fx_ or fy_ like the base class, just a single, common f value. Though now that I think about it, I can do something about it.

@@ -109,6 +111,11 @@ class GTSAM_EXPORT Cal3Bundler {
return v0_;
}

Matrix3 K() const; ///< Standard 3*3 calibration matrix
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is in base class, should be omitted or made override?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should override, since we should force skew to be 0, even if it is read from a file.

|| std::abs(v0_ - K.v0_) > tol)
return false;
return true;
return (std::fabs(f_ - K.f_) < tol && std::fabs(k1_ - K.k1_) < tol &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about base? And I think f should go :-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. Don't know how I missed that, then again this is a ginormous PR.

@@ -34,65 +34,58 @@ namespace gtsam {
* but using only k1,k2,p1, and p2 coefficients.
* K = [ fx s u0 ; 0 fy v0 ; 0 0 1 ]
* rr = Pn.x^2 + Pn.y^2
* \hat{Pn} = (1 + k1*rr + k2*rr^2 ) Pn + [ 2*p1 Pn.x Pn.y + p2 (rr + 2 Pn.x^2) ;
* \hat{Pn} = (1 + k1*rr + k2*rr^2 ) Pn + [ 2*p1 Pn.x Pn.y + p2 (rr + 2 Pn.x^2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What, no unicode??? ;-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aye aye, Cap'n.

/// Return dimensions of calibration manifold object
virtual size_t dim() const { return 9; }
virtual size_t dim() const { return dimension; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add to base and override if not just return Dim();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each model has a different dimension (though some have common values for dimension), so I'll have to pick and choose.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I can just get rid of the subclass dim() methods and use your suggestion of return Dim().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checked with a unit test: we will need to override dim(). 😞


/// Return dimensions of calibration manifold object
static size_t Dim() { return 9; }
static size_t Dim() { return dimension; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THis might be harder to put in base class, with static involved?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes especially since we are using this to differentiate the various dimensionalities.

double delta_u = u - u0_, delta_v = v - v0_;
double inv_fx = 1 / fx_, inv_fy = 1 / fy_;
double inv_fy_delta_v = inv_fy * delta_v,
inv_fx_s_inv_fy = inv_fx * s_ * inv_fy;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing?

CHECK(assert_equal((Vector)intrinsic, (Vector)K.calibrate(image)));
}

//TODO(Varun) Add calibrate and uncalibrate methods
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stick these in a different branch, PR, rather than landing commented out code.

@varunagrawal
Copy link
Collaborator Author

All done! I'll merge once CI passes. 🎉

@varunagrawal varunagrawal merged commit 091fa9b into develop Dec 3, 2020
@varunagrawal varunagrawal deleted the feature/cal3 branch December 3, 2020 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cleanup Help clean up old/obsolete aspects of GTSAM design Design choices enhancement Improvement to GTSAM refactor Refactoring of code to remove rot
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants