Merge pull request #495 from borglab/jingwu/shonan
Refactor MakeATangentVector by using VectorValues and fix testcase failurerelease/4.3a0
						commit
						144db8e11e
					
				| 
						 | 
					@ -643,20 +643,25 @@ bool ShonanAveraging<d>::checkOptimality(const Values &values) const {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ************************************************************************* */
 | 
					/* ************************************************************************* */
 | 
				
			||||||
/// Create a tangent direction xi with eigenvector segment v_i
 | 
					 | 
				
			||||||
template <size_t d>
 | 
					template <size_t d>
 | 
				
			||||||
Vector ShonanAveraging<d>::MakeATangentVector(size_t p, const Vector &v,
 | 
					VectorValues ShonanAveraging<d>::TangentVectorValues(size_t p,
 | 
				
			||||||
                                              size_t i) {
 | 
					                                                     const Vector &v) {
 | 
				
			||||||
 | 
					  VectorValues delta;
 | 
				
			||||||
  // Create a tangent direction xi with eigenvector segment v_i
 | 
					  // Create a tangent direction xi with eigenvector segment v_i
 | 
				
			||||||
  const size_t dimension = SOn::Dimension(p);
 | 
					  const size_t dimension = SOn::Dimension(p);
 | 
				
			||||||
  const auto v_i = v.segment<d>(d * i);
 | 
					  double sign0 = pow(-1.0, round((p + 1) / 2) + 1);
 | 
				
			||||||
  Vector xi = Vector::Zero(dimension);
 | 
					  for (size_t i = 0; i < v.size() / d; i++) {
 | 
				
			||||||
  double sign = pow(-1.0, round((p + 1) / 2) + 1);
 | 
					    // Assumes key is 0-based integer
 | 
				
			||||||
  for (size_t j = 0; j < d; j++) {
 | 
					    const auto v_i = v.segment<d>(d * i);
 | 
				
			||||||
    xi(j + p - d - 1) = sign * v_i(d - j - 1);
 | 
					    Vector xi = Vector::Zero(dimension);
 | 
				
			||||||
    sign = -sign;
 | 
					    double sign = sign0;
 | 
				
			||||||
 | 
					    for (size_t j = 0; j < d; j++) {
 | 
				
			||||||
 | 
					      xi(j + p - d - 1) = sign * v_i(d - j - 1);
 | 
				
			||||||
 | 
					      sign = -sign;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    delta.insert(i, xi);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return xi;
 | 
					  return delta;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ************************************************************************* */
 | 
					/* ************************************************************************* */
 | 
				
			||||||
| 
						 | 
					@ -690,14 +695,8 @@ template <size_t d>
 | 
				
			||||||
Values ShonanAveraging<d>::LiftwithDescent(size_t p, const Values &values,
 | 
					Values ShonanAveraging<d>::LiftwithDescent(size_t p, const Values &values,
 | 
				
			||||||
                                           const Vector &minEigenVector) {
 | 
					                                           const Vector &minEigenVector) {
 | 
				
			||||||
  Values lifted = LiftTo<SOn>(p, values);
 | 
					  Values lifted = LiftTo<SOn>(p, values);
 | 
				
			||||||
  for (auto it : lifted.filter<SOn>()) {
 | 
					  VectorValues delta = TangentVectorValues(p, minEigenVector);
 | 
				
			||||||
    // Create a tangent direction xi with eigenvector segment v_i
 | 
					  return lifted.retract(delta);
 | 
				
			||||||
    // Assumes key is 0-based integer
 | 
					 | 
				
			||||||
    const Vector xi = MakeATangentVector(p, minEigenVector, it.key);
 | 
					 | 
				
			||||||
    // Move the old value in the descent direction
 | 
					 | 
				
			||||||
    it.value = it.value.retract(xi);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return lifted;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ************************************************************************* */
 | 
					/* ************************************************************************* */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,12 +20,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <gtsam/base/Matrix.h>
 | 
					#include <gtsam/base/Matrix.h>
 | 
				
			||||||
#include <gtsam/base/Vector.h>
 | 
					#include <gtsam/base/Vector.h>
 | 
				
			||||||
 | 
					#include <gtsam/dllexport.h>
 | 
				
			||||||
#include <gtsam/geometry/Rot2.h>
 | 
					#include <gtsam/geometry/Rot2.h>
 | 
				
			||||||
#include <gtsam/geometry/Rot3.h>
 | 
					#include <gtsam/geometry/Rot3.h>
 | 
				
			||||||
 | 
					#include <gtsam/linear/VectorValues.h>
 | 
				
			||||||
#include <gtsam/nonlinear/LevenbergMarquardtParams.h>
 | 
					#include <gtsam/nonlinear/LevenbergMarquardtParams.h>
 | 
				
			||||||
#include <gtsam/sfm/BinaryMeasurement.h>
 | 
					#include <gtsam/sfm/BinaryMeasurement.h>
 | 
				
			||||||
#include <gtsam/slam/dataset.h>
 | 
					#include <gtsam/slam/dataset.h>
 | 
				
			||||||
#include <gtsam/dllexport.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <Eigen/Sparse>
 | 
					#include <Eigen/Sparse>
 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
| 
						 | 
					@ -200,8 +201,8 @@ public:
 | 
				
			||||||
  /// Project pxdN Stiefel manifold matrix S to Rot3^N
 | 
					  /// Project pxdN Stiefel manifold matrix S to Rot3^N
 | 
				
			||||||
  Values roundSolutionS(const Matrix &S) const;
 | 
					  Values roundSolutionS(const Matrix &S) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Create a tangent direction xi with eigenvector segment v_i
 | 
					  /// Create a VectorValues with eigenvector v_i
 | 
				
			||||||
  static Vector MakeATangentVector(size_t p, const Vector &v, size_t i);
 | 
					  static VectorValues TangentVectorValues(size_t p, const Vector &v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Calculate the riemannian gradient of F(values) at values
 | 
					  /// Calculate the riemannian gradient of F(values) at values
 | 
				
			||||||
  Matrix riemannianGradient(size_t p, const Values &values) const;
 | 
					  Matrix riemannianGradient(size_t p, const Values &values) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,18 +121,17 @@ TEST(ShonanAveraging3, tryOptimizingAt4) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ************************************************************************* */
 | 
					/* ************************************************************************* */
 | 
				
			||||||
TEST(ShonanAveraging3, MakeATangentVector) {
 | 
					TEST(ShonanAveraging3, TangentVectorValues) {
 | 
				
			||||||
  Vector9 v;
 | 
					  Vector9 v;
 | 
				
			||||||
  v << 1, 2, 3, 4, 5, 6, 7, 8, 9;
 | 
					  v << 1, 2, 3, 4, 5, 6, 7, 8, 9;
 | 
				
			||||||
  Matrix expected(5, 5);
 | 
					  Vector expected0(10), expected1(10), expected2(10);
 | 
				
			||||||
  expected << 0, 0, 0, 0, -4, //
 | 
					  expected0 << 0, 3, -2, 1, 0, 0, 0, 0, 0, 0;
 | 
				
			||||||
      0, 0, 0, 0, -5,         //
 | 
					  expected1 << 0, 6, -5, 4, 0, 0, 0, 0, 0, 0;
 | 
				
			||||||
      0, 0, 0, 0, -6,         //
 | 
					  expected2 << 0, 9, -8, 7, 0, 0, 0, 0, 0, 0;
 | 
				
			||||||
      0, 0, 0, 0, 0,          //
 | 
					  const VectorValues xi = ShonanAveraging3::TangentVectorValues(5, v);
 | 
				
			||||||
      4, 5, 6, 0, 0;
 | 
					  EXPECT(assert_equal(expected0, xi[0]));
 | 
				
			||||||
  const Vector xi_1 = ShonanAveraging3::MakeATangentVector(5, v, 1);
 | 
					  EXPECT(assert_equal(expected1, xi[1]));
 | 
				
			||||||
  const auto actual = SOn::Hat(xi_1);
 | 
					  EXPECT(assert_equal(expected2, xi[2]));
 | 
				
			||||||
  CHECK(assert_equal(expected, actual));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ************************************************************************* */
 | 
					/* ************************************************************************* */
 | 
				
			||||||
| 
						 | 
					@ -168,7 +167,8 @@ TEST(ShonanAveraging3, CheckWithEigen) {
 | 
				
			||||||
      minEigenValue = min(lambdas(i), minEigenValue);
 | 
					      minEigenValue = min(lambdas(i), minEigenValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Actual check
 | 
					  // Actual check
 | 
				
			||||||
  EXPECT_DOUBLES_EQUAL(minEigenValue, lambda, 1e-12);
 | 
					  EXPECT_DOUBLES_EQUAL(0, lambda, 1e-11);
 | 
				
			||||||
 | 
					  EXPECT_DOUBLES_EQUAL(0, minEigenValue, 1e-11);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Construct test descent direction (as minEigenVector is not predictable
 | 
					  // Construct test descent direction (as minEigenVector is not predictable
 | 
				
			||||||
  // across platforms, being one from a basically flat 3d- subspace)
 | 
					  // across platforms, being one from a basically flat 3d- subspace)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue