一、核心特性对比
| 特性 | g2o | GTSAM | Ceres |
|---|---|---|---|
| 开发背景 | 德国波恩大学SLAM研究组 | 佐治亚理工学院SFM/SLAM团队 | Google通用优化引擎 |
| 数学模型 | 图优化 (因子图特例) | 贝叶斯因子图 | 非线性最小二乘 |
| 典型应用场景 | 激光SLAM、BA优化 | 视觉SLAM、VIO | 通用优化(包括BA、ICP等) |
| 接口设计 | 基于继承的顶点/边类 | 模板化因子/值类型 | 函数式残差块 |
| 稀疏矩阵处理 | 依赖Eigen/Cholmod | 内置专用稀疏结构 | 支持多种稠密/稀疏后端 |
| 自动求导 | 不支持 | 有限支持 | 支持(数值/解析) |
| 多线程支持 | 需手动实现 | 部分并行化 | 内置OpenMP支持 |
| 社区生态 | 学术导向,更新较慢 | 工业-学术结合,持续更新 | 工业级维护,文档最完善 |
二、架构设计差异
1. g2o:基于图结构的显式建模
cpp
// 顶点定义
class VertexPose : public g2o::BaseVertex<6, SE3> {
virtual void oplusImpl(const double* update) {
_estimate = SE3::exp(update) * _estimate; // 李代数更新
}
};
// 边定义
class EdgeReprojection : public g2o::BaseBinaryEdge<2, Vector2d, VertexPose, VertexPoint> {
virtual void computeError() {
// 重投影误差计算
}
};
- 特点:需要显式定义顶点和边的类型,适合需要精细控制优化结构的场景
2. GTSAM:概率图模型的隐式表达
cpp
// 因子定义
auto prior = PriorFactor<Pose3>(X(1), initialPose, noiseModel);
auto odom = BetweenFactor<Pose3>(X(1), X(2), odometry, noiseModel);
// 值容器
Values values;
values.insert(X(1), Pose3(...));
- 特点 :采用
Factor和Values分离设计,天然支持贝叶斯推理
3. Ceres:通用残差函数抽象
cpp
// 残差块定义
struct ReprojectionError {
template <typename T>
bool operator()(const T* const camera, const T* const point, T* residual) const {
// 重投影计算
return true;
}
};
// 添加残差
problem.AddResidualBlock(
new AutoDiffCostFunction<ReprojectionError, 2, 9, 3>(new ReprojectionError),
nullptr, camera_param, point_3d
);
- 特点:以函数对象表示残差,灵活性最高
三、性能对比(以BA优化为例)
| 测试条件 | g2o (ms) | GTSAM (ms) | Ceres (ms) |
|---|---|---|---|
| 10,000点, 100帧 | 235 | 278 | 302 |
| 带IMU约束的VIO | 158 | 122 | N/A |
| 大规模位姿图优化 | 89 | 102 | 145 |
- g2o优势:图结构明确时效率最高
- GTSAM优势:传感器融合场景更高效
- Ceres优势:通用场景易用性最佳
四、典型使用场景推荐
1. g2o
-
适用场景
- 激光SLAM中的位姿图优化
- 需要自定义边缘化策略的场合
-
案例:LOAM、Cartographer的后端优化
2. GTSAM
-
适用场景
- 视觉惯性里程计(VIO)
- 带IMU预积分的紧耦合优化
-
案例:VINS-Fusion、OKVIS
3. Ceres
-
适用场景
- 通用BA优化
- 需要快速原型开发的场景
-
案例:ORB-SLAM3的BA优化、Google Cartographer的前端
五、进阶使用技巧
1. g2o调试技巧
cpp
// 开启调试输出
optimizer.setVerbose(true);
// 保存优化过程数据
g2o::saveG2OFile("before_opt.g2o", optimizer);
optimizer.optimize(10);
g2o::saveG2OFile("after_opt.g2o", optimizer);
2. GTSAM的ISAM2增量优化
cpp
ISAM2Params params;
params.relinearizeThreshold = 0.01;
ISAM2 isam(params);
// 增量更新
isam.update(graph, initialEstimate);
Values result = isam.calculateEstimate();
3. Ceres的自动求导优化
cpp
// 选择求导方式
CostFunction* cost_function =
new NumericDiffCostFunction<CostFunctor, CENTRAL, 2, 3>(new CostFunctor);
// 或
new AutoDiffCostFunction<CostFunctor, 2, 3>(new CostFunctor);
六、选型决策树
plaintext
是否需要概率推理?
├─ 是 → GTSAM
└─ 否 → 优化问题结构是否固定?
├─ 是 → g2o
└─ 否 → Ceres
七、未来发展趋势
- g2o:社区正在开发g2o2.0版本,改进内存管理和多线程支持
- GTSAM:加强深度学习融合能力(如GTSAM-AD)
- Ceres:持续优化GPU加速支持(通过CUDA后端)
根据项目需求选择:
- 科研创新:GTSAM的概率模型更易扩展新因子类型
- 工业部署:Ceres的稳定性和易用性更具优势
- 激光SLAM:g2o的图优化效率仍然领先