Improved small angle behavior of retract
parent
fcbceaf746
commit
3245a2304e
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
#include <boost/random/variate_generator.hpp>
|
#include <boost/random/variate_generator.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
@ -135,37 +136,39 @@ double Unit3::distance(const Unit3& q, OptionalJacobian<1,2> H) const {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Unit3 Unit3::retract(const Vector2& v) const {
|
Unit3 Unit3::retract(const Vector2& v) const {
|
||||||
|
|
||||||
// Compute the 3D xi_hat vector
|
// Compute the 3D xi_hat vector
|
||||||
Vector3 xi_hat = basis() * v;
|
Vector3 xi_hat = basis() * v;
|
||||||
double xi_hat_norm = xi_hat.norm();
|
double theta = xi_hat.norm();
|
||||||
|
|
||||||
// When v is the so small and approximate as a direction
|
// Treat case of very small v differently
|
||||||
if (xi_hat_norm < 1e-8) {
|
if (theta < std::numeric_limits<double>::epsilon()) {
|
||||||
return Unit3(cos(xi_hat_norm) * p_ + xi_hat);
|
return Unit3(cos(theta) * p_ + xi_hat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 exp_p_xi_hat = cos(xi_hat_norm) * p_
|
Vector3 exp_p_xi_hat =
|
||||||
+ sin(xi_hat_norm) * (xi_hat / xi_hat_norm);
|
cos(theta) * p_ + xi_hat * (sin(theta) / theta);
|
||||||
return Unit3(exp_p_xi_hat);
|
return Unit3(exp_p_xi_hat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Vector2 Unit3::localCoordinates(const Unit3& y) const {
|
Vector2 Unit3::localCoordinates(const Unit3& other) const {
|
||||||
|
const double x = p_.dot(other.p_);
|
||||||
double dot = p_.dot(y.p_);
|
// Crucial quantitity here is y = theta/sin(theta) with theta=acos(x)
|
||||||
|
// Now, y = acos(x) / sin(acos(x)) = acos(x)/sqrt(1-x^2)
|
||||||
// Check for special cases
|
// We treat the special caes 1 and -1 below
|
||||||
if (std::abs(dot - 1.0) < 1e-16)
|
const double x2 = x * x;
|
||||||
return Vector2(0.0, 0.0);
|
const double z = 1 - x2;
|
||||||
else if (std::abs(dot + 1.0) < 1e-16)
|
double y;
|
||||||
return Vector2(M_PI, 0.0);
|
if (z < std::numeric_limits<double>::epsilon()) {
|
||||||
else {
|
if (x > 0) // expand at x=1
|
||||||
|
y = 1.0 - (x - 1.0) / 3.0;
|
||||||
|
else // cop out
|
||||||
|
return Vector2(M_PI, 0.0);
|
||||||
|
} else {
|
||||||
// no special case
|
// no special case
|
||||||
const double theta = acos(dot);
|
y = acos(x) / sqrt(z);
|
||||||
Vector3 result_hat = (theta / sin(theta)) * (y.p_ - p_ * dot);
|
|
||||||
return basis().transpose() * result_hat;
|
|
||||||
}
|
}
|
||||||
|
return basis().transpose() * y * (other.p_ - x * p_);
|
||||||
}
|
}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue