因子图优化相关问题

🌞这篇blog主要是记录毕设一些因子图相关的问题 不太好手动理解的点 主要途径就是通过看论文 还有gpt搜集到的一些理解的东西 记录一下

为什么用联合概率密度来描述导航问题

解释1

在导航和其他机器人感知系统中,状态估计问题经常涉及位置X,地图L和观测数据Z的不确定性。利用联合概率密度函数来表示这些变量,可以系统地包含所有相关的不确定性和依赖关系,从而使得可以进行精确的推断和决策。以下是详细解释为什么采用这种表示方法:

在导航问题中:

  • X 表示机器人的位置状态序列,即在不同时间点的位置状态。
  • L 表示环境的地图,包括可能的地标或其他特征。
  • Z 表示机器人的观测数据序列,即机器人通过其传感器相对于环境特征的观测。

概率模型表示

  1. 初始状态的概率 \(P(x_0)\):这是机器人在开始导航前的位置状态的初始概率分布。这通常是基于先验知识或初始观测所给定的。
  2. 状态转移概率 \(\prod_{i=1}^M P(x_i|x_{i-1}, u_i)\) :这一部分表示机器人位置的演化,其中每个状态 \(x_i\) 取决于前一个状态 \(x_{i-1}\) 和执行的控制指令 \(u_i\)状态转移概率捕捉了系统动态和可能的过程噪声
  3. 观测模型 \(\prod_{k=1}^K P(z_k|x_{i_k}, l_{j_k})\):每个观测 \(z_k\) 都依赖于特定时刻 \(i_k\)的位置 $x_{i_k} $ 和相关联的地图特征 \(l_{j_k}\)观测模型描述了如何根据机器人的当前位置和周围环境的地标特征产生观测数据,包括观测噪声。

联合概率密度函数的优势

使用联合概率密度函数 $P(X, L, Z) $ 的优势在于:

  • 全面性:通过整合所有可能的不确定性来源(控制输入的不确定性、位置的不确定性和观测的不确定性),这种方法提供了一个全面的系统描述。
  • 条件依赖性的显式表达:明确表达了各状态和观测之间的条件依赖关系,这对于理解和实现滤波器和估计算法至关重要。
  • 灵活性:这种表示允许使用各种概率推断技术,如卡尔曼滤波、粒子滤波或图优化,来估计位置和地图。
  • 信息整合:可以有效地整合多时刻和多来源的信息,优化状态估计和地图构建。

总之,联合概率密度函数通过对所有变量的依赖关系进行建模,为解决导航中的状态估计问题提供了一个强大的数学框架,使得可以利用概率方法处理不确定性和推导最优解。这种方法是解决SLAM问题的基石,也是现代自动驾驶和机器人导航系统中不可或缺的一部分。

一个具体的例子

再尝试用一个更简单和直观的方式来理解为什么在导航中的状态估计问题可以通过一个联合概率密度函数来表示。我们可以通过具体的例子和逐步解析来帮助理解。

假设我们有一个机器人在一个未知的环境中导航。机器人的任务是理解自己的位置(状态X),探索并绘制周围的地图(L),同时根据自己的传感器收集信息(观测Z)。

  1. 初始状态\(P(x_0)\):
    • 在一开始,我们只知道机器人可能在一个初始位置,比如我们可以假设它以某个概率分布(如高斯分布)位于起点附近。
  2. 状态转移\(P(x_i|x_{i-1}, u_i)\):
    • 每次机器人移动,它的新位置\(x_i\) 将基于前一个位置 \(x_{i-1}\)和其执行的移动指令\(u_i\)(比如向前移动一米)。这个过程不是完全准确的,因此我们使用概率模型(如另一个高斯分布)来表示可能的新位置。
  3. 观测模型 \(P(z_k|x_{i_k}, l_{j_k})\):
    • 同时,机器人会使用传感器(如摄像头或激光雷达)观测周围环境。这些观测\(z_k\)取决于机器人的当前位置 \(x\)和它所观测到的环境特征\(l_{j_k}\)(比如附近的一个门或窗户)。观测也不是完全精确的,同样用概率模型来描述。

解释2

当我们想要同时考虑所有这些因素来估计机器人的最可能的位置、绘制地图和解释观测数据时,我们可以构造一个联合概率模型 \(P(X, L, Z)\)

  • 综合所有信息:这个联合模型把所有关于机器人位置的不确定性、地图的不确定性和观测数据的不确定性都整合在一起。我们通过计算这个联合概率来寻找最有可能解释所有观测数据和已知信息的位置和地图配置
  • 条件依赖关系:这个模型同时还能清晰地表达各种条件依赖关系,例如观测依赖于位置和地图的某些特定特征,位置的更新依赖于先前的位置和移动指令。
  • 灵活的推断和优化:有了这个联合模型,我们可以利用不同的数学工具和算法(如贝叶斯滤波器、粒子滤波、最大似然估计等)来推断未知的状态和地图。

总结来说,这个联合概率密度函数提供了一种全面并且系统的方法来考虑和处理导航问题中的所有不确定性和依赖性。这种方法使得可以更有效地进行状态估计和环境映射,帮助机器人更好地理解和操作在其所处的环境中。

如何根据联合概率密度分布 求解

在解决导航和地图构建的问题中,目标通常是找到一组变量(机器人的位置和地图配置)的配置,这些配置最能解释观测数据和已知信息。这里的“解释”通常是指在给定模型下,找到最大化联合概率 \(P(X, L, Z)\)\(X\)(位置)和\(L\)(地图)的配置。这种方法是基于最大似然估计或最大后验估计的原理。

最大似然估计和最大后验估计

  • 最大似然估计(MLE): 在这种情况下,我们寻找的是最大化观测数据 (Z) 出现概率的位置\(X\) 和地图\(L\) 配置,不考虑位置和地图的先验概率。数学上表达为 \(\arg\max_{X, L} P(Z|X, L)\)

  • 最大后验估计(MAP): 更常见的是,我们寻找能够最大化后验概率\(P(X, L | Z)\)\(X\)\(L\)。由于根据贝叶斯公式,\(P(X, L | Z) \propto P(Z | X, L) P(X, L)\),这不仅考虑了观测数据的似然度,还包括了关于位置和地图的先验知识。

计算过程

  1. 定义概率模型:
    • 状态转移概率 \(P(x_i | x_{i-1}, u_i)\)描述了给定前一状态和控制输入后,当前状态的概率。
    • 观测模型 \(P(z_k | x_{i_k}, l_{j_k})\) 描述了给定当前状态和地图配置时,观测数据出现的概率。
    • 先验\(P(X, L)\)可能基于以前的知识或假设(如位置的均匀分布,或地图的某些特征)。
  2. 优化过程:
    • 在实践中,最大化\(P(X, L | Z)\) 通常涉及到优化算法,如梯度上升、期望最大化(EM)算法或其他非线性优化技术。
    • 在机器人技术中,常见的优化工具包括粒子滤波(用于非线性/非高斯问题)和卡尔曼滤波(用于线性/高斯问题)。
  3. 联合概率和解释:
    • 我们不是寻找最小的联合概率,而是寻找最大化后验概率的 \(X, L\)配置,因为后验概率高意味着给定观测数据和先验知识下,该配置更可能是正确的。

通过最大化后验概率\(P(X, L | Z)\),我们找到一组X 和L,使得在已有的观测Z和可能的先验知识下,这组配置是最有可能的。这就是如何使用联合概率模型来优化并解释机器人的导航和地图构建问题。这种方法使得可以在不确定的环境中做出最好的估计和决策。

关于概率推导

导航定位系统状态量的最大后验估计问题可以转换为在已知系统观测信息的前提下,求解最大化系统的状态信息的概率密度。如式 所示: \[ X^{MAP}=\arg\max_Xp(X_m\mid Z_j)=\arg\max_X\frac{p(Z_j\mid X_m)p(X_m)}{p(Z_j)} \] 由于观测的数据\(Z_j\)是已知的,且与待估计的状态是独立的,于是有: ​\[ p(X_m\mid Z_j)\propto p(Z_j\mid X_m)p(X_m)\\X^{MAP}=\arg\max_Xp(Z_j\mid X_m)p(X_m) \]

在给定系统状态的情况下,每个观测数据是独立的。 为什么观测模型还依赖于系统状态?

解释1

在给定系统状态的情况下,每个观测数据是独立的,这意味着每个观测数据\(z_k\)的生成不受其他观测数据的影响。但是,观测数据和系统状态之间仍然可能存在依赖关系,这种依赖关系通常由观测模型\(h_k(x_{i_k})\)来描述。

观测模型\(h_k(x_{i_k})\)表示系统状态\(x_{i_k}\)到观测数据\(z_k\)之间的映射关系。即使在给定系统状态的情况下,不同的系统状态可能会导致不同的观测数据。这种依赖关系可以是物理上的,也可以是统计上的。例如,在一个移动机器人的定位问题中,机器人的位置状态会影响传感器测量值的期望值,即观测模型\(h_k(x_{i_k})\)。即使在给定机器人位置的情况下,由于传感器的测量误差,不同的位置状态也会导致不同的观测数据。

因此,虽然在给定系统状态的情况下,每个观测数据是独立的,但观测模型\(h_k(x_{i_k})\)仍然依赖于系统状态,因为观测数据的生成过程与系统状态之间可能存在依赖关系。

解释2

在给定观测数据\(z\)的情况下,观测模型的确不应该直接依赖于系统状态\(x\),因为观测数据\(z\)已经被视为已知值,与系统状态无关。

在导航定位系统中,观测模型\(h_k(x_{i_k})\)通常描述了系统状态\(x_{i_k}\)到观测数据\(z_k\)之间的映射关系。这个映射关系可以是物理上的,例如,通过测量信号强度来估计距离,或者是统计上的,例如,通过回归模型来预测观测数据的期望值。

然而,当我们使用高斯分布来表示观测数据\(z_k\)在给定状态\(x_{i_k}\)下的条件概率时,我们需要考虑观测模型和观测噪声。这里的高斯分布是一个常用的假设,用于表示观测数据的不确定性,其中噪声项\(\nu_k\)通常被假设为零均值的高斯分布。

因此,虽然在给定观测数据\(z\)的情况下,观测模型不应该直接依赖于系统状态\(x\),但在贝叶斯推断中,我们可能仍然需要考虑观测模型\(h_k(x_{i_k})\)的形式,以便通过高斯分布来表示观测数据的条件概率分布。然而,需要注意的是,高斯分布中的参数应该是与系统状态无关的,因为在给定观测数据的情况下,观测模型不应该依赖于系统状态。

🌰具体的例子

当处理导航定位系统时,一个常见的观测是通过GPS接收器收集到的位置数据。在这种情况下,我们可以将观测模型视为将系统状态(例如,实际位置)映射到观测数据(例如,GPS接收器报告的位置)的函数。

假设我们想要估计一个移动机器人的位置。机器人当前的真实位置是系统的状态,我们用\(x_i\)表示。而机器人所收集到的GPS数据就是观测数据,用\(z_i\)表示。GPS数据可能会受到多种因素的影响,例如大气干扰、多径效应等,因此我们会有一个观测噪声的模型。

假设我们的观测模型是一个简单的线性模型,即:

\[z_i = x_i + \nu_i\]

其中,\(\nu_i\)是观测噪声,表示GPS测量的误差。

在这个例子中,观测模型\(h(x_i)\)是直接将系统状态\(x_i\)映射到观测数据\(z_i\)上,这是一个物理上的映射关系。但是,为了考虑观测噪声的影响,我们可能会假设\(\nu_i\)是一个零均值的高斯随机变量。

因此,我们可以使用高斯分布来描述观测数据\(z_i\)在给定状态\(x_i\)下的条件概率分布,即:

\[p(z_i \mid x_i) \propto \exp \left( -\frac{1}{2\sigma^2} \|z_i - x_i\|^2 \right)\]

其中,\(\sigma^2\)是观测噪声的方差,\(\|.\|\)表示向量的范数。

需要注意的是,在这个例子中,虽然我们使用了一个与系统状态\(x_i\)相关的观测模型\(h(x_i)\),但是在贝叶斯推断中,我们最终要估计的是系统状态\(x_i\)的后验分布\(p(x_i \mid z_i)\),而不是观测模型\(h(x_i)\)本身。因此,我们仍然可以利用贝叶斯定理来计算后验分布,如前面提到的那样。

关于残差

残差不仅仅反映了异常值的存在,它还反映了模型预测值与实际观测值之间的差异,包括了模型未能完全解释的部分以及数据中的随机噪声。

在统计学和机器学习中,残差通常被定义为观测值与模型的预测值之间的差异。如果我们的模型能够很好地拟合数据,那么残差应该是很小的。然而,当数据中存在异常值或者模型不够准确时,残差可能会变得较大,因为观测值与模型的预测值之间的差异会增大。

因此,残差不仅反映了异常值的存在,还反映了其他因素导致的预测误差。但是,由于异常值往往会导致较大的残差,因此在一定程度上残差可以用来间接地检测异常值的存在。

当我们使用鲁棒核函数时,对于较大的残差会施加较小的权重,使得异常值的影响降低,从而更有可能得到更好的优化结果。因此,虽然残差不仅仅反映了异常值的存在,但异常值对于残差的贡献往往是较大的,因此对异常值施加较小的权重可以减小它们对优化过程的影响。

关于鲁棒核函数

对于常规的最小二乘法,异常值的存在会对优化结果产生较大的影响,因为它们对残差的贡献很大,导致最小二乘法过度拟合这些异常值。这是因为最小二乘法对所有的残差都施加相同的惩罚,而对于异常值来说,它们的残差通常会比较大。

相比之下,鲁棒核函数(如Huber损失函数)会在残差较小的时候施加较小的惩罚,而在残差较大的时候施加较大的惩罚。这使得鲁棒核函数能够更好地适应数据中的异常值,并且对异常值的影响较小。因此,当使用鲁棒核函数进行优化时,异常值不会对优化过程产生过大的影响,从而使得优化结果更加稳健。

总的来说,使用鲁棒核函数能够减少异常值对优化过程的影响,使得优化结果更具有鲁棒性,更能反映数据的真实情况。

为什么残差可以体现异常值

残差对于异常值的影响在于它们对误差的贡献程度。在最小二乘法中,所有残差都会以相同的权重参与到优化过程中,这意味着即使存在异常值,它们也会对最终拟合结果产生显著影响,因为异常值通常会导致较大的残差。

然而,当使用鲁棒核函数(如Huber损失函数)时,对于较小的残差,它们只会受到较小的惩罚,而对于较大的残差,它们会受到更大的惩罚。这样的设计使得鲁棒核函数能够更好地适应异常值的存在,因为异常值通常会导致较大的残差。因此,使用鲁棒核函数时,异常值的影响会被减弱,从而使得优化过程更加稳健,并且更能够反映数据的真实情况。

总的来说,鲁棒核函数通过调整对残差的惩罚来减少异常值对优化过程的影响,从而使得优化结果更具有鲁棒性。

残差是指观测值与拟合值之间的差异,它们在统计学和优化问题中经常被使用。在回归或拟合问题中,残差可以看作是模型未能解释的部分,包括了模型无法捕捉到的数据的波动性或噪声。当数据中存在异常值时,这些异常值往往会导致较大的残差,因为它们与模型的预期值相差较大。

因此,残差的大小和分布可以在一定程度上反映数据中的异常值。当数据中存在异常值时,通常会观察到较大的残差值,因为异常值与其他数据点的差异较大。这使得残差成为了一种检测异常值的方式,因为异常值通常会导致残差的偏离。

在统计建模和优化问题中,我们通常会对残差进行分析和处理,以便更好地理解数据的特征并提高模型的拟合效果。例如,在回归分析中,我们可以检查残差的分布是否满足模型假设,并根据需要调整模型。在优化问题中,我们可以使用残差来评估优化算法的效果,并进一步改进算法,以使残差逐渐减小。

因此,残差在一定程度上可以反映异常值的存在和影响,它们是在统计建模和优化问题中常用的工具,用于识别和处理数据中的异常情况。

什么是残差较大的时候 施加较大的惩罚

当我们说在残差较大的时候施加较大的惩罚时,意味着在优化过程中对于较大的残差值,我们会给予更大的权重或惩罚,以使得这些较大的残差不会对优化结果产生过大的影响。这样的做法可以减少异常值对优化过程的影响,使得优化结果更加鲁棒。

让我们通过一个简单的线性回归的例子来说明这个概念。假设我们有一组数据\((x_i, y_i)\),我们想要用线性模型\(y = mx + b\) 来拟合这些数据。然而,数据中存在一些异常值,这些异常值可能会导致较大的残差。在普通的最小二乘法中,我们会平方残差并求和,以最小化这些残差的平方和,即最小化目标函数:

\[\text{minimize } \sum_i (y_i - (mx_i + b))^2\]

然而,当存在异常值时,它们会导致较大的残差,从而对最小二乘法产生较大的影响。为了降低异常值的影响,我们可以使用Huber损失函数来代替平方损失,它在残差较小的情况下类似于平方损失,而在残差较大的情况下则类似于绝对值损失。这样的损失函数将对较大的残差施加较大的惩罚,从而减小了异常值对优化结果的影响。

Huber损失函数的形式如下:

\[L(r) = \begin{cases} \frac{1}{2} r^2, & \text{if } |r| \leq \delta \\ \delta (|r| - \frac{1}{2}\delta), & \text{if } |r| > \delta \end{cases}\]

其中,\(r\)表示残差,\(\delta\)是一个阈值参数,用于控制在何种范围内将损失函数视为二次型。当残差小于等于\(\delta\)时,损失函数是一个平方函数,而当残差大于\(\delta\)时,损失函数是一个线性函数。这样的设计使得在优化过程中对于较大的残差会施加较大的惩罚,从而减少了异常值对优化结果的影响。

什么是较大的惩罚

让我进一步解释一下“受到较大的惩罚”是什么意思。

在优化问题中,我们通常会定义一个损失函数,用于衡量模型的拟合程度。这个损失函数越小,表示模型对数据的拟合越好。当我们使用不同的损失函数时,对于相同的残差,损失函数可能会对其赋予不同的重要性或权重。

举个简单的例子,假设我们使用平方损失函数:

\[ L(r) = r^2 \] 在这种情况下,不论残差\(r\)的大小如何,损失函数都会将其平方作为损失。因此,对于较大的残差,损失函数会将其平方的值作为较大的损失,而对于较小的残差,损失函数会将其平方的值作为较小的损失。

而当我们使用Huber损失函数时,对于较小的残差,损失函数是一个二次函数,因此对其赋予较小的权重;而对于较大的残差,损失函数是一个线性函数,因此对其赋予较大的权重。换句话说,Huber损失函数对于较大的残差会施加较大的惩罚,而对于较小的残差则施加较小的惩罚。

所以,当我们说“受到较大的惩罚”时,意味着对于那些导致较大残差的数据点,它们在优化过程中会被赋予较大的权重,以使得模型更加关注这些异常值,并尽可能减少它们对模型参数的影响。


🌿比较好的例子​!!

理解这个问题的关键在于理解异常值对于损失函数的影响。在传统的最小二乘法中,异常值的存在可能会导致较大的残差,从而对整个损失函数产生较大的影响。这意味着优化过程会受到异常值的干扰,可能会导致无法收敛到最优解,或者收敛到一个不够准确的解。

而使用鲁棒核函数时,对于较大的残差,它们会受到较小的权重,即较小的惩罚。这意味着异常值的存在不会对损失函数产生过大的影响,因为它们对于整体损失函数的贡献较小。相比之下,对于传统的最小二乘法来说,异常值的残差较大,导致损失函数的值被显著地增加。

通过减少异常值的影响,优化过程更有可能收敛到更好的解。这是因为优化过程可以更专注于拟合那些正常的、代表性的数据点,而不会被少数异常值所主导。这种机制使得优化过程更加稳健,能够更可靠地找到对数据拟合更好的解。

总的来说,通过对异常值施加较小的权重,可以减小它们对损失函数的影响,从而使得优化过程更有可能收敛到更好的解。

具体数值的例子

当我们使用最小二乘法时,我们通常会最小化残差的平方和,即: \[ \sum_{k=1}^n \|h_k(x_{i_k}) - z_k\|^2 \] 在这个公式中,\(h_k(x_{i_k})\) 是模型对观测数据 \(z_k\) 的预测值,\(x_{i_k}\) 是系统状态。这个公式中的每个残差都会被平方,并等权重地加总起来。

假设我们有一组观测数据和模型如下:

  • 观测数据:\(z_1 = 10\), \(z_2 = 12\), \(z_3 = 8\)
  • 模型预测值:\(h(x) = x\)

如果我们使用最小二乘法,那么我们的优化目标就是最小化残差的平方和:

\[ \text{目标:} \min_{x} \left( (x - 10)^2 + (x - 12)^2 + (x - 8)^2 \right) \] 假设我们初始时取 \(x = 0\)。计算残差的平方和为: \[ (0 - 10)^2 + (0 - 12)^2 + (0 - 8)^2 = 100 + 144 + 64 = 308 \] 然后我们使用优化算法来尝试减小这个值。

但如果我们知道在数据中有一些异常值,比如一个 \(z_2 = 100\),这个数远远超出了其他数据的范围。在这种情况下,传统的最小二乘法会对这个异常值产生较大的影响。

现在我们尝试使用Huber损失函数,它对较大的残差施加较小的权重。Huber损失函数的形式如下:

\[ L(r) = \begin{cases} \frac{1}{2} r^2, & \text{if } |r| \leq \delta \\ \delta (|r| - \frac{1}{2}\delta), & \text{if } |r| > \delta \end{cases} \] 假设我们选择 \(\delta = 2\)。那么在计算损失函数时,对于较小的残差,我们会使用残差的平方,而对于较大的残差,我们会使用一个线性函数。所以,对于较大的残差,Huber损失函数的惩罚相对较小。

我们再次尝试用 \(x = 0\) 开始优化。计算Huber损失函数的值:

\[ \text{目标:} \min_{x} \left( \frac{1}{2}(x - 10)^2 + \frac{1}{2}(x - 12)^2 + \frac{1}{2}(x - 8)^2 \right) \] 计算后的损失函数值为: \[ \frac{1}{2}(0 - 10)^2 + \frac{1}{2}(0 - 12)^2 + \frac{1}{2}(0 - 8)^2 = 25 + 36 + 16 = 77 \] 可以看出,相比于传统的最小二乘法,Huber损失函数对异常值的影响要小得多。因此,优化算法更有可能收敛到一个更接近于真实值的解。

因子图为什么处理导航相关问题

  1. 局部测量与全局状态的关系:在GNSS/PDR系统中,我们需要整合来自GNSS的卫星信号数据和PDR系统(如加速度计、陀螺仪等)提供的内部传感器数据。这些数据与用户的全局位置和运动状态有直接关系。因子图允许我们将这些关系表达为局部函数,这些函数仅与某些变量相关联。

  2. 联乘积形式的模型表示:在因子图中,全局函数(如位置和姿态的估计)可以被表示为多个局部函数的乘积。每个局部函数对应于一个特定的测量或状态变量的影响。例如,一个局部函数可能代表来自GNSS的位置测量,另一个局部函数可能代表来自步行检测算法的位移估计。这些局部函数的联乘积可以有效地融合来自不同源的数据,以优化全局状态的估计。

在因子图中,各个因子对于执行如图搜索、优化和推断等操作是非常有效的?

在因子图中,各个因子直接关联到一组变量,并定义这些变量间的局部关系,这对于执行如图搜索、优化和推断等操作是非常有效的?

这段话描述了因子图的核心特性:因子图是一种图形模型,用于表示变量之间的依赖关系。在因子图中,各个因子直接与一组变量相连,并且定义了这些变量之间的具体关系。这种结构对于图搜索、优化和推断等操作非常有效。以下是几个关键点来帮助理解这个概念:

因子图的结构

  1. 变量节点:表示问题中的各种变量(例如,在SLAM中的机器人位置或地图特征点)。
  2. 因子节点:表示变量之间的具体关系或依赖,通常体现为概率函数或约束。这些因子定义了变量如何相互作用,例如,一个因子可能表示在给定机器人的某个位置时,预期的传感器测量与实际观察之间的关系。

执行图搜索、优化和推断的效果

  1. 图搜索:因子图的结构使得可以有效地进行图搜索操作,例如寻找最可能的变量配置。因子图中的连接告诉搜索算法哪些变量是直接相互关联的,从而可以系统地探索这些变量的组合,寻找满足所有因子约束的最优解。

  2. 优化:在因子图中,优化通常涉及调整变量的值以最大化(或最小化)整体系统的某个性能指标(如概率总和或误差平方和)。因为因子直接定义了变量间的关系,优化算法可以直接利用这些局部关系,集中处理影响最大的部分,从而高效地改进解决方案。

  3. 推断:在概率模型中,推断通常意味着基于给定的数据和模型结构推测某些变量的状态。因子图提供了一种清晰的方式来利用局部信息(因子定义的局部概率关系)对全局状态(整个变量集的状态)进行推断。例如,给定某些变量的测量值,可以通过因子图推断其他未知变量的最可能值。

效率的原因

因子图将复杂的全局问题分解为多个简单的局部问题,每个局部问题都集中在一小组变量上。这种分解使得可以并行处理这些局部问题,或者专注于最关键的部分,从而大大提高了计算的效率。此外,因为因子定义了变量之间的确切关系,算法可以避免处理无关变量间的不必要计算,进一步优化性能。

因此,因子图是处理具有复杂依赖关系的优化和推断问题的一个非常强大和灵活的工具。

因子图通过将测量值作为已知的参数而不是变量来简化问题表示?

因子图通过将测量值作为已知的参数而不是变量来简化问题表示,使得模型更直接地关联到优化问题本身,这对于高效解决SLAM等复杂问题至关重要。 这段话怎么理解?通过将测量值作为已知的参数而不是变量来简化问题表示?

这段话指出因子图在处理如SLAM这样的问题时的一个关键特性:将测量数据视为已知参数,而不是作为需要求解的变量。这种处理方式在建模和求解复杂系统时有几个重要的好处:

简化问题表示

  1. 明确角色分配:在SLAM等问题中,我们的主要目标是推断或优化未知的状态变量(如机器人的位置、地图的特征点等),而测量数据(如来自传感器的读数)是用来帮助确定这些未知变量的。将测量值视为已知参数,意味着这些数据在模型中的角色是辅助性的,它们用于构建关于未知变量的条件概率表达,而不是自身需要被解决的问题

  2. 减少求解复杂度:如果将测量值也视为变量,那么问题的复杂度会显著增加,因为这样不仅需要推断未知的状态变量,还要同时解决这些测量值的准确性和可靠性问题。将测量值作为参数,可以直接使用这些数据来形成对未知变量的概率描述,从而简化了模型和计算。

直接关联到优化问题本身

  1. 更加聚焦核心任务:在SLAM等应用中,核心任务是基于测量数据推断或更新未知的状态变量。将测量数据视为参数,可以使模型更加集中于如何利用这些数据来改善对未知变量的估计,而非分散注意力于处理测量数据本身的不确定性。

  2. 提高算法效率:当模型聚焦于核心变量时,优化算法可以更有效地调整和优化这些变量的值以达到最佳估计。这通常会导致更快的计算速度和更好的优化性能,因为算法可以直接利用固定的、已知的测量数据来逐步改进状态估计。

总之,将测量值作为已知参数处理,有助于因子图更加高效和直接地应对复杂的优化问题,如SLAM,这样做能够减轻计算负担,同时提高问题求解的准确性和效率。这种方法使得模型设计和算法实现都更加直接和实用,特别是在实时或资源受限的应用场景中。

因子图优化如何更新节点状态

让我们逐一探讨这两个问题:

1. 根据导数信息计算状态更新量的例子

考虑一个简单的SLAM问题,其中机器人需要确定它的位置x和地图上一个地标的位置 l。假设有一个观测z与机器人的位置和地标之间的距离相关。

步骤

  • 误差函数:设\(h(x, l)\)是从机器人位置 \(x\) 到地标 \(l\) 的预测测量,误差函数$ e$可表示为 \(e = z - h(x, l)\)

  • 雅可比矩阵:计算误差\(e\)关于状态 \(x\) 和地标位置 \(l\) 的雅可比矩阵\(J_x\)\(J_l\)

  • 更新公式:使用高斯牛顿法,更新公式可以写作:

\[ \begin{pmatrix} \Delta x \\ \Delta l \end{pmatrix} = -(J^T J + \lambda I)^{-1} J^T e \]

其中 ( J ) 是组合了\(J_x\) 和$ J_l$ 的雅可比矩阵,$ $是为了提高数值稳定性而添加的阻尼因子(Levenberg-Marquardt算法中使用),I是单位矩阵。

  • 状态更新:计算得到的$ x $ 和$l $用来更新当前状态和地标位置。

2. 增量式图优化方法的实际操作

在实时系统如自动驾驶车辆中,增量图优化主要关注最近的观测和状态,以减少每次更新所需的计算资源。

步骤

  • 局部图更新:每当接收到新的观测数据时,只更新与这些新数据直接相关的节点和边,这些通常是最近的机器人状态和相关地标。
  • 窗口优化:一种常见的策略是固定滑动窗口方法,即仅在固定大小的最近状态窗口内进行优化。较旧的状态和地标,一旦它们超出窗口,可以被边缘化(从优化问题中移除但考虑其对现有状态的统计影响)或锁定。
  • 增量求解器:使用专门设计的增量求解器,如 iSAM 或 g2o,这些工具能够有效地更新信息矩阵和求解增量更新问题。
  • 实时反馈:通过快速更新仅涉及局部改动的解决方案,系统能够快速地对新数据做出响应。

这种增量更新方法能够显著降低因每个新观测而进行全局优化的计算成本,使系统更适合实时应用场景,如自动驾驶或动态环境中的机器人导航。

因子图的迭代优化算法

图优化的迭代优化通常涉及到通过逐步优化来调整和改进图中的节点估计(即状态变量),以最小化整个图中所有误差函数(因子)的总和。这个过程通常使用类似于高斯-牛顿或者LM算法的优化方法。

图优化迭代过程

  1. 初始化
    • 节点的初始估计通常基于传感器的原始数据或某些先验知识。
  2. 构建误差函数
    • 对于图中的每一个因子,构建一个误差函数,该函数衡量当前节点状态估计与观测数据之间的差异。
  3. 线性化误差函数
    • 在当前估计点附近对误差函数进行线性化,通常是通过计算误差函数相对于每个节点状态的雅可比矩阵。
  4. 构建正规方程
    • 将所有线性化的误差函数组合成一个大的系统方程。这通常表现为一个大的稀疏线性系统,可以写成 \[ H\delta = b \] 的形式,其中 ( H ) 是信息矩阵(或海森矩阵),而 ( b ) 是基于误差的向量。
  5. 求解线性系统
    • 使用直接求解器(如Cholesky分解)或迭代求解器(如共轭梯度法)来解决上述线性系统,以找到状态更新 \(\delta\)
  6. 更新状态估计
    • 将解得的\(\delta\)应用到当前的状态估计中,更新所有节点的状态。
  7. 迭代和收敛检查
    • 检查解的改进程度,如果未达到预设的收敛标准(如状态改变量的大小低于某个阈值或达到最大迭代次数),则重复步骤 2-6。
  8. 最终优化结果
    • 当迭代收敛时,当前的状态估计被认为是优化的解,即图中所有节点的最优估计。

使用Levenberg-Marquardt方法的特别说明

Levenberg-Marquardt算法是高斯-牛顿算法的一个变种,通过引入一个调整参数(阻尼因子)来平衡算法的迭代速度与稳定性。这个阻尼因子可以动态调整,以在必要时约束更新步长,从而提高收敛性和算法的鲁棒性。

关于因子图的误差函数

一个具体的例子

在因子图中使用的每个因子都可以被看作是一个误差函数,它描述了给定状态变量下预期观测值与实际观测值之间的差异。雅可比矩阵是这些误差函数对于状态变量的一阶导数,用于在非线性优化过程中进行线性化。

模型和误差函数

以GNSS和PDR为例,我们可以具体定义状态变量和误差函数。

假设状态变量 \(\mathbf{x}_k\) 在第 \(k\) 时刻是一个包括位置和朝向的位姿,可以表示为一个二维平面上的姿态(位置 \((x, y)\) 和朝向 \(\theta\)): \[ \mathbf{x}_k = \begin{bmatrix} x_k \\ y_k \\ \theta_k \end{bmatrix} \] GNSS观测模型

假设GNSS提供了位姿的绝对观测: \[ \mathbf{z}^{\text{GNSS}}_k = \begin{bmatrix} x^{\text{meas}}_k \\ y^{\text{meas}}_k \\ \theta^{\text{meas}}_k \end{bmatrix} \] 误差函数(GNSS因子)可以定义为: \[ \mathbf{e}^{\text{GNSS}}_k = \mathbf{z}^{\text{GNSS}}_k - \mathbf{x}_k \]

PDR观测模型

PDR通常提供相对于上一状态的位移和方向改变,假设步行产生的位移 \(\Delta d\) 和方向变化 \(\Delta \theta\)\[ \mathbf{z}^{\text{PDR}}_k = \begin{bmatrix} \Delta d_k \\ \Delta \theta_k \end{bmatrix} \] 相应的误差函数(PDR因子)可能是: \[ \mathbf{e}^{\text{PDR}}_k = \mathbf{x}_k - \left( \mathbf{x}_{k-1} + \begin{bmatrix} \Delta d_k \cos(\theta_{k-1}) \\ \Delta d_k \sin(\theta_{k-1}) \\ \Delta \theta_k \end{bmatrix} \right) \]

雅可比矩阵计算

雅可比矩阵是误差函数相对于状态变量的偏导数。以PDR误差函数为例,其雅可比矩阵相对于状态 \(\mathbf{x}_k\) 的导数为:

\[ J_{\mathbf{x}_k}^{\text{PDR}} = \frac{\partial \mathbf{e}^{\text{PDR}}_k}{\partial \mathbf{x}_k} = \begin{bmatrix} 1 & 0 & -\Delta d_k \sin(\theta_{k-1}) \\ 0 & 1 & \Delta d_k \cos(\theta_{k-1}) \\ 0 & 0 & 1 \end{bmatrix} \]

这里,偏导数是通过微分 \(\mathbf{x}_k\)\(\mathbf{x}_{k-1}\) 相关的表达式得到的。

GTSAM中的实现

在GTSAM这样的库中,用户只需定义状态变量、误差函数和噪声模型。库内部负责计算雅可比矩阵并进行优化。在每次迭代中,基于当前的估计值,库会自动对误差函数进行线性化,计算雅可比矩阵,并更新状态估计。

在GTSAM中,可以通过自定义因子类来将状态转移函数 ( f ) 纳入因子图中,并通过优化来估计状态变量。以下是一个示例,演示了如何在PDR/GNSS联合定位中使用状态转移函数作为因子的一部分。

假设我们有一个PDR传感器和一个GNSS传感器,我们希望使用PDR的状态转移函数来更新我们的位置估计。这里我们将假设PDR传感器的状态转移函数为 ( f(x_t, u_t) ),其中 ( x_t ) 是时刻 ( t ) 的位置状态, ( u_t ) 是时刻 ( t ) 的PDR测量值。

其中一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <gtsam/base/numericalDerivative.h>
#include <gtsam/geometry/Pose2.h>
#include <gtsam/inference/Symbol.h>
#include <gtsam/nonlinear/ExpressionFactorGraph.h>
#include <gtsam/nonlinear/Expression.h>
#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
#include <iostream>

using namespace gtsam;

// 定义PDR状态转移函数
Pose2 pdrStateTransition(const Pose2& xt, const Pose2& ut) {
// 这里简单假设PDR每一步都是直线运动
return xt.compose(ut);
}

int main() {
// 创建优化器
LevenbergMarquardtOptimizer optimizer;

// 创建符号变量
Symbol x1('x', 1); // 时刻1的位置状态
Symbol u1('u', 1); // 时刻1的PDR测量

// 创建初始估计值
Values initial;
initial.insert(x1, Pose2(0, 0, 0)); // 初始位置状态
initial.insert(u1, Pose2(1, 0, 0)); // 初始PDR测量值

// 创建因子图
ExpressionFactorGraph graph;

// 添加PDR状态转移因子
// 创建表达式表示PDR状态转移函数
Expression<Pose2> f_expr = pdrStateTransition(Expression<Pose2>(x1), Expression<Pose2>(u1));
// 添加因子
graph.addExpressionFactor(f_expr, Pose2(1, 0, 0), noiseModel::Isotropic::Sigma(3, 0.1));

// 执行优化
Values result = optimizer.optimize(graph, initial);

// 输出最终估计结果
std::cout << "Final Result:\n";
result.print();

return 0;
}

在这个示例中,我们通过 ExpressionFactorGraph 来创建因子图,并使用 Expression 表示状态转移函数。然后,我们将这个表达式因子添加到因子图中,并执行优化以估计最终的状态。

这个示例中的 pdrStateTransition 函数是一个简单的状态转移函数示例,实际应用中可能需要根据具体的PDR传感器和系统模型来定义更复杂的状态转移函数。

另一种

在GTSAM中,如果要将状态转移函数 ( f ) 作为实现因子的一部分,你需要定义自定义的因子类。这个类应当能够处理状态的更新并计算误差向量,同时能够自动计算雅可比矩阵。下面是一个例子,展示如何为一个简单的PDR/GNSS系统创建一个自定义的因子类。

以下是GTSAM中一个自定义因子的简单实现,用于处理PDR和GNSS数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <gtsam/nonlinear/NonlinearFactor.h>
#include <gtsam/geometry/Pose2.h>

using namespace gtsam;

// 假设系统的状态由位置 (x, y) 和方向 (theta) 组成,使用 Pose2 表示
class PDRGNSSFactor : public NoiseModelFactor1<Pose2> {
public:
// 测量值
Point2 measuredGNSS; // GNSS测量的位置
double measuredSteps; // PDR测量的步数
double stepLength; // 步长
double measuredHeading; // 步行方向

/**
* 构造函数
* key - 对应变量的键
* measuredGNSS - GNSS测量值
* measuredSteps - PDR测量的步数
* stepLength - 单步步长
* measuredHeading - 测量的步行方向
* noiseModel - 噪声模型
*/
PDRGNSSFactor(Key key, const Point2& gnssMeasurement, double steps, double length, double heading, const SharedNoiseModel& noiseModel)
: NoiseModelFactor1<Pose2>(noiseModel, key), measuredGNSS(gnssMeasurement), measuredSteps(steps), stepLength(length), measuredHeading(heading) {}

// 计算误差向量的函数
Vector evaluateError(const Pose2& pose, boost::optional<Matrix&> H = boost::none) const override {
// 使用当前姿势来预测下一位置
double dx = stepLength * measuredSteps * cos(measuredHeading);
double dy = stepLength * measuredSteps * sin(measuredHeading);
Point2 predictedPosition(pose.x() + dx, pose.y() + dy);

// 如果需要雅可比矩阵
if (H) {
*H = (Matrix(2, 3) << cos(measuredHeading), -sin(measuredHeading), 0,
sin(measuredHeading), cos(measuredHeading), 0).finished();
}

// 返回GNSS测量值和预测位置之间的差异
return (Vector(2) << measuredGNSS.x() - predictedPosition.x(), measuredGNSS.y() - predictedPosition.y()).finished();
}
};

使用此因子

在你的SLAM系统或状态估计框架中,你可以像添加任何其他因子一样添加这个自定义因子:

1
2
NonlinearFactorGraph graph;
graph.add(PDRGNSSFactor(1, Point2(34.052, -118.243), 20, 0.5, 0.785, noiseModel::Diagonal::Sigmas(Vector2(0.5, 0.5))));

这里,我们假设了步长为0.5米,测量的步行方向为0.785弧度(大约45度)。

  • 确保你的噪声模型和其他系统参数与你的具体应用场景匹配。
  • 如果你的状态模型或动态更复杂,你可能需要扩展 Pose2 到更高维度的表示,或者使用 Pose3 如果是三维空间的应用。

这个示例为如何将PDR和GNSS数据融合到单一的因子中提供了一个框架,展示了如何结合两种不同类型的测量更新机器人或移动设备的位置估计。

为什么是因子图不是卡尔曼

(1)处理非线性问题:EKF在处理行人轨迹的不确定性和GNSS信号的非线性特性时存在性能限制。由于行人轨迹的不确定性本质上属于状态非线性过程,EKF通过线性化系统模型来处理非线性问题,但这种方法是局部的,仅在当前估计点附近有效。FGO则是通过构建一个包含所有测量和状态变量的全局图模型,然后应用非线性最优化技术在整个状态空间中寻找最优解来解决整个问题,而不是局限于在每个时间步的局部线性化。

由于非线性问题的复杂性,这种全局优化通常是迭代进行的。每一次迭代都会重新计算整个状态的最优估计,更新的估计会反过来影响下一次迭代的起始条件。这个过程一直重复,直到达到一个收敛条件,比如改进非常小或达到预设的迭代次数。

但是这个非线性的函数是需要自己手动添加的。那么问题来了,非线性函数都是自己手动给设置好的,怎么就直接参入因子图里面去了。就是编程里面?

后续需要编程学习!需要定义误差因子

  1. 处理连续轨迹跟踪:EKF的一阶马尔可夫假设限制了其对历史数据的再评估能力,影响行人轨迹连续跟踪性能。FGO则在新数据到来时重新评估整个状态历史,进行全局优化,提供更准确的状态估计,尤其适用于需要频繁更新和修正轨迹估计的室外行人导航。

在因子图优化中,通常会使用全局优化算法(例如梯度下降、高斯牛顿、或勒文贝格-马夸尔特方法等)来找到最小化所有因子误差的整体解。这种优化会考虑到新的数据点以及它们与已有数据点之间的关系,从而可能会影响到整个状态历史的估计

  1. 异步数据处理:EKF在实时处理不同传感器数据更新频率不一致时面临挑战。FGO允许传感器数据以即插即用的方式整合,通过贝叶斯推理对因子进行综合分析,有效解决异步数据问题。

具体见后文因子图的即插即用

(4)解算效率:EKF在处理大规模或复杂系统时,由于需要操作稠密的协方差矩阵而效率较低。相比之下, FGO通过仅在因子间建立显式连接,自然地体现了系统的稀疏性。这种特性使得FGO适合处理那些局部相互作用的大型系统,从而提高了效率。

综上所述,FGO为解决行人导航中的非线性问题、提高位置估计准确性、异步数据的处理和解算效率上提供了一种新的解决方案。

因子图的增量更新

在因子图优化中,确实可以采用一种增量更新的方法,但这并不意味着每来一个新数据就单独优化一次。因子图优化通常包括两种主要的更新策略:批量优化和增量优化,这取决于应用的需求和系统设计。

批量优化

在批量优化策略中,因子图会收集一定量的数据后,进行一次全局优化。这种方法可以确保考虑到所有可用的信息来优化整个图的配置。批量处理通常在数据集完整或更新频率不高的情况下使用,例如在某些离线处理或数据分析任务中。

增量优化

增量优化策略则更加动态,它允许系统在接收到新数据时即时更新和优化图的一部分。这并不意味着每接收到一个新的数据点就执行一次完整的全局优化,而是指更新影响到的部分节点和边,从而局部调整图的结构。这样的方法适用于需要实时或近实时处理的应用,如移动机器人的导航或在线地图构建。

如何处理新增数据

当新数据到达时,在因子图中,通常采用以下步骤处理:

  1. 新增因子:将新的观测数据转化为因子,并将其连接到图中对应的变量节点上。
  2. 局部优化:对受新因子影响的节点进行局部优化,更新这些节点的状态估计。这种方法称为增量或局部优化。
  3. 全局优化:在某些情况下,为了保证整体性能,可能定期进行一次全局优化,以整合所有信息并纠正潜在的误差积累。

这种灵活性和即插即用的特性使因子图非常适合于动态环境下的应用,如动态传感器网络、实时导航系统等,它们需要不断地接受新信息并快速反应。因子图的这些特性也使得它能够在不重新启动系统的情况下适应新的配置或数据源的变化。

因子图的即插即用

因子图对于处理传感器更新频率不一致问题提供了一种灵活且有效的方式,特别是在复杂的多传感器融合系统中。这主要得益于因子图在处理多源信息与维持全局状态估计方面的灵活性。

在因子图中,每个传感器的输入可以被视为一个因子,它只与图中的某些变量(例如机器人的某个位置)相关联。当新的传感器数据到来时,可以简单地将相应的新因子添加到图中,而无需重新配置整个系统。 这使得因子图非常适合于处理具有不同更新频率的传感器数据。

假设一个机器人装备了一个高频率的IMU(惯性测量单元)和一个低频率的GPS。IMU能够提供高频率但低精度的位置和方向更新,而GPS提供低频率但高精度的位置测量。

  1. 构建因子图:机器人的每个状态(位置和姿态)都是图中的一个节点。IMU和GPS的每次读数分别产生一个新的因子,这些因子与特定的状态节点相连接。
  2. IMU因子:IMU的数据频繁更新,为图中相邻的状态节点间提供动态的约束(如速度和方向)。
  3. GPS因子:GPS数据不频繁,但每当数据到来时,会在因子图中创建一个新的因子,这个因子直接将GPS测量的位置与最近的状态节点相关联。
  4. 因子更新无论何时收到新的传感器数据,都只需将对应的新因子添加到图中并重新优化,而不必修改或重处理整个图。

与卡尔曼滤波的比较

卡尔曼滤波器(包括其扩展和无迹变体)通常需要处理所有传感器数据的固定结构和预设的处理流程。每个传感器都需要在每个时间步被处理,即使某些传感器的数据并未更新。

  • 即插即用:卡尔曼滤波处理新传感器集成通常需要重新设计滤波过程和状态协方差的计算,而因子图可以更容易地通过添加新的因子来整合新传感器,无需重新设计或重新初始化整个系统。
  • 处理非同步数据:卡尔曼滤波器对于非同步传感器数据处理通常需要额外的插值或同步机制,而因子图可以更自然地通过在适当的时间点插入因子来处理这种数据。

卡尔曼滤波器(KF)是一种适用于线性系统(或近似线性)的递推滤波方法,它依赖于数据输入的同步和连续性。在实际应用中,如自动驾驶车辆、机器人导航或多传感器融合系统中,传感器可能无法以同一频率或同步的方式产生数据。这会给基于卡尔曼滤波的系统设计带来挑战。

卡尔曼滤波器和非同步数据处理

当使用卡尔曼滤波器处理来自不同传感器的数据时,若这些传感器的更新频率不一致或数据非同步接收,可能需要进行额外处理以保证数据的时序一致性。这主要是因为卡尔曼滤波器在每个时间步更新状态估计时都假定接收到的数据是当前时刻的准确反映。

举例说明

假设有一个移动机器人使用两种传感器:一个激光雷达(LIDAR)和一个轮速计。激光雷达每100毫秒更新一次位置信息,而轮速计每30毫秒更新一次速度信息。如果直接将这些数据输入到一个卡尔曼滤波器,可能会出现问题,因为两种数据的时间戳不匹配。

为了同步这些传感器数据,一个常见的方法是使用插值:

  • 插值:例如,可以使用线性插值或更复杂的插值方法(如样条插值)来估计激光雷达测量间隙中的位置数据,或者在轮速计测量间隙中估计速度,以便在非测量时刻提供数据估计。
  • 数据缓冲:另一种方法是对快速更新的传感器(轮速计)数据进行缓冲,直到慢速传感器(激光雷达)的下一次数据到来,然后一起处理这些数据。

卡尔曼滤波器(KF)处理的核心在于它按照严格的时序顺序处理观测数据来更新状态估计。这个处理过程基于两个关键假设:系统的动态是已知的,并且观测数据是同步到特定的时间点的。 当观测数据来自频率不同或非同步的多个传感器时,这些假设可能不再成立,直接接受数据而不进行任何处理可能会导致以下问题:

1. 误差累积

卡尔曼滤波器在每个时间步更新其状态估计时,假设最新的观测数据反映了当前的系统状态。如果直接使用非同步的观测数据,滤波器可能无法准确地关联观测数据与其对应的状态,从而导致误差累积。例如,如果一个传感器的数据延迟或提前了,而滤波器误以为这些数据是最新的,那么更新的状态估计可能会基于错误的信息。

2. 时间戳不匹配

在处理来自不同传感器的数据时,每个传感器的输出通常带有时间戳。如果这些时间戳不一致,直接接受数据意味着滤波器可能会在错误的时间点应用观测数据,导致状态更新不准确。 这对于那些高度依赖精确时间信息的应用(如导航和跟踪系统)尤为重要。

3. 数据丢失或重叠

非同步数据可能导致数据在时间轴上出现重叠或缺口。例如,一个传感器可能在另一个传感器的两次读数之间多次更新,或者在长时间内没有更新。这种情况下,直接处理可能导致某些观测数据被忽略或重复计算,影响滤波器的性能

卡尔曼滤波的结构和限制

  1. 模型依赖性: 卡尔曼滤波依赖于一个预先定义好的线性模型(或在扩展卡尔曼滤波和无迹卡尔曼滤波中的非线性模型近似)。这个模型包括状态转移矩阵和观测矩阵,它们必须在滤波器初始化时就确定下来。如果系统的动态特性改变(例如,添加了新的传感器或系统的运动模型改变),可能需要重新定义这些模型矩阵。

  2. 系统维度: 卡尔曼滤波在设计时需要确定状态向量的维度。如果需要加入新的状态变量(比如从新传感器获得的额外数据),通常需要重新设计整个状态向量和相关的处理矩阵,这可能涉及到重新设计状态转移和观测矩阵,以及相应的噪声协方差矩阵。

  3. 实时性和适应性: 卡尔曼滤波器是为了连续、实时的数据流设计的,其强大的实时更新能力在许多应用中非常有用。然而,对于动态变化的系统配置或异步数据源的适应性则不如因子图灵活。

虽然卡尔曼滤波在处理线性系统、实时跟踪等方面有其固有优势,但在系统动态变化较大、数据源频繁变动或需要处理高度非线性系统时,因子图提供了更高的灵活性和扩展性。因子图的结构使其能够更容易地适应系统配置的变化,而不需要进行大规模的系统重设计。这使得因子图在多传感器融合、复杂环境导航等领域尤为适用。

解决方法:插值和数据缓冲

为了解决这些问题,卡尔曼滤波器通常采用以下策略:

  • 插值:通过插值方法(如线性插值、样条插值等)创建虚拟的观测数据,填补时间上的缺口,使得每个时间步都有相应的数据输入。这有助于保持滤波器的连续性和准确性。

  • 数据缓冲:将来自不同传感器的数据存储在缓冲区中,直到收集到所有相关传感器的数据为止。然后,根据这些数据的时间戳一起处理它们。这样可以保证数据在时间上的一致性,减少由于时间错配引起的误差。

这两种方法使得卡尔曼滤波器能够更加稳定和准确地处理来自多源的非同步数据,从而提高系统的整体性能。

因子图的优势

相比之下,因子图提供了一个更灵活的框架来处理非同步数据。因子图是一种图形模型,它以图的形式表示变量之间的条件依赖关系。在因子图中,每个传感器的读数可以作为一个因子被添加到图中,这些因子与它们影响的状态变量相关联。如果传感器数据是非同步的,可以:

  • 动态添加因子:根据每个传感器的时间戳动态地向图中添加新的因子。这意味着每个传感器更新只影响相关的状态变量,不需要人为地同步所有数据。
  • 时间标记:每个因子可以携带时间信息,因此状态更新可以在正确的时间点进行,与数据实际测量的时间相匹配。

因此,因子图模型通过在合适的时间点添加因子来自然地处理非同步的传感器数据,从而避免了在卡尔曼滤波器中必须进行的数据插值或同步。这样不仅简化了处理过程,而且可能提高了系统的整体性能和精度。

因子图的结构允许在不中断现有系统的情况下动态地添加新的节点和边。这在处理如下情况时特别有用:

  • 新增数据源:可以将新传感器数据直接作为新因子加入图中,与相关的状态节点连接,无需改变现有的其他因子或节点。
  • 系统扩展:在因子图中,系统的扩展通常只涉及向图中添加更多的节点和边,而不需要重新配置整个系统的基本结构。

因子图处理和识别不同的传感器

要在代码层面正确地处理和区分不同类型的传感器数据(如IMU和GNSS),你通常需要依赖于数据本身的元数据,这些元数据包括数据类型、时间戳等信息。让我们从这两个方面(实际实现和理论理解)来探讨你的问题:

代码层面:如何识别和处理不同的传感器数据

在现实世界的应用中,每个传感器的输出通常会被标记有其类型,可能还包括精确的时间戳。这允许你在接收数据时进行适当的处理。以下是一个简化的例子,展示如何在接收数据时识别和处理IMU与GNSS数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <variant>

struct IMUData {
double acceleration[3]; // 加速度数据
double gyro[3]; // 陀螺仪数据
double timestamp; // 时间戳
};

struct GNSSData {
double latitude;
double longitude;
double altitude;
double timestamp; // 时间戳
};

typedef std::variant<IMUData, GNSSData> SensorData; // 使用C++17标准的std::variant来处理不同类型的数据

// 处理IMU数据
void processIMUData(const IMUData& data) {
std::cout << "Processing IMU Data at timestamp: " << data.timestamp << std::endl;
// 添加IMU因子到因子图等
}

// 处理GNSS数据
void processGNSSData(const GNSSData& data) {
std::cout << "Processing GNSS Data at timestamp: " << data.timestamp << std::endl;
// 添加GNSS因子到因子图等
}

// 处理传感器数据
void processData(const SensorData& sensorData) {
std::visit([&](auto&& data) {
using T = std::decay_t<decltype(data)>;
if constexpr (std::is_same_v<T, IMUData>) {
processIMUData(data);
} else if constexpr (std::is_same_v<T, GNSSData>) {
processGNSSData(data);
}
}, sensorData);
}

int main() {
IMUData imuData = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, 0.1};
GNSSData gnssData = {34.05, -118.25, 100, 0.2};

processData(imuData);
processData(gnssData);

return 0;
}

理论层面:为什么因子图能实现即插即用

因子图的设计非常适合于处理复杂的多源信息融合问题,主要有以下几个理由:

  1. 模块化:因子图通过因子来定义变量间的关系。每个传感器的数据可以被视为一个因子,这些因子可以独立地被添加到图中。因此,不同类型和不同时间的传感器数据可以作为独立的因子插入,而不会影响图中的其他部分。

  2. 灵活性:由于因子图中各个因子的独立性,新的数据可以在任何时点加入图中,而不需要按照特定的顺序。这对于处理具有不同采样率和可能不同步到达的传感器数据尤其有用。

  3. 扩展性:因子图可以容易地扩展以包含新的变量和因子,使得它非常适合于动态环境和在线更新的场景。

因子图允许在不重新整个系统的情况下,根据新接收到的数据进行局部更新,这使得它非常适合于需要实时或近实时性能的应用,如动态的机器人导航和车辆定位系统。

为什么要引进\(G_i^i=-I_{d\times d}\)

关于这个莫名的公式可以看看isam的公式,这个就是对那个公式的补充点

在因子图和图优化中进行线性化处理时,引入矩阵\(G_i^i = -I_{d \times d}\)是为了便于表达和操作线性化的状态变化量。这里,$ I_{d d} \(表示 \( d \)-维的单位矩阵。矩阵 \( G_i^i \) 的作用是在数学表达式中简化状态变量\)x_i$的运算,从而使得该线性系统易于使用线性代数技术求解。

在线性化的SLAM或图优化问题中,我们通常处理的是两类项:

  1. 过程模型项:它们涉及从一个状态\(x_{i-1}\) 到下一个状态$ x_i$的过渡,如机器人的运动模型。
  2. 测量模型项:涉及从状态变量到测量变量的映射,如从机器人的位置到传感器观测的映射。

引入 $G_i^i = -I_{d d} $

在方程 (6) 中,我们考虑了状态变量 \(x_i\)\(x_{i-1}\)之间的关系。线性化后的模型需要处理这些状态变量的增量\(\delta x_i\)\(\delta x_{i-1}\)。线性化过程后的表达式为:

\[ f_i(x_{i-1}, u_i) - x_i \approx \{ f_i(x_{i-1}^0, u_i) + F_i^{i-1} \delta x_{i-1} \} - \{ x_i^0 + \delta x_i \} \] 要将这个方程转换成标准的线性形式,我们需要确保$ x_i $ 和\(\delta x_{i-1}\)在同一方程中有适当的正负号。在这里,引入\(G_i^i = -I_{d \times d}\)允许我们将$x_i $ 项简单地表示为加法形式的负增量,即:

\[ F_i^{i-1} \delta x_{i-1} - \delta x_i = F_i^{i-1} \delta x_{i-1} + G_i^i \delta x_i \] 这样,线性方程更容易处理,因为它将状态变化量\(\delta x_i\)直接以线性代数的标准形式表示,允许使用矩阵运算直接进行计算。

线性最小二乘问题

通过引入\(G_i^i = -I_{d \times d}\)整个问题可表示为一个标准的线性最小二乘问题:

\[ \delta^* = \underset{\delta}{\operatorname*{argmin}} \left\{ \sum_{i=1}^M \| F_i^{i-1} \delta x_{i-1} + G_i^i \delta x_i + a_i \|_{\Lambda_i}^2 + \sum_{k=1}^K \| H_k^{i_k} \delta x_{i_k} + J_k^{j_k} \delta l_{j_k} - c_k \|_{\Sigma_k}^2 \right\} \] 这个形式使得应用线性代数和优化方法成为可能,从而可以有效求解大规模SLAM问题。

信息矩阵\(I\)

在机器人定位和地图构建的问题中,通常涉及到估计机器人在环境中的位置轨迹 \(X\)以及环境本身的结构地图 \(L\)。在这种情况下,信息矩阵 \(\mathcal{I}\),也被称为费舍尔信息矩阵,是用来表示这些未知量的不确定性和相互依赖关系的关键工具。

信息矩阵 \(\mathcal{I}\) 是由雅可比矩阵 \(A\)(或系统的设计矩阵)通过 \(A^T A\) 计算得到的。这个矩阵可以从以下几个方面描述机器人轨迹和地图内部的信息.

  1. 量化不确定性:
    • 对角线元素:信息矩阵的对角线元素量化了每个参数(位置或地图特征)的信息量或确信度。对角线元素的值越大,表示对应参数的不确定性越小,我们对该参数的估计越精确。
    • 非对角线元素:非对角线元素描述了参数之间的依赖关系或相关性。例如,如果位置 \(x_i\) 和位置 \(x_j\)(或地图特征)在矩阵中的对应元素非零,这表明这两个位置(或特征)的估计值相互依赖
  2. 编码相关性:
    • 分块 \(\mathcal{I}_{XL}\)\(\mathcal{I}_{XL}^T\) 特别重要,因为它们编码了轨迹 \(X\) 和地图 \(L\) 之间的相关性。这意味着机器人在特定位置的估计如何依赖于地图的特定特征, 反之亦然。这种相关性对于同时定位和地图构建(SLAM)至关重要,因为它帮助系统同时解决导航和地图创建的问题。
  3. 优化和解算:
    • 在实际应用中,基于信息矩阵的结构,可以采用更有效的数值方法来解决估计问题,如使用稀疏矩阵技术处理大规模SLAM问题。信息矩阵的稀疏性表明很多参数之间的依赖性较低,这可以大大减少计算量。

信息矩阵 \(\mathcal{I}\) 不仅提供了对机器人轨迹和地图每一部分的内部信息的详尽描述,而且还通过其结构揭示了不同部分之间的相互作用和依赖性,从而在理论和实践中都是解决SLAM问题的核心部分。

矩阵 \(\mathcal{I}\) 是通过矩阵 \(A\) 的转置乘以 \(A\) 计算得到的,这里 \(A\) 被分为两部分:对应于机器人轨迹 \(X\)\(A_X\) 和对应于地图 \(L\)\(A_L\)

矩阵 \(\mathcal{I}\) 的结构表明它分为四个部分:

  1. \(A_X^T A_X\):这是左上角的块,代表轨迹 \(X\) 内部的信息。
  2. \(A_L^T A_L\):这是右下角的块,代表地图 \(L\) 内部的信息。
  3. \(\mathcal{I}_{XL}\)\(\mathcal{I}_{XL}^T\):这两个块分别位于非对角线的位置,\(\mathcal{I}_{XL} \triangleq A_X^T A_L\) 和其转置表示轨迹 \(X\) 和地图 \(L\) 之间的相关性。

\[ \mathcal{I}_{XL} \triangleq A_X^T A_L \]

表示的是 \(A_X\)\(A_L\) 之间的交叉信息,它编码了机器人状态 \(X\) 和地图 \(L\) 之间的相关性。对角线块 \(A_X^T A_X\)\(A_L^T A_L\) 表明它们是“带对角线”的,这通常意味着这些块主要关注各自的内部结构和相互作用,而不是外部的。

关于信息矩阵和残差

标准化残差考虑到了模型和观测的不确定性,这种不确定性可以通过残差的协方差矩阵来量化,而这个协方差矩阵的估计依赖于参数的协方差矩阵,即信息矩阵的逆。因此,信息矩阵 I 通过其逆的形式,直接影响到标准化残差的计算,特别是在决定各残差分量的权重时。

关于AX-b 中A和b的物理意义

在SLAM问题中,机器人的动态与环境交互通过一系列的状态转移和观测更新来描述。矩阵\(A\) 在这个问题中的作用,是将这些动态和交互的关系转化为数学形式,特别是以线性化的方式来近似非线性系统的行为。

矩阵 \(A\) 的意义:

  1. 物理意义:矩阵 \(A\) 表示系统状态变量之间的关系,以及状态变量与观测之间的线性关系。具体来说:
    • 运动模型部分:矩阵\(F_i^{i-1}\)\(G_i^i\) 表示从状态 \(x_{i-1}\)到状态 \(x_i\)的线性化运动模型。这些块表示了机器人如何从一个位置或方向移动到下一个位置,通常基于机器人的控制指令如转向和前进。描绘了状态之间的转移关系。
    • 观测模型部分:矩阵 \(H_k^{i_k}\))和 \(J_k^{j_k}\) 表示状态 \(x_{i_k}\))和地标 \(l_{j_k}\))如何影响第 \(k\) 次观测。这反映了如何从当前状态和地标位置预测观测值例如,从摄像头或激光雷达。通过 \(H_k^{i_k}\)\(J_k^{j_k}\) 描述的块,这些块表明如何从当前的状态和地标位置预测可能的观测结果 \(z_k\)

向量 \(b\):向量 \(b\) 通常包含观测数据与由模型预测的状态转移或观测的差异。在SLAM中,\(b\) 可能由实际观测值 \(z_k\) 减去根据当前状态估计和地标估计得到的预测观测值构成。

计算意义:在最优化问题中,我们通常求解最小化 \((|A\delta - b|_2^2)\),这是一个最小二乘问题,意味着我们在寻找最佳的状态变量更新 (\(\delta\)),使得线性化模型的预测尽可能接近实际观测和运动指令的结果。

为什么 \(A\)重要:

  • (\(A\)) 矩阵捕捉了机器人动态和环境的整体结构,这是理解和解决SLAM问题的核心。正确构建和更新这个矩阵对于准确地估计机器人的状态和地图至关重要。
  • 矩阵的稀疏性表明大多数状态变量不直接相互影响,这在数值计算上是有利的。稀疏矩阵技术可以显著提高求解SLAM问题的效率。

因此,矩阵A 通过其块状结构和各个元素,捕捉了机器人如何移动(动态)和如何观察周围环境(观测)的数学描述。这不仅包括了机器人状态的转移关系,还包括了状态与环境地标之间的相互作用。通过优化问题最小化$|A- b|_2^2 $,我们实际上是在调整对机器人状态和地图的估计,使得这些线性化的预测尽可能贴近实际观测,从而实现同时定位与地图构建的目的。

在SLAM问题中,矩阵 \(A\) 和向量 \(b\) 的物理意义及其在优化问题中的作用是核心部分,反映了状态估计的数学模型与实际操作间的联系:

最小化正规方程 \(A^T A x = A^T b\)

在SLAM问题的线性化模型中,我们通常希望找到一个状态变量的更新量 \(\delta\),使得模型预测尽可能贴近实际的观测。具体来说,我们尝试最小化以下目标函数:

\[ \| A \delta - b \|_2^2 \]

  • \(|\cdot|_2^2\) 表示二范数的平方,用于度量误差的大小。
  • \(A \delta\) 表示对当前状态估计的改正(或更新)。
  • \(b\) 是观测数据与模型预测之间的差异。

解决这个最小化问题通常涉及到求解正规方程:

\[A^T A \delta = A^T b\]

  • \(A^T A\) 是一个方阵,通常更易于处理,尤其是当 \(A\) 是稀疏或结构化的时,这种方法效率更高。
  • \(A^T b\) 是一个向量,表示在当前误差度量下,最佳更新方向的投影。

通过最小化这个误差,我们在数学上是在寻找一个向量 \(\delta\),使得 \(A \delta\) 尽可能接近 \(b\),即尝试对预测的状态和观测进行校正,以逼近真实的观测值。

滤波器与平滑器

在SLAM(Simultaneous Localization and Mapping,即同时定位与建图)问题中,信息矩阵 (I) 是一个关键的概念,用于表示机器人的状态(如位置和方向)以及环境中地标的不确定性。信息矩阵是协方差矩阵的逆,其中每个元素反映了状态变量之间的条件依赖性。在SLAM中,主要有两种处理信息的方法:滤波和平滑。

滤波

滤波是一种在线处理方式,即它只处理当前和过去的信息,通常用于实时系统中。在滤波过程中,随着新数据的持续加入,为了维持计算的可管理性,旧的数据或状态往往需要被边缘化(移除),这导致信息矩阵趋向于变得密集。

  • 在滤波过程中,为了保持计算的实时性和可管理性,通常只会保留当前状态的信息,而把旧的状态信息“边缘化”(即从当前考虑的状态集中移除)。这种边缘化过程会引入额外的非零元素到信息矩阵中,因为边缘化旧状态意味着需要将这些状态的信息“分摊”到剩余的状态上。结果是信息矩阵变得密集,即使原来很多状态之间是条件独立的。
  • 为了处理这种密集化,研究者通常会采用各种技术(如稀疏化技术)来移除信息矩阵中的某些链接,以减少计算负担。

解释为什么在SLAM中进行滤波操作时,边缘化过去的状态会导致信息矩阵变得密集。

示例情景

假设一个机器人在一个简单的环境中沿直线移动,每移动一段距离记录一次位置,形成状态序列 \(X_1, X_2, X_3, \ldots, X_t\)。每个状态都与其前后状态有直接的连接(例如通过里程计测量),并可能与环境中的某些地标有关联。

在开始,信息矩阵 (I) 是稀疏的,因为只有时间上相邻的状态或与某个地标直接相关的状态之间存在连接。例如,如果(X_1)和(X_2)通过里程计相关联,那么在信息矩阵中,\(I_{1,1},I_{1,2},和I_{2,2}\)是非零的。

边缘化过程

当机器人继续前进并且需要在滤波器中处理新的状态时(比如(X_{t+1})),为了保持计算的可管理性,较早的状态(比如(X_1)) 可能会被边缘化掉。边缘化(X_1)意味着我们需要从当前激活的状态集中移除(X_1)的影响。

  • 原本(X_1)直接影响(X_2),在边缘化(X_1)后,我们必须将(X_1)对(X_2)的影响“转移”给与(X_2)相关的其他状态,比如(X_3)。这意味着原先(X_1)与(X_3)可能没有直接关系,但在边缘化(X_1)后,(X_2)与(X_3)之间的关系需要加强,以反映从(X_1)到(X_3)的间接影响。

当我们在状态估计或者滤波问题中进行边缘化时,我们的目标是将某些状态(例如 \[X_1\])的影响通过与其相关联的其他状态(如 \[X_2\]\[X_3\])重新表达,而不是直接包括这些状态。这个过程在信息矩阵(或费舍尔信息矩阵)中的表示可以通过一个具体的数学过程来阐述。

假设我们的系统的信息矩阵 \[\mathcal{I}\] 分布如下,其中包含三个状态 \[X_1\], \[X_2\], 和 \[X_3\]\[ \mathcal{I} = \begin{bmatrix} \mathcal{I}_{11} & \mathcal{I}_{12} & \mathcal{I}_{13} \\ \mathcal{I}_{21} & \mathcal{I}_{22} & \mathcal{I}_{23} \\ \mathcal{I}_{31} & \mathcal{I}_{32} & \mathcal{I}_{33} \end{bmatrix} \] 在这里,\[\mathcal{I}_{ij}\] 表示状态 \[X_i\] 和状态 \[X_j\] 之间的信息量。

当我们决定边缘化状态 \[X_1\],我们需要消除 \[X_1\] 的影响,并将其影响“转移”到与 \[X_1\] 相关的其他状态,比如 \[X_2\]\[X_3\]。边缘化 \[X_1\] 的信息矩阵可以通过 Schur 补数得到: \[ \mathcal{I}_{\text{marginal}} = \mathcal{I}_{22:33} - \mathcal{I}_{21:31}^T \mathcal{I}_{11}^{-1} \mathcal{I}_{21:31} \] 其中:

  • \[\mathcal{I}_{22:33}\] 表示除去与 \[X_1\] 相关的行和列后剩余的信息矩阵部分。
  • \[\mathcal{I}_{21:31}\] 表示与 \[X_1\] 相关的其它状态的交叉信息块。

假设原信息矩阵的块为: \[ \mathcal{I}_{11} = \begin{bmatrix} 2 \end{bmatrix}, \quad \mathcal{I}_{21:31} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}, \quad \mathcal{I}_{22:33} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \]

进行计算: \[ \mathcal{I}_{\text{marginal}} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} - \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 2 \end{bmatrix}^{-1} \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = \begin{bmatrix} 0 & 0 \\ 0 & 0 \end{bmatrix} \]

这个简化例子说明了如何通过矩阵运算处理边缘化。实际应用中,这个过程将导致 \[\mathcal{I}_{22:33}\] 的非对角线元素变得非零,表明 \[X_2\]\[X_3\] 之间的新建立的依赖关系。这反映了从 \[X_1\]\[X_3\] 的间接影响,即使在原始矩阵中 \[X_2\]\[X_3\] 之间没有直接的依赖关系。随着更多状态的边缘化,信息矩阵将变得更加密集,反映出复杂的依赖关系网络。

结果

这个转移过程在信息矩阵中表现为原先为零的元素变成非零,因为(X_2)和(X_3)现在有了新的依赖关系。随着越来越多状态的边缘化,这种间接依赖会累积,导致信息矩阵逐渐从稀疏变为密集。

几何直观

可以想象,每个状态不仅与其直接的邻居有联系,还因为边缘化而与更多其他状态产生了联系。随着时间的推移,几乎每个状态都以某种方式间接地与其他所有状态连接,从而增加了信息矩阵中的非零元素数量,使矩阵变得密集。

这种密集化不仅增加了计算的复杂度,还可能影响滤波器的性能,因此在实际应用中,开发者会寻找各种方法(例如使用稀疏近似或选择性地保留关键状态)来尽可能减少这种影响。

平滑

平滑则是一种离线处理方式,它考虑全部的数据(包括过去和未来的数据)。在平滑处理中,由于不需要边缘化任何状态(因为所有状态对计算都是可用的),所以关联的信息矩阵维持稀疏性,这是因为不存在需要通过边缘化引入新依赖的需求。

  • 平滑处理,相比于滤波,不会边缘化任何过去的状态。相反,它保留了所有历史和当前的状态信息,因此可以在整个时间线上提供更精确的状态估计。
  • 平滑方法中,由于不进行边缘化操作,所以不会引入额外的非零元素导致信息矩阵密集化。这意味着信息矩阵能够保持其原始的稀疏结构,其中非零元素主要集中在时间线上相邻状态之间的依赖关系。这种稀疏性是因为在大多数SLAM场景中,只有时间上相邻的状态或空间上邻近的地标才具有直接的相互依赖。

因此,在与平滑信息矩阵 (I) 关联的MRF中,信息矩阵保持稀疏,主要是因为平滑处理不涉及边缘化过去的状态。这样,每个状态只与其直接相关的少数几个其他状态或地标相关联,而不是与整个历史状态集相关联,从而避免了矩阵的密集化。这种方法不仅保持了计算效率,而且通常能提供比滤波更为精确的状态估计。

用一个具体的数学例子来解释SLAM问题中平滑方法的信息矩阵是如何维持其稀疏性的。在这个例子中,我们考虑一个小规模的机器人轨迹,其中机器人在四个时间点上测量其位置。我们将看到在不进行边缘化的情况下,信息矩阵如何保持其结构。

假设有四个状态\(X_1, X_2, X_3, X_4\),它们代表机器人在四个连续时间点的位置。在SLAM中,通常只有连续的状态之间存在直接的测量依赖关系。

在平滑方法中,信息矩阵I初始化时将反映状态之间的这些直接依赖关系。例如,如果我们假设每个状态只与其前后状态有关系,并且每个这样的依赖对信息矩阵贡献 (1) 的信息值,那么信息矩阵可能看起来像这样:

\[ I = \begin{bmatrix} 1 & -1 & 0 & 0 \\ -1 & 2 & -1 & 0 \\ 0 & -1 & 2 & -1 \\ 0 & 0 & -1 & 1 \end{bmatrix} \] 这里,对角线上的元素 (2) 表示一个状态依赖于其前后状态的信息总和(除了边界条件,即 (X_1) 和 (X_4))。非对角线的 (-1) 表示状态 (X_i) 与 (X_{i+1}) 和 (X_{i-1}) 之间的信息依赖。

在平滑方法中,由于不进行边缘化操作,我们保留所有历史状态的数据。这意味着在任何给定的时刻,我们都可以访问到所有历史和未来的状态信息,而不是只有当前和未来的状态。因此,信息矩阵的非零结构不会改变——它始终保持与初始时刻相同的稀疏模式。

这种方法的优点是,信息矩阵维持了其稀疏性,这大大减少了计算的复杂性和内存需求。例如,当使用稀疏矩阵技术处理大型SLAM问题时,这一特性非常重要。每个状态只与直接相邻的状态有关系,没有因边缘化而引入的额外复杂依赖关系。

这样的稀疏结构是高效处理大规模SLAM问题的关键,因为它减少了必须处理的数据量,并允许使用优化的数值方法来处理信息矩阵。

为什么在平滑中仍然会有变量消除

尽管在平滑处理中,信息矩阵维持其稀疏性质,我们仍可能需要执行某种形式的变量消除,这主要是为了效率和算法实现上的考虑。例如,在求解线性系统时(如 \[Ax = b\]),通常会采用一些数学技术来简化问题,比如通过Cholesky分解等。在这个过程中,创建弦图和消元树是为了优化这些数学操作:

  1. 弦图的创建:在进行Cholesky分解等操作前,弦图能帮助我们识别并利用信息矩阵的稀疏结构,以减少计算过程中的填充(非零元素的添加)。

  2. 消元树的建立:即便信息矩阵是稀疏的,构建消元树可以进一步提高解线性系统的效率。消元树能够指导计算顺序,确保依赖关系得到正确处理,并优化内存访问模式。

因此,尽管平滑信息矩阵在理论上不需要通过边缘化来维护其稀疏性,但在实际计算和算法实现中,变量消除和相关的图形表示(如弦图和消元树)仍然是优化性能和保证算法效率的重要工具。

消元树

消元树是一种用来表示消除过程中变量依赖关系的树状结构,它帮助指导了矩阵分解过程中的计算流程,特别是在反向替代阶段。这里用一个具体的例子来说明这一点:

假设我们有一个系统的矩阵 \[A\],我们想要进行Cholesky分解(假设\[A\]是对称正定的)。我们首先选择一个变量来消除,这通常是基于某种启发式方法,比如最小填充法或最小度法。

考虑以下矩阵:

\[ A = \begin{bmatrix} 4 & 1 & 0 & 0 \\ 1 & 4 & 1 & 0 \\ 0 & 1 & 4 & 1 \\ 0 & 0 & 1 & 3 \\ \end{bmatrix} \]

第一步:消除第一个变量

我们首先消除第一个变量,这会影响与它直接相连的变量(这里是第二个变量)。消除第一个变量后,更新矩阵(做适当的行和列操作)可能会导致非零元素填充原本为零的位置,即产生“填充”。

弦图的形成

在这个过程中,如果我们将每个变量和与它相邻的变量视为图的一个节点和边,消除一个变量相当于在图中移除一个节点及其相关的边,并可能在未被消除的相邻节点间添加新的边(如果它们之前不直接相连)。这个操作最终形成了一个弦图,即每个循环都至少有一个弦(非环的边)的图。

构建消元树

在构建弦图的基础上,消元树被定义为消除过程中的依赖关系图。例如:

  1. 将第一个被消除的变量作为树的根节点。
  2. 每次消除一个变量后,将受到影响的变量作为当前消除变量的子节点添加到树中。

对于上面的矩阵,消元树可能如下:

  • 根节点为第一个被消除的变量。
  • 第二个被影响的变量成为第一个节点的子节点。
  • 依次类推,直到所有变量都被放置在树中。

在反向替代阶段的作用

在进行例如Cholesky分解后,求解线性系统 \[Ax = b\] 需要先进行前代(使用 \[L\] 矩阵)和后代(使用 \[L^T\] 矩阵)。在后代过程中,消元树指导了计算的顺序:从树的叶子(最先消除的变量)开始,逐步向根节点(最后消除的变量)进行,确保在计算当前变量值之前,所有依赖于它的变量值已经被计算。

通过这种方式,消元树不仅帮助优化计算过程,还确保了在计算过程中遵循正确的依赖关系,有效地利用了矩阵的稀疏性质。

QR分解

QR 分解是将矩阵 \[A\] 分解成一个正交矩阵 \[Q\] 和一个上三角矩阵 \[R\] 的方法。如果 \[A\] 是一个 \[m \times n\] 矩阵且 \[m \geq n\],那么分解形式通常写为:

\[A = QR\]

其中,\[Q\] 是一个 \[m \times m\] 正交矩阵(\[Q^T Q = QQ^T = I\]),\[R\] 是一个 \[m \times n\] 的上三角矩阵,其中除了前 \[n\] 行可能有非零元素外,其余部分全为零。在许多实际情况中,我们更关心 \[R\] 的前 \[n \times n\] 部分,因为它是一个完全的上三角矩阵。

为什么 \[R\] 下面有一个0

\[Q^T A = \left[\begin{array}{c} R \\ 0 \end{array}\right]\] 的表达式中,\[R\]\[n \times n\] 的上三角矩阵,而下面的0表示在 \[Q^T\] 作用后,剩下 \[m-n\] 行都被消减到了零。这是因为 \[Q\] 通过正交变换将 \[A\] 的所有向量投影到一个由 \[A\] 的列空间张成的正交子空间。

如何进行QR分解

QR分解可以通过多种方式进行,包括Householder反射、Gram-Schmidt正交化或Givens旋转等。其中,Householder反射是最常用的方法,因为它具有很好的数值稳定性。

Householder反射:

  1. 选取一个列向量,构造一个反射矩阵 \[H\],使得除了第一项外,该列的其余项变为零。
  2. 重复应用上述过程,每次将 \[A\] 的一个列向量(逐步从左到右)变为期望的上三角形式。
  3. 通过连续左乘不同的Householder矩阵(\[H_1, H_2, \ldots, H_n\]),我们最终得到 \[Q^T A = \left[\begin{array}{c} R \\ 0 \end{array}\right]\]

QR分解在最小二乘中的应用

在最小二乘问题中,我们通常要最小化 \[\|A\delta - b\|_2^2\]。通过QR分解,我们可以转化这个问题为:

\[\|Q^T(A\delta - b)\|_2^2 = \|R\delta - Q^Tb\|_2^2\]

由于 \[Q\] 是正交的,所以转换不会改变二范数。因此,问题简化为最小化 \[\|R\delta - d\|_2^2\](其中 \[d\]\[Q^Tb\] 的前 \[n\] 个元素)加上 \[\|e\|_2^2\](其中 \[e\]\[Q^Tb\] 的剩余 \[m-n\] 个元素,代表方程的残差)。

由于 \[R\] 是上三角的,这个问题可以通过反向替换直接求解 \[R\delta = d\],从而找到最小二乘解 \[\delta^*\]

为什么用Cholesky 分解求解正规方程

为什么使用 Cholesky 分解?

  1. 效率和稳定性

    效率:Cholesky分解相比于其他方法(如LU分解或QR分解)通常更为高效。它的计算复杂度大约是 \[\frac{1}{3} n^3\] 对于 \[n \times n\] 矩阵,而LU分解和QR分解的计算复杂度分别大约是 \[\frac{2}{3} n^3\]\[2n^3\]。这使得Cholesky分解成为求解大型正定线性系统的首选方法。

    稳定性:对于对称正定矩阵,Cholesky分解非常稳定。由于对称性和正定性保证了分解的成功执行,它避免了在数值分解过程中的潜在不稳定性。

  2. 数值属性

    ​ 在数值线性代数中,Cholesky分解对于对称正定矩阵来说是一种数值上稳定的方法,特别是当矩阵 \[A^T A\] 的条件数相对较低时。这是因为它直接利用了矩阵的对称性和正定性。

  3. 简化求解过程

    ​ 通过Cholesky分解,矩阵 \[A^T A\] 被分解为一个下三角矩阵 \[L\] 和其转置的上三角矩阵 \[L^T\] 的乘积,即 \[A^T A = L L^T\]。这种分解简化了线性系统的求解,因为只需先解下三角系统 \[L \mathbf{y} = A^T \mathbf{b}\] 获得临时向量 \[\mathbf{y}\],然后解上三角系统 \[L^T \mathbf{x} = \mathbf{y}\] 获取最终解 \[\mathbf{x}\]

    ​ 这种分步求解的过程比直接求解原方程更易于处理,并且可以有效地利用现代计算机体系结构。

总结

由于上述优点,Cholesky分解成为解决正定线性系统(特别是在涉及正规方程时)的理想选择,提供了一种高效、稳定的方法来求解最小二乘问题中的线性系统。这在实际应用中,如图优化、信号处理、统计数据分析等领域,具有广泛的应用。

一些相关链接 不定时更新

可以关注的blog 多源融合

Welson WEN - 知乎 (zhihu.com)

理论学习

滤波优化算法

卡尔曼滤波:究竟滤了谁?

关于卡尔曼滤波 如何通俗并尽可能详细地解释卡尔曼滤波? - 司南牧(李韬)的回答 - 知乎

SLAM找工作1.6 因子图优化(蜘蛛) - 知乎 (zhihu.com)

个人github的blog 估计是大学生 写得还不错

GraphGNSSLib: 基于因子图技术的GNSS定位和GNSS RTK定位算法

SLAM14讲学习笔记(七)后端(BA与图优化,Pose Graph优化的理论与公式详解、因子图优化)

因子图介绍 YOLO

因子图和求和乘积算法 |IEEE期刊和杂志 |IEEE Xplore(IEEE的Xplore)

SLAM算法-因子图建模

学习随笔:机器人感知-因子图在SLAM中的应用

SLAM中后端优化的技术细节

干货:因子图优化的资源合集 算法发展脉络

计算机视觉 教材

概率图模型之贝叶斯网络

csdn:SLAM后端:因子图优化

知乎:三.因子图优化学习---董靖博士在泡泡实验室的公开课学习

知乎:一.因子图优化学习---董靖博士在深蓝学院的公开课学习(1)

贝叶斯派的概率图模型讲解概述

代码编程

GTSAM库

自动驾驶 C++相关

[[代码实践] GTSAM 学习记录(二)]

因子图和GTSAM--实践介绍—个人blog含代码讲解

Factor Graphs and GTSAM

因子图优化 slam找工作

代码能力

自动驾驶 C++相关

因子图优化 slam找工作

https://www.zhihu.com/people/mach999/posts