-
Notifications
You must be signed in to change notification settings - Fork 779
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
Add Similarity(2) support in gtsam/geometry #918
Merged
Merged
Changes from 29 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
d5918dc
Create Similarity2.h
johnwlambert 6b7b31a
Create Similarity2.cpp
johnwlambert e48704d
add basic Python interface to .i file
johnwlambert 6005390
add python unit tests
johnwlambert 8e9815b
fix typo
johnwlambert 9fd7451
add Pose2Pair typedef
johnwlambert 7082b67
fix typo in types
johnwlambert 4372ed8
add means() function to Point2.h
johnwlambert 1dd20a3
add missing `means()` function for Point2
johnwlambert 2252d5e
fix typo in size of mean vector for Point2Pair means()
johnwlambert dfb9497
add Rot2.ClosestTo()
johnwlambert 37af8cf
finish Rot2.ClosestTo()
johnwlambert 6853570
fix typo
johnwlambert c2040fb
use ClosestTo() in initializer list
johnwlambert 7ebbe18
fix Eigen error
784bdc6
minor fixes to Pose2 and Rot2
varunagrawal bf668e5
Similarity2 fixes
varunagrawal a57465e
Similarity3 fixes
varunagrawal 5e75986
fix wrapper
varunagrawal b484a21
fix tests
varunagrawal 1933597
Merge branch 'develop' into add-Similarity2-classes-2
varunagrawal c716f63
wrap Pose2Pairs
varunagrawal 5098706
wrap equals for Sim2 and Sim3
varunagrawal 464af9f
Fix syntactic errors in test_Sim2.py
varunagrawal 5a1797f
Merge branch 'develop' into add-Similarity2-classes
varunagrawal b60ca0f
Merge branch 'add-Similarity2-classes' into add-Similarity2-classes-2
varunagrawal cc8d80f
Remove SFINAE from KarcherMean so we can also use it for Rot2
varunagrawal 37ae703
Fix tests
varunagrawal 10554d8
Merge pull request #1090 from borglab/add-Similarity2-classes-2
johnwlambert d8e5658
capitalize static methods
varunagrawal 5be6309
GTSAM_EXPORT at the class level
varunagrawal 53b3705
remove Pose2/3 casts from Sim2/3
varunagrawal ad2e347
update assertions
varunagrawal ba6c3cc
Merge branch 'develop' into add-Similarity2-classes
varunagrawal e704b40
typo fix
varunagrawal 9eff71e
Rot2::ClosestTo with SVD
varunagrawal 7a56473
add Lie group operations
varunagrawal b8b52cb
AdjointMap method
varunagrawal a73d6e0
Sim3 cpp unit tests
varunagrawal 12dd2ec
identity needs to be lowercase and fix tests
varunagrawal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
/* ---------------------------------------------------------------------------- | ||
|
||
* 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 Similarity2.cpp | ||
* @brief Implementation of Similarity2 transform | ||
* @author John Lambert | ||
*/ | ||
|
||
#include <gtsam/base/Manifold.h> | ||
#include <gtsam/geometry/Pose2.h> | ||
#include <gtsam/geometry/Rot3.h> | ||
#include <gtsam/geometry/Similarity2.h> | ||
#include <gtsam/slam/KarcherMeanFactor-inl.h> | ||
|
||
namespace gtsam { | ||
|
||
using std::vector; | ||
|
||
namespace internal { | ||
|
||
/// Subtract centroids from point pairs. | ||
static Point2Pairs subtractCentroids(const Point2Pairs& abPointPairs, | ||
const Point2Pair& centroids) { | ||
Point2Pairs d_abPointPairs; | ||
for (const Point2Pair& abPair : abPointPairs) { | ||
Point2 da = abPair.first - centroids.first; | ||
Point2 db = abPair.second - centroids.second; | ||
d_abPointPairs.emplace_back(da, db); | ||
} | ||
return d_abPointPairs; | ||
} | ||
|
||
/// Form inner products x and y and calculate scale. | ||
static double calculateScale(const Point2Pairs& d_abPointPairs, | ||
const Rot2& aRb) { | ||
double x = 0, y = 0; | ||
dellaert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Point2 da, db; | ||
|
||
for (const Point2Pair& d_abPair : d_abPointPairs) { | ||
std::tie(da, db) = d_abPair; | ||
const Vector2 da_prime = aRb * db; | ||
y += da.transpose() * da_prime; | ||
x += da_prime.transpose() * da_prime; | ||
} | ||
const double s = y / x; | ||
return s; | ||
} | ||
|
||
/// Form outer product H. | ||
static Matrix2 calculateH(const Point2Pairs& d_abPointPairs) { | ||
Matrix2 H = Z_2x2; | ||
for (const Point2Pair& d_abPair : d_abPointPairs) { | ||
H += d_abPair.first * d_abPair.second.transpose(); | ||
} | ||
return H; | ||
} | ||
|
||
/** | ||
* @brief This method estimates the similarity transform from differences point | ||
* pairs, given a known or estimated rotation and point centroids. | ||
* | ||
* @param d_abPointPairs | ||
* @param aRb | ||
* @param centroids | ||
* @return Similarity2 | ||
*/ | ||
static Similarity2 align(const Point2Pairs& d_abPointPairs, const Rot2& aRb, | ||
const Point2Pair& centroids) { | ||
const double s = calculateScale(d_abPointPairs, aRb); | ||
// dividing aTb by s is required because the registration cost function | ||
// minimizes ||a - sRb - t||, whereas Sim(2) computes s(Rb + t) | ||
const Point2 aTb = (centroids.first - s * (aRb * centroids.second)) / s; | ||
return Similarity2(aRb, aTb, s); | ||
} | ||
|
||
/** | ||
* @brief This method estimates the similarity transform from point pairs, | ||
* given a known or estimated rotation. | ||
* Refer to: | ||
* http://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2005/Zinsser05-PSR.pdf | ||
* Chapter 3 | ||
* | ||
* @param abPointPairs | ||
* @param aRb | ||
* @return Similarity2 | ||
*/ | ||
static Similarity2 alignGivenR(const Point2Pairs& abPointPairs, | ||
varunagrawal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const Rot2& aRb) { | ||
auto centroids = means(abPointPairs); | ||
auto d_abPointPairs = internal::subtractCentroids(abPointPairs, centroids); | ||
return internal::align(d_abPointPairs, aRb, centroids); | ||
} | ||
} // namespace internal | ||
|
||
Similarity2::Similarity2() : t_(0, 0), s_(1) {} | ||
|
||
Similarity2::Similarity2(double s) : t_(0, 0), s_(s) {} | ||
|
||
Similarity2::Similarity2(const Rot2& R, const Point2& t, double s) | ||
: R_(R), t_(t), s_(s) {} | ||
|
||
Similarity2::Similarity2(const Matrix2& R, const Vector2& t, double s) | ||
: R_(Rot2::ClosestTo(R)), t_(t), s_(s) {} | ||
|
||
Similarity2::Similarity2(const Matrix3& T) | ||
: R_(Rot2::ClosestTo(T.topLeftCorner<2, 2>())), | ||
t_(T.topRightCorner<2, 1>()), | ||
s_(1.0 / T(2, 2)) {} | ||
|
||
bool Similarity2::equals(const Similarity2& other, double tol) const { | ||
return R_.equals(other.R_, tol) && | ||
traits<Point2>::Equals(t_, other.t_, tol) && s_ < (other.s_ + tol) && | ||
s_ > (other.s_ - tol); | ||
} | ||
|
||
bool Similarity2::operator==(const Similarity2& other) const { | ||
return R_.matrix() == other.R_.matrix() && t_ == other.t_ && s_ == other.s_; | ||
} | ||
|
||
void Similarity2::print(const std::string& s) const { | ||
std::cout << std::endl; | ||
std::cout << s; | ||
rotation().print("\nR:\n"); | ||
std::cout << "t: " << translation().transpose() << " s: " << scale() | ||
<< std::endl; | ||
} | ||
|
||
Similarity2 Similarity2::identity() { return Similarity2(); } | ||
|
||
Similarity2 Similarity2::operator*(const Similarity2& S) const { | ||
dellaert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return Similarity2(R_ * S.R_, ((1.0 / S.s_) * t_) + R_ * S.t_, s_ * S.s_); | ||
} | ||
|
||
Similarity2 Similarity2::inverse() const { | ||
const Rot2 Rt = R_.inverse(); | ||
const Point2 sRt = Rt * (-s_ * t_); | ||
return Similarity2(Rt, sRt, 1.0 / s_); | ||
} | ||
|
||
Point2 Similarity2::transformFrom(const Point2& p) const { | ||
const Point2 q = R_ * p + t_; | ||
return s_ * q; | ||
} | ||
|
||
Pose2 Similarity2::transformFrom(const Pose2& T) const { | ||
Rot2 R = R_.compose(T.rotation()); | ||
Point2 t = Point2(s_ * (R_ * T.translation() + t_)); | ||
return Pose2(R, t); | ||
} | ||
|
||
Point2 Similarity2::operator*(const Point2& p) const { | ||
return transformFrom(p); | ||
} | ||
|
||
Similarity2 Similarity2::Align(const Point2Pairs& abPointPairs) { | ||
// Refer to Chapter 3 of | ||
// http://www5.informatik.uni-erlangen.de/Forschung/Publikationen/2005/Zinsser05-PSR.pdf | ||
if (abPointPairs.size() < 2) | ||
throw std::runtime_error("input should have at least 2 pairs of points"); | ||
auto centroids = means(abPointPairs); | ||
auto d_abPointPairs = internal::subtractCentroids(abPointPairs, centroids); | ||
Matrix2 H = internal::calculateH(d_abPointPairs); | ||
// ClosestTo finds rotation matrix closest to H in Frobenius sense | ||
Rot2 aRb = Rot2::ClosestTo(H); | ||
return internal::align(d_abPointPairs, aRb, centroids); | ||
} | ||
|
||
Similarity2 Similarity2::Align(const Pose2Pairs& abPosePairs) { | ||
const size_t n = abPosePairs.size(); | ||
if (n < 2) | ||
throw std::runtime_error("input should have at least 2 pairs of poses"); | ||
|
||
// calculate rotation | ||
vector<Rot2> rotations; | ||
Point2Pairs abPointPairs; | ||
rotations.reserve(n); | ||
abPointPairs.reserve(n); | ||
// Below denotes the pose of the i'th object/camera/etc | ||
// in frame "a" or frame "b". | ||
Pose2 aTi, bTi; | ||
for (const Pose2Pair& abPair : abPosePairs) { | ||
std::tie(aTi, bTi) = abPair; | ||
const Rot2 aRb = aTi.rotation().compose(bTi.rotation().inverse()); | ||
rotations.emplace_back(aRb); | ||
abPointPairs.emplace_back(aTi.translation(), bTi.translation()); | ||
} | ||
const Rot2 aRb_estimate = FindKarcherMean<Rot2>(rotations); | ||
|
||
return internal::alignGivenR(abPointPairs, aRb_estimate); | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& os, const Similarity2& p) { | ||
os << "[" << p.rotation().theta() << " " << p.translation().transpose() << " " | ||
<< p.scale() << "]\';"; | ||
return os; | ||
} | ||
|
||
Matrix3 Similarity2::matrix() const { | ||
Matrix3 T; | ||
T.topRows<2>() << R_.matrix(), t_; | ||
T.bottomRows<1>() << 0, 0, 1.0 / s_; | ||
return T; | ||
} | ||
|
||
Similarity2::operator Pose2() const { return Pose2(R_, s_ * t_); } | ||
|
||
} // namespace gtsam |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this PR and my latest PR, I'm starting to think we should "light-deprecate" PointPairs and do the computation in Eigen.
https://eigen.tuxfamily.org/dox/group__TutorialReductionsVisitorsBroadcasting.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we save this for another PR in favor of landing this one?
We can create an issue to track it.