Files
vio/GPU_version/svo/include/gpu_svo/nlls_solver.h
T
2021-05-26 10:50:20 +02:00

170 lines
5.0 KiB
C++

/*
* Abstract Nonlinear Least-Squares Solver Class
*
* nlls_solver.h
*
* Created on: Nov 5, 2012
* Author: cforster
*/
#ifndef LM_SOLVER_H_
#define LM_SOLVER_H_
#include <stdint.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <Eigen/Core>
#include <Eigen/StdVector>
#include <gpu_svo/math_utils.h>
#include <gpu_svo/robust_cost.h>
namespace vk {
using namespace std;
using namespace Eigen;
/**
* \brief Abstract Class for solving nonlinear least-squares (NLLS) problems.
*
* The function implements two algorithms: Levenberg Marquardt and Gauss Newton
*
* Example implementations of this function can be found in the rpl_examples
* package: img_align_2d.cpp, img_align_3d.cpp
*
* Template Parameters:
* D : dimension of the residual
* T : type of the model, e.g. SE2, SE3
*/
template <int D, typename T>
class NLLSSolver {
public:
typedef T ModelType;
enum Method{GaussNewton, LevenbergMarquardt};
enum ScaleEstimatorType{UnitScale, TDistScale, MADScale, NormalScale};
enum WeightFunctionType{UnitWeight, TDistWeight, TukeyWeight, HuberWeight};
protected:
Matrix<double, D, D> H_; //!< Hessian approximation
Matrix<double, D, 1> Jres_; //!< Jacobian x Residual
Matrix<double, D, 1> x_; //!< update step
bool have_prior_;
ModelType prior_;
Matrix<double, D, D> I_prior_; //!< Prior information matrix (inverse covariance)
double chi2_;
double rho_;
Method method_;
/// If the flag linearize_system is set, the function must also compute the
/// Jacobian and set the member variables H_, Jres_
virtual double
computeResiduals (const ModelType& model,
bool linearize_system,
bool compute_weight_scale) = 0;
/// Solve the linear system H*x = Jres. This function must set the update
/// step in the member variable x_. Must return true if the system could be
/// solved and false if it was singular.
virtual int
solve () = 0;
virtual void
update (const ModelType& old_model, ModelType& new_model) = 0;
virtual void
applyPrior (const ModelType& current_model) { }
virtual void
startIteration () { }
virtual void
finishIteration () { }
virtual void
finishTrial () { }
public:
/// Damping parameter. If mu > 0, coefficient matrix is positive definite, this
/// ensures that x is a descent direction. If mu is large, x is a short step in
/// the steepest direction. This is good if the current iterate is far from the
/// solution. If mu is small, LM approximates gauss newton iteration and we
/// have (almost) quadratic convergence in the final stages.
double mu_init_, mu_;
double nu_init_, nu_; //!< Increase factor of mu after fail
size_t n_iter_init_, n_iter_; //!< Number of Iterations
size_t n_trials_; //!< Number of trials
size_t n_trials_max_; //!< Max number of trials
size_t n_meas_; //!< Number of measurements
bool stop_; //!< Stop flag
bool verbose_; //!< Output Statistics
double eps_; //!< Stop if update norm is smaller than eps
size_t iter_; //!< Current Iteration
// robust least squares
bool use_weights_;
float scale_;
robust_cost::ScaleEstimatorPtr scale_estimator_;
robust_cost::WeightFunctionPtr weight_function_;
NLLSSolver() :
have_prior_(false),
method_(LevenbergMarquardt),
mu_init_(0.01f),
mu_(mu_init_),
nu_init_(2.0),
nu_(nu_init_),
n_iter_init_(15),
n_iter_(n_iter_init_),
n_trials_(0),
n_trials_max_(5),
n_meas_(0),
stop_(false),
verbose_(true),
eps_(0.0000000001),
iter_(0),
use_weights_(false),
scale_(0.0),
scale_estimator_(NULL),
weight_function_(NULL)
{ }
virtual ~NLLSSolver() {}
/// Calls the GaussNewton or LevenbergMarquardt optimization strategy
void optimize(ModelType& model);
/// Gauss Newton optimization strategy
void optimizeGaussNewton(ModelType& model);
/// Levenberg Marquardt optimization strategy
void optimizeLevenbergMarquardt(ModelType& model);
/// Specify the robust cost that should be used and the appropriate scale estimator
void setRobustCostFunction(
ScaleEstimatorType scale_estimator,
WeightFunctionType weight_function);
/// Add prior to optimization.
void setPrior(
const ModelType& prior,
const Matrix<double, D, D>& Information);
/// Reset all parameters to restart the optimization
void reset();
/// Get the squared error
const double& getChi2() const;
/// The Information matrix is equal to the inverse covariance matrix.
const Matrix<double, D, D>& getInformationMatrix() const;
};
} // end namespace vk
#include "gpu_svo/nlls_solver_impl.hpp"
#endif /* LM_SOLVER_H_ */