109 lines
3.2 KiB
C++
109 lines
3.2 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* @file Sphere2.h
|
|
* @date Feb 02, 2011
|
|
* @author Can Erdogan
|
|
* @author Frank Dellaert
|
|
* @brief Develop a Sphere2 class - basically a point on a unit sphere
|
|
*/
|
|
|
|
#include <gtsam/geometry/Sphere2.h>
|
|
#include <gtsam/geometry/Point2.h>
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
|
|
namespace gtsam {
|
|
|
|
/* ************************************************************************* */
|
|
Matrix Sphere2::getBasis() const {
|
|
|
|
// Get the axis of rotation with the minimum projected length of the point
|
|
Point3 axis;
|
|
double mx = fabs(p_.x()), my = fabs(p_.y()), mz = fabs(p_.z());
|
|
if ((mx <= my) && (mx <= mz))
|
|
axis = Point3(1.0, 0.0, 0.0);
|
|
else if ((my <= mx) && (my <= mz))
|
|
axis = Point3(0.0, 1.0, 0.0);
|
|
else if ((mz <= mx) && (mz <= my))
|
|
axis = Point3(0.0, 0.0, 1.0);
|
|
else
|
|
assert(false);
|
|
|
|
// Create the two basis vectors
|
|
Point3 b1 = p_.cross(axis);
|
|
b1 = b1 / b1.norm();
|
|
Point3 b2 = p_.cross(b1);
|
|
b2 = b2 / b2.norm();
|
|
|
|
// Create the basis matrix
|
|
Matrix B(3, 2);
|
|
B << b1.x(), b2.x(), b1.y(), b2.y(), b1.z(), b2.z();
|
|
return B;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
/// The print fuction
|
|
void Sphere2::print(const std::string& s) const {
|
|
cout << s << ":" << p_ << endl;
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
Matrix Sphere2::skew() const {
|
|
return skewSymmetric(p_.x(), p_.y(), p_.z());
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
Sphere2 Sphere2::retract(const Vector& v) const {
|
|
|
|
// Get the vector form of the point and the basis matrix
|
|
Vector p = Point3::Logmap(p_);
|
|
Matrix B = getBasis();
|
|
|
|
// Compute the 3D xi_hat vector
|
|
Vector xi_hat = v(0) * B.col(0) + v(1) * B.col(1);
|
|
Vector newPoint = p + xi_hat;
|
|
|
|
// Project onto the manifold, i.e. the closest point on the circle to the new location;
|
|
// same as putting it onto the unit circle
|
|
Vector projected = newPoint / newPoint.norm();
|
|
|
|
return Sphere2(Point3::Expmap(projected));
|
|
}
|
|
|
|
/* ************************************************************************* */
|
|
Vector Sphere2::localCoordinates(const Sphere2& y) const {
|
|
|
|
// Make sure that the angle different between x and y is less than 90. Otherwise,
|
|
// we can project x + xi_hat from the tangent space at x to y.
|
|
double cosAngle = y.p_.dot(p_);
|
|
assert(cosAngle > 0.0 && "Can not retract from x to y.");
|
|
|
|
// Get the basis matrix
|
|
Matrix B = getBasis();
|
|
|
|
// Create the vector forms of p and q (the Point3 of y).
|
|
Vector p = Point3::Logmap(p_);
|
|
Vector q = Point3::Logmap(y.p_);
|
|
|
|
// Compute the basis coefficients [v0,v1] = (B'q)/(p'q).
|
|
double alpha = p.transpose() * q;
|
|
assert(alpha != 0.0);
|
|
Matrix coeffs = (B.transpose() * q) / alpha;
|
|
Vector result = Vector_(2, coeffs(0, 0), coeffs(1, 0));
|
|
return result;
|
|
}
|
|
/* ************************************************************************* */
|
|
|
|
}
|