当前位置: 首页 > ds >正文

海森矩阵(Hessian Matrix)在SLAM图优化和点云配准中的应用介绍

在非线性最小二乘问题中(如 SLAM 或点云配准),通常我们有一个误差函数:

f(x)=∑i∥ei(x)∥2 f(x) = \sum_i \| e_i(x) \|^2 f(x)=iei(x)2

其中 ei(x)e_i(x)ei(x) 是残差项,对它求 Hessian 就需要用雅可比矩阵:

H=J⊤J+∑iei⊤Hei H = J^\top J + \sum_i e_i^\top H_{e_i} H=JJ+ieiHei

通常我们近似为:

H≈J⊤J H \approx J^\top J HJJ

这就是 高斯-牛顿法Levenberg-Marquardt(LM)方法 中用的近似 Hessian。


1、从误差平方和构建优化系统

最小化目标函数:

f(x)=12∑i∥ri(x)∥2 f(\mathbf{x}) = \frac{1}{2} \sum_{i} \| \mathbf{r}_i(\mathbf{x}) \|^2 f(x)=21iri(x)2

对其做泰勒二阶展开,令:

  • Δx\Delta \mathbf{x}Δx:当前状态变量的小增量(在李代数中则是 δξ\delta \xiδξ
  • Ji=∂ri∂x\mathbf{J}_i = \frac{\partial \mathbf{r}_i}{\partial \mathbf{x}}Ji=xri:残差对状态的 Jacobian

展开形式如下:

f(x+Δx)≈f(x)+∇f(x)⊤Δx+12Δx⊤HΔx f(\mathbf{x} + \Delta \mathbf{x}) \approx f(\mathbf{x}) + \nabla f(\mathbf{x})^\top \Delta \mathbf{x} + \frac{1}{2} \Delta \mathbf{x}^\top H \Delta \mathbf{x} f(x+Δx)f(x)+f(x)Δx+21ΔxHΔx


2、构建雅可比与 Hessian

根据误差平方和结构,可以推导出:

  • 梯度项

∇f(x)=∑iJi⊤ri \nabla f(\mathbf{x}) = \sum_{i} \mathbf{J}_i^\top \mathbf{r}_i f(x)=iJiri

  • Hessian 矩阵(高效构建方式):

H=∑iJi⊤Ji H = \sum_{i} \mathbf{J}_i^\top \mathbf{J}_i H=iJiJi

这是 Gauss-Newton 近似的 Hessian(忽略二阶导项 ∂2r∂x2\frac{\partial^2 r}{\partial x^2}x22r)。


3、图优化中的应用场景

1. GTSAM / Ceres / g2o 中

它们都将优化建模为图结构:

  • 节点:状态变量(位姿、地图点);

  • 边:观测(误差函数);

  • 每条边贡献一个残差项 ri(x)r_i(\mathbf{x})ri(x),其 Jacobian 用于构建:

    • 梯度向量 b=−∑iJi⊤ri\mathbf{b} = - \sum_i \mathbf{J}_i^\top \mathbf{r}_ib=iJiri
    • Hessian 矩阵 H=∑iJi⊤JiH = \sum_i \mathbf{J}_i^\top \mathbf{J}_iH=iJiJi

构建最终线性系统:

HΔx=−b \boxed{H \Delta \mathbf{x} = -\mathbf{b}} HΔx=b

更新状态:

xk+1=xk+Δx \mathbf{x}_{k+1} = \mathbf{x}_k + \Delta \mathbf{x} xk+1=xk+Δx

在李群中,更新为 Tk+1=exp⁡(Δξ∧)⋅Tk\mathbf{T}_{k+1} = \exp(\Delta \xi^\wedge) \cdot \mathbf{T}_kTk+1=exp(Δξ)Tk

G2O中自定义边类中计算 Hessian 的代码示例

以经典的图优化中 EdgeSE2 为例,创建顶点和边。

#include <g2o/core/sparse_optimizer.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/solvers/dense/linear_solver_dense.h>
#include <g2o/types/slam2d/types_slam2d.h>using namespace g2o;int main() {SparseOptimizer optimizer;optimizer.setVerbose(true);// 设置线性求解器auto linearSolver = g2o::make_unique<LinearSolverDense<BlockSolverX::PoseMatrixType>>();auto solver = g2o::make_unique<BlockSolverX>(std::move(linearSolver));optimizer.setAlgorithm(new OptimizationAlgorithmLevenberg(std::move(solver)));// 添加两个顶点auto v1 = new VertexSE2();v1->setId(0);v1->setEstimate(SE2(0, 0, 0));optimizer.addVertex(v1);auto v2 = new VertexSE2();v2->setId(1);v2->setEstimate(SE2(1, 0, 0));optimizer.addVertex(v2);// 添加边(测量为 v1 到 v2 的位姿)auto edge = new EdgeSE2();edge->setId(0);edge->setVertex(0, v1);edge->setVertex(1, v2);edge->setMeasurement(SE2(1, 0, 0));edge->setInformation(Eigen::Matrix3d::Identity());optimizer.addEdge(edge);// 初始化完毕,计算 Hessianoptimizer.initializeOptimization();optimizer.computeActiveErrors();// 手动计算一次误差、雅可比和 Hessianedge->computeError();          // e = prediction - measurementedge->linearizeOplus();        // J1, J2// 获取雅可比矩阵Eigen::Matrix<double, 3, 3, Eigen::ColMajor> J1 = edge->jacobianOplusXi();Eigen::Matrix<double, 3, 3, Eigen::ColMajor> J2 = edge->jacobianOplusXj();Eigen::Matrix3d Omega = edge->information(); // 信息矩阵// 手动构造 H 和 bEigen::Matrix<double, 3, 3> H11 = J1.transpose() * Omega * J1;Eigen::Matrix<double, 3, 3> H12 = J1.transpose() * Omega * J2;Eigen::Matrix<double, 3, 3> H22 = J2.transpose() * Omega * J2;Eigen::Vector3d e = edge->error();Eigen::Vector3d b1 = J1.transpose() * Omega * e;Eigen::Vector3d b2 = J2.transpose() * Omega * e;std::cout << "H11:\n" << H11 << "\n";std::cout << "H12:\n" << H12 << "\n";std::cout << "H22:\n" << H22 << "\n";std::cout << "b1:\n" << b1 << "\n";std::cout << "b2:\n" << b2 << "\n";return 0;
}

2. 在 ICP / 点云优化中

残差形式:

ri=pitarget−T⋅pisource r_i = \mathbf{p}_i^{\text{target}} - T \cdot \mathbf{p}_i^{\text{source}} ri=pitargetTpisource

残差对位姿变量 δξ\delta \xiδξ 求导,得到 Jacobian,然后构造:

H=∑iJi⊤Ji,b=∑iJi⊤ri H = \sum_i J_i^\top J_i, \quad b = \sum_i J_i^\top r_i H=iJiJi,b=iJiri

代码示例(部分内容)

Eigen::Matrix<double, 6, 6> H = Eigen::Matrix<double, 6, 6>::Zero();
Eigen::Matrix<double, 6, 1> b = Eigen::Matrix<double, 6, 1>::Zero();for (int i = 0; i < N; ++i) {Eigen::Vector3d pi = source[i];Eigen::Vector3d qi = target[i];Eigen::Vector3d transformed = R * pi + t;Eigen::Vector3d r = qi - transformed;Eigen::Matrix<double, 3, 6> Ji;Ji.block<3,3>(0,0) = -Eigen::Matrix3d::Identity();Ji.block<3,3>(0,3) = R * skewSymmetric(pi);H += Ji.transpose() * Ji;b += Ji.transpose() * r;
}

其中 skewSymmetric(p) 为构造叉乘矩阵的函数。



4、Hessian 矩阵的结构特性

  • 稀疏性:每个残差只与少量变量有关(如仅涉及两个相邻位姿),因此 Hessian 是稀疏对称正定矩阵;
  • 块结构:Hessian 可分块处理(每个块是某对变量之间的二阶互导);
  • 可增量维护:可通过 iSAM 增量式维护 Hessian / 信息矩阵。

5、实际系统构建 Hessian 的代码结构(伪代码)

Matrix H = Zero(n, n); // n 变量总数
Vector b = Zero(n);for (Residual& r : residuals) {Vector r_i = r.evaluate(x);Matrix J_i = r.jacobian(x);H += J_i.transpose() * J_i;b += J_i.transpose() * r_i;
}Solve(H * dx = -b);
x = x + dx;

6、GTSAM 中的 Hessian 与信息矩阵

在 GTSAM 中:

  • 每个误差项对应一个 GaussianFactor

  • 系统构建整体的 HessianFactor

    12x⊤Hx−x⊤b \frac{1}{2} \mathbf{x}^\top H \mathbf{x} - \mathbf{x}^\top \mathbf{b} 21xHxxb

用于求解最大后验估计(MAP)问题。
获取信息矩阵代码示例

#include <gtsam/nonlinear/NonlinearFactorGraph.h>
#include <gtsam/nonlinear/Values.h>
#include <gtsam/linear/HessianFactor.h>using namespace gtsam;// 假设你已有 factorGraph 和初始值 initialEstimate
NonlinearFactorGraph graph;
Values initialEstimate;// Step 1: 线性化
GaussianFactorGraph::shared_ptr linearGraph = graph.linearize(initialEstimate);// Step 2: 转为单个 HessianFactor(组合所有项)
boost::shared_ptr<HessianFactor> hessianFactor = boost::dynamic_pointer_cast<HessianFactor>(linearGraph->toHessianFactor());// Step 3: 提取 Hessian 矩阵 H 和向量 b
Matrix H;
Vector b;
Vector d; // 误差项常数项
hessianFactor->info(H, b, d); // info = 信息矩阵(H)std::cout << "Hessian Matrix H:\n" << H << std::endl;
std::cout << "Gradient vector b:\n" << b << std::endl;

7、相关优化方法对 Hessian 的依赖

方法Hessian 使用方式
Gauss-Newton使用近似 Hessian H=J⊤JH = J^\top JH=JJ
Levenberg-Marquardt在 Gauss-Newton Hessian 上加阻尼项 H+λIH + \lambda IH+λI
Dogleg使用 Hessian 构建信赖域
Ceres Solver自动构建稀疏 Jacobian 与 Hessian,支持 Dense/Schur

8、总结表格

内容作用
Hessian 矩阵 HHH描述误差函数的局部二阶结构
如何构建H=∑iJi⊤JiH = \sum_i J_i^\top J_iH=iJiJi,基于残差 Jacobian
在线性系统中作用HΔx=−bH \Delta x = -bHΔx=b,得到优化步长
稀疏性对图优化系统极为重要,可用稀疏求解器(如 CHOLMOD、Eigen::SimplicialLDLT)
GTSAM 应用HessianFactor、GaussianFactorGraph、稀疏线性解系统
点云注册中作用提高配准精度、支持高效的刚体估计

http://www.xdnf.cn/news/15850.html

相关文章:

  • 实战指南|智慧无人机安防系统搭建全流程解析
  • 深入理解Linux文件操作:stdin/stdout/stderr与C语言文件函数全解析
  • PDF 拆分合并PDFSam:开源免费 多文件合并 + 按页码拆分 本地处理
  • 突破性量子芯片问世:电子与光子首次集成,开启量子技术规模化应用新篇章
  • 暑期自学嵌入式——Day05补充(C语言阶段)
  • 二分答案之第 K 小/大
  • Visual Studio编译WPF项目生成的文件介绍
  • 服务器mysql数据的简单备份脚本
  • 二、Dify 版本升级教程(LInux-openeuler)
  • iOS OC 图片压缩
  • vue2 面试题及详细答案150道(101 - 120)
  • 国产替代:ASP4644在电信通信设备中的测试与应用前景
  • Java类:BigDecimal 的用法:乘法
  • IDEA 2020.1版本起下载JDK
  • Logback 配置的利器:深入理解<property>与<variable>
  • vue2 面试题及详细答案150道(21 - 40)
  • 闭包的定义和应用场景
  • Rust实战:高效对接Postman API
  • Spring中的SpEL是什么
  • Springboot3整合Elasticsearch8(elasticsearch-java)
  • [2025CVPR-目标检测方向]FSHNet:一种用于3D物体检测的全稀疏混合网络。
  • Hive数据仓库工具
  • 什么是高光谱相机,它与数码相机有什么区别?
  • 相机光学(五十)——Depth AF
  • RTKLIB读取星历文件,观测数据
  • 解决Flutter运行android提示Deprecated imperative apply of Flutter‘s Gradle plugins
  • 电解电容串联均衡电阻计算
  • 模板初阶和C++内存管理
  • 功能安全之BIST的基本原理
  • 第7天 | openGauss中一个数据库中可以创建多个模式