OptimizationAlgorithmFactory 类位于 optimization_algorithm_factory.h
cpp
//***g2o源码 g2o/g2o/core/optimization_algorithm_factory.h ***//
/**
* \brief create solvers based on their short name
*
* Factory to allocate solvers based on their short name.
* The Factory is implemented as a sigleton and the single
* instance can be accessed via the instance() function.
*/
/**
* \brief 工厂类用于根据优化算法的名称创建不同的优化算法(OptimizationAlgorithm)
*
* 工厂类是单例模式(singleton)的实现,可以通过instance()方法获取唯一的实例,
* 并通过destroy()方法释放实例。
*/
class G2O_CORE_API OptimizationAlgorithmFactory
{
public:
typedef std::list<AbstractOptimizationAlgorithmCreator*> CreatorList;
//! return the instance
//! 获取工厂类的唯一实例
static OptimizationAlgorithmFactory* instance();
//! free the instance
//! 释放唯一实例
static void destroy();
/**
* register a specific creator for allocating a solver
* 注册特定的创建者 creator 以分配求解器 solver
*/
void registerSolver(AbstractOptimizationAlgorithmCreator* c);
/**
* unregister a specific creator for allocating a solver
*/
void unregisterSolver(AbstractOptimizationAlgorithmCreator* c);
/**
* construct a solver based on its name, e.g., var, fix3_2_cholmod
* 根据名称 tag 来创建求解器 solver
*/
OptimizationAlgorithm* construct(const std::string& tag, OptimizationAlgorithmProperty& solverProperty) const;
//! list the known solvers into a stream
//! 将已知的求解器 solver 列到流中
void listSolvers(std::ostream& os) const;
//! return the underlying list of creators
//! 返回创建者 creators 的基本列表
const CreatorList& creatorList() const { return _creator;}
protected:
OptimizationAlgorithmFactory();
~OptimizationAlgorithmFactory();
CreatorList _creator;
CreatorList::const_iterator findSolver(const std::string& name) const;
CreatorList::iterator findSolver(const std::string& name);
private:
static OptimizationAlgorithmFactory* factoryInstance;
};
还有 RobustKernelFactory
cpp
//***g2o源码 g2o/g2o/core/robust_kernel_factory.h ***//
/**
* \brief create robust kernels based on their human readable name
*/
class G2O_CORE_API RobustKernelFactory
{
public:
//! return the instance
static RobustKernelFactory* instance();
//! free the instance
static void destroy();
/**
* register a tag for a specific creator
*/
void registerRobustKernel(const std::string& tag, AbstractRobustKernelCreator* c);
/**
* unregister a tag for a specific creator
*/
void unregisterType(const std::string& tag);
/**
* construct a robust kernel based on its tag
*/
RobustKernel* construct(const std::string& tag) const;
/**
* return the creator for a specific tag
*/
AbstractRobustKernelCreator* creator(const std::string& tag) const;
/**
* get a list of all known robust kernels
*/
void fillKnownKernels(std::vector<std::string>& types) const;
protected:
typedef std::map<std::string, AbstractRobustKernelCreator*> CreatorMap;
RobustKernelFactory();
~RobustKernelFactory();
CreatorMap _creator; ///< look-up map for the existing creators
private:
static RobustKernelFactory* factoryInstance;
};
示例代码:
cpp
// 这里使用一个工厂函数同时初始化迭代方式和线性求解方式,后续可以将迭代方式(总求解器 solver)和线性求解方式(线性求解器 LinearSolver)分开
// 创建一个指向 g2o::OptimizationAlgorithmFactory 的实例指针
g2o::OptimizationAlgorithmFactory *solver_factory = g2o::OptimizationAlgorithmFactory::instance();
// 定义一个 g2o::OptimizationAlgorithmProperty 类型的对象用于存储与优化算法相关的元信息
g2o::OptimizationAlgorithmProperty solver_property;
// 根据名称 tag 创建求解器 solver,调用 construct() 时,函数会将所构建的求解器相关的元信息存储到这个对象中,
// 比如该求解器的名称、是否需要舒尔补、位姿自由度、地图路标自由度等。
g2o::OptimizationAlgorithm *solver = solver_factory->construct("lm_var", solver_property);
std::unique_ptr<g2o::SparseOptimizer> graph_ptr_;
graph_ptr_.reset(new g2o::SparseOptimizer());
graph_ptr_->setAlgorithm(solver);
if (!graph_ptr_->solver()) {
LOG(ERROR) << "G2O 优化器创建失败!";
}
// 创建一个指向 g2o::RobustKernelFactory 的实例指针
g2o::RobustKernelFactory *robust_kernel_factory_ = g2o::RobustKernelFactory::instance();
// 根据给定的标签 tag 返回对应的鲁棒核函数实例
g2o::RobustKernel *kernel = robust_kernel_factory_->construct(tag);
// 设置鲁棒核函数的阈值为 delta_th
kernel->setDelta(delta_th);
其中,OptimizationAlgorithm* construct(const std::string& tag, OptimizationAlgorithmProperty& solverProperty) const; 函数中 tag 的所有可用算法与其对应描述有:
cpp
//*** g2o源码 g2o/g2o/solvers/cholmod/solver_cholmod.cpp ***//
G2O_REGISTER_OPTIMIZATION_LIBRARY(cholmod);
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_var_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"gn_var_cholmod",
"Gauss-Newton: Cholesky solver using CHOLMOD (variable blocksize)",
"CHOLMOD", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_fix3_2_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"gn_fix3_2_cholmod",
"Gauss-Newton: Cholesky solver using CHOLMOD (fixed blocksize)",
"CHOLMOD", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_fix6_3_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"gn_fix6_3_cholmod",
"Gauss-Newton: Cholesky solver using CHOLMOD (fixed blocksize)",
"CHOLMOD", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_fix7_3_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"gn_fix7_3_cholmod",
"Gauss-Newton: Cholesky solver using CHOLMOD (fixed blocksize)",
"CHOLMOD", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_var_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"lm_var_cholmod",
"Levenberg: Cholesky solver using CHOLMOD (variable blocksize)",
"CHOLMOD", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_fix3_2_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"lm_fix3_2_cholmod",
"Levenberg: Cholesky solver using CHOLMOD (fixed blocksize)", "CHOLMOD",
true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_fix6_3_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"lm_fix6_3_cholmod",
"Levenberg: Cholesky solver using CHOLMOD (fixed blocksize)", "CHOLMOD",
true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_fix7_3_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"lm_fix7_3_cholmod",
"Levenberg: Cholesky solver using CHOLMOD (fixed blocksize)", "CHOLMOD",
true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
dl_var_cholmod,
new CholmodSolverCreator(OptimizationAlgorithmProperty(
"dl_var_cholmod",
"Dogleg: Cholesky solver using CHOLMOD (variable blocksize)", "CHOLMOD",
false, Eigen::Dynamic, Eigen::Dynamic)));
cpp
//*** g2o源码 g2o/g2o/solvers/csparse/solver_csparse.cpp ***//
G2O_REGISTER_OPTIMIZATION_LIBRARY(csparse);
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_var_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("gn_var_csparse", "Gauss-Newton: Cholesky solver using CSparse (variable blocksize)", "CSparse", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix3_2_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("gn_fix3_2_csparse", "Gauss-Newton: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix6_3_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("gn_fix6_3_csparse", "Gauss-Newton: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix7_3_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("gn_fix7_3_csparse", "Gauss-Newton: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_var_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("lm_var_csparse", "Levenberg: Cholesky solver using CSparse (variable blocksize)", "CSparse", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix3_2_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("lm_fix3_2_csparse", "Levenberg: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix6_3_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("lm_fix6_3_csparse", "Levenberg: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix7_3_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("lm_fix7_3_csparse", "Levenberg: Cholesky solver using CSparse (fixed blocksize)", "CSparse", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(dl_var_csparse, new CSparseSolverCreator(OptimizationAlgorithmProperty("dl_var_csparse", "Dogleg: Cholesky solver using CSparse (variable blocksize)", "CSparse", false, Eigen::Dynamic, Eigen::Dynamic)));
cpp
//*** g2o源码 g2o/g2o/solvers/eigen/solver_eigen.cpp ***//
G2O_REGISTER_OPTIMIZATION_LIBRARY(eigen);
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_var, new EigenSolverCreator(OptimizationAlgorithmProperty("gn_var", "Gauss-Newton: Cholesky solver using Eigen's Sparse Cholesky methods (variable blocksize)", "Eigen", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix3_2, new EigenSolverCreator(OptimizationAlgorithmProperty("gn_fix3_2", "Gauss-Newton: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix6_3, new EigenSolverCreator(OptimizationAlgorithmProperty("gn_fix6_3", "Gauss-Newton: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(gn_fix7_3, new EigenSolverCreator(OptimizationAlgorithmProperty("gn_fix7_3", "Gauss-Newton: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_var, new EigenSolverCreator(OptimizationAlgorithmProperty("lm_var", "Levenberg: Cholesky solver using Eigen's Sparse Cholesky methods (variable blocksize)", "Eigen", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix3_2, new EigenSolverCreator(OptimizationAlgorithmProperty("lm_fix3_2", "Levenberg: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix6_3, new EigenSolverCreator(OptimizationAlgorithmProperty("lm_fix6_3", "Levenberg: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(lm_fix7_3, new EigenSolverCreator(OptimizationAlgorithmProperty("lm_fix7_3", "Levenberg: Cholesky solver using Eigen's Sparse Cholesky (fixed blocksize)", "Eigen", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(dl_var, new EigenSolverCreator(OptimizationAlgorithmProperty("dl_var", "Dogleg: Cholesky solver using Eigen's Sparse Cholesky methods (variable blocksize)", "Eigen", false, Eigen::Dynamic, Eigen::Dynamic)));
cpp
//*** g2o源码 g2o/g2o/solvers/dense/solver_dense.cpp ***//
G2O_REGISTER_OPTIMIZATION_LIBRARY(dense);
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_dense, new DenseSolverCreator(OptimizationAlgorithmProperty(
"gn_dense", "Gauss-Newton: Dense solver (variable blocksize)",
"Dense", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_dense3_2,
new DenseSolverCreator(OptimizationAlgorithmProperty(
"gn_dense3_2", "Gauss-Newton: Dense solver (fixed blocksize)", "Dense",
true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_dense6_3,
new DenseSolverCreator(OptimizationAlgorithmProperty(
"gn_dense6_3", "Gauss-Newton: Dense solver (fixed blocksize)", "Dense",
true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_dense7_3,
new DenseSolverCreator(OptimizationAlgorithmProperty(
"gn_dense7_3", "Gauss-Newton: Dense solver (fixed blocksize)", "Dense",
true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_dense, new DenseSolverCreator(OptimizationAlgorithmProperty(
"lm_dense", "Levenberg: Dense solver (variable blocksize)",
"Dense", false, -1, -1)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_dense3_2, new DenseSolverCreator(OptimizationAlgorithmProperty(
"lm_dense3_2", "Levenberg: Dense solver (fixed blocksize)",
"Dense", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_dense6_3, new DenseSolverCreator(OptimizationAlgorithmProperty(
"lm_dense6_3", "Levenberg: Dense solver (fixed blocksize)",
"Dense", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_dense7_3, new DenseSolverCreator(OptimizationAlgorithmProperty(
"lm_dense7_3", "Levenberg: Dense solver (fixed blocksize)",
"Dense", true, 7, 3)));
cpp
//*** g2o源码 g2o/g2o/solvers/pcg/solver_pcg.cpp ***//
G2O_REGISTER_OPTIMIZATION_LIBRARY(pcg);
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_pcg, new PCGSolverCreator(OptimizationAlgorithmProperty(
"gn_pcg",
"Gauss-Newton: PCG solver using block-Jacobi pre-conditioner "
"(variable blocksize)",
"PCG", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_pcg3_2, new PCGSolverCreator(OptimizationAlgorithmProperty(
"gn_pcg3_2",
"Gauss-Newton: PCG solver using block-Jacobi "
"pre-conditioner (fixed blocksize)",
"PCG", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_pcg6_3, new PCGSolverCreator(OptimizationAlgorithmProperty(
"gn_pcg6_3",
"Gauss-Newton: PCG solver using block-Jacobi "
"pre-conditioner (fixed blocksize)",
"PCG", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
gn_pcg7_3, new PCGSolverCreator(OptimizationAlgorithmProperty(
"gn_pcg7_3",
"Gauss-Newton: PCG solver using block-Jacobi "
"pre-conditioner (fixed blocksize)",
"PCG", true, 7, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_pcg, new PCGSolverCreator(OptimizationAlgorithmProperty(
"lm_pcg",
"Levenberg: PCG solver using block-Jacobi pre-conditioner "
"(variable blocksize)",
"PCG", false, Eigen::Dynamic, Eigen::Dynamic)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_pcg3_2, new PCGSolverCreator(OptimizationAlgorithmProperty(
"lm_pcg3_2",
"Levenberg: PCG solver using block-Jacobi pre-conditioner "
"(fixed blocksize)",
"PCG", true, 3, 2)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_pcg6_3, new PCGSolverCreator(OptimizationAlgorithmProperty(
"lm_pcg6_3",
"Levenberg: PCG solver using block-Jacobi pre-conditioner "
"(fixed blocksize)",
"PCG", true, 6, 3)));
G2O_REGISTER_OPTIMIZATION_ALGORITHM(
lm_pcg7_3, new PCGSolverCreator(OptimizationAlgorithmProperty(
"lm_pcg7_3",
"Levenberg: PCG solver using block-Jacobi pre-conditioner "
"(fixed blocksize)",
"PCG", true, 7, 3)));
其中 RobustKernel* construct(const std::string& tag) const; 函数中 tag 的所有可用鲁棒核函数有:
cpp
//*** g2o源码 g2o/g2o/core/robust_kernel_impl.cpp ***//
// register the kernel to their factory
G2O_REGISTER_ROBUST_KERNEL(Huber, RobustKernelHuber)
G2O_REGISTER_ROBUST_KERNEL(PseudoHuber, RobustKernelPseudoHuber)
G2O_REGISTER_ROBUST_KERNEL(Cauchy, RobustKernelCauchy)
G2O_REGISTER_ROBUST_KERNEL(GemanMcClure, RobustKernelGemanMcClure)
G2O_REGISTER_ROBUST_KERNEL(Welsch, RobustKernelWelsch)
G2O_REGISTER_ROBUST_KERNEL(Fair, RobustKernelFair)
G2O_REGISTER_ROBUST_KERNEL(Tukey, RobustKernelTukey)
G2O_REGISTER_ROBUST_KERNEL(Saturated, RobustKernelSaturated)
G2O_REGISTER_ROBUST_KERNEL(DCS, RobustKernelDCS)