首页 > 其他分享 >VINS-FUSION 优化-先验因子(边缘化)

VINS-FUSION 优化-先验因子(边缘化)

时间:2024-07-22 16:57:05浏览次数:14  
标签:para Pose 边缘化 FUSION 因子 先验 VINS 优化

一、边缘化

VINS中的边缘化策略,将滑出窗外的帧与滑窗内的帧的约束使用边缘化的形式保存为先验误差因子进行后续非线性优化,以保留约束信息。

VINS-Fusion优化约束包括:a.视觉误差因子约束,b.IMU预积分约束,c.边缘化先验因子约束

文章主要讲述边缘化先验因子约束如何产生。

VINS-Fusion中,边缘化如图示:

二、边缘化原理

优化问题通用表达形式:

HX = b

其中,H = J^{T}Jb=J^{T}ee=(J^{T})^{+ }b, ()^{+ }为伪逆,e为残差,J为残差对状态的Jacobian。

将其拆解成以下形式:

\begin{bmatrix} H_{mm} & H_{mr}\\ H_{rm} & H_{rr} \end{bmatrix} \begin{bmatrix} X_{m}\\ X_{r} \end{bmatrix} = \begin{bmatrix} b_{m}\\ b_{r} \end{bmatrix}

拆解成上述形式后,通过变化将状态量X_{m}删掉,并把它的约束保留下来。

在滑窗模式中,这个X_{m}即为要边缘化的量。

舒尔补原理

给定矩阵

M = \begin{bmatrix} A & B\\ C & D \end{bmatrix}

通过下述变换,变成上三角矩阵,如下:

\begin{bmatrix} I & 0\\ -CA^{-1} & I \end{bmatrix} \begin{bmatrix} A & B\\ C & D \end{bmatrix} = \begin{bmatrix} A & B\\ 0 & \Delta A \end{bmatrix}

其中,\Delta A = D - CA^{-1}B称为A关于M的舒尔补。

将舒尔补原理应用到上述拆解形式的优化问题上,则:

\begin{bmatrix} I & 0\\ -H_{rm}H_{mm}^{-1} & I \end{bmatrix} \begin{bmatrix} H_{mm} & H_{mr}\\ H_{rm} & H_{rr} \end{bmatrix} \begin{bmatrix} X_{m}\\ X_{r} \end{bmatrix} = \begin{bmatrix} I & 0\\ -H_{rm}H_{mm}^{-1} & I \end{bmatrix}\begin{bmatrix} b_{m}\\ b_{r} \end{bmatrix}

进一步化简,得到:

\begin{bmatrix} H_{mm} & H_{mr}\\ 0 & H_{rr} - H_{rm}H_{mm}^{-1}H_{mr} \end{bmatrix} \begin{bmatrix} X_{m}\\ X_{r} \end{bmatrix} = \begin{bmatrix} b_{m}\\ b_{r} - H_{rm}H_{mm}^{-1}b_{m}\end{bmatrix}

于是通过矩阵第二行等式,可得:

(H_{rr} - H_{rm}H_{mm}^{-1}H_{mr})X_{r} = b_{r} - H_{rm}H_{mm}^{-1}b_{m}

通过观察上述形式,等式中不包含变量X_{m},即完成了将X_{m}删掉的目的。

(H_{rr} - H_{rm}H_{mm}^{-1}H_{mr})X_{r}记为H_{0}b_{r} - H_{rm}H_{mm}^{-1}b_{m}记为b_{0}

得到边缘化后待求解的增量方程如下:

H_{0}\delta x = b_{0}                        (1)

需根据这个增量方程恢复出边缘化先验误差因子,即e_{p}

随着优化迭代进行,状态量被不断更新。但边缘化时,被边缘化的状态值固定,舒尔补时使用的Jacobian为当时泰勒展开使用该固定值(x线性化点)求得的Jacobian。在VINS中,线性化处的参数值x0保存为parameter_block_data,此即为EFJ。

但(1)式中,b = J^{T}e,其中e随着优化状态更新而变化。

优化状态的更新:

x = Exp(\delta x)\bigotimes x_{0}

此时b的更新可表示为:

b=b_{0}+\frac{\partial b}{\partial x}\mid _{x_{0}}\delta x

=b_{0}+J^{T}\frac{\partial e}{\partial x}\mid _{x_{0}}\delta x

=b_{0}+J^{T}J\delta x

=b_{0}+H\delta x

则,边缘化后先验误差因子:

e_{p} = (J^{T})^{+ }b

=(J^{T})^{+ }(b_{0} + H\delta x)

=(J^{T})^{+ }b_{0} + (J^{T})^{+ }J^{T}J\delta x

=(J^{T})^{+ }b_{0} + J\delta x

至此,边缘化的步骤可总结为:

Marginalize_old

Hx = b优化参数x,由ceres完成优化迭代, Evaluate如下:

d_{x}=x-x_{0}, e=e_{0}+J_{0}d_{x}, J=J_{0}

上一次Marginalize,更新得到线性化点x_{0},及其J_{0}e_{0}

MarginalizationInfo *marginalization_info = new MarginalizationInfo()

创建边缘化管理类MarginalizationInfo,添加AddResidualBlockInfo

上一次先验残差及待边缘化变量索引Marginalization_factor
最老帧,即0-1帧预积分残差IMUFactor
第一次观测为第0帧的所有路标点对应的视觉观测ProjectionFactor

preMarginalize(),更新Je,并将参数x存入parameter_block_data,Evaluate如下:

d_{x}=x-x_{0}, e=e_{0}+J_{0}d_{x}, J=J_{0}

上一步参数x优化

Marginalize(),多线程更新Ab

A=J^{T}J,b=J^{T}e

舒尔补更新线性化点x_{0}及其J_{0}e_{0}

H_{0} = (H_{rr} - H_{rm}H_{mm}^{-1}H_{mr})X_{r}

b_{0}=b_{r} - H_{rm}H_{mm}^{-1}b_{m}

H_{0}分解得到J_{0}e_{0}=(J^{T})^{+ }b_{0}

parameter_block_data,得到x_{0}

由preMarginalize更新得到parameter_block_data、Je

三、先验因子约束优化

1.添加边缘化先验因子约束,完成优化

在runOptimization()优化函数中,使用ceres完成先验因子优化,参照文章“Ceres优化库详细解析”。

添加先验因子约束

构建边缘化因子类MarginalizationFactor。

MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_margnlztn_manager_);
class MarginalizationFactor : public ceres::CostFunction {
   public:
    // 将边缘化的结果转化为边缘化因子
    MarginalizationFactor(MarginalizationManager* _marginalization_info);

    // ceres接口,计算残差和雅可比,提供给ceres做优化
    virtual bool Evaluate(double const* const* _Parameters, double* _Residuals, double** _Jacobians) const;

    MarginalizationManager* marginalization_info_;
};

MarginalizationFactor类继承SizedCostFunction,并在类IMUFactor中实现CostFunction::Evaluate(),

MarginalizationManager,边缘化管理类。主要完成:收集被边缘化帧及其相关联帧、因子(imu预积分、特征重投影因子),执行边缘化操作,获得边缘化因子

ceres完成优化。

2.执行边缘化,产生边缘化先验因子

上述完成边缘化因子的前提是已经完成一次边缘化,如何执行边缘化操作,获得边缘化因子?

(1)边缘化最老帧
a.与最老帧关联的IMU预积分处理
if(USE_IMU) {
	if (pre_integrations_[1]->sum_dt < 10.0) {
		IMUFactor* cost_func = new IMUFactor(pre_integrations_[1]);
		ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(
			cost_func, NULL/*loss func*/,
			vector<double*>{para_Pose_[0], para_Speed_Bias_[0], 
							para_Pose_[1], para_Speed_Bias_[1]},
			vector<int>{0, 1}/*drop set*/);
		curr_margnlztn_manager->addResidualBlockInfo(residual_block_info);
	}
}

添加残差块,值得注意的是参数块:{para_Pose_[0], para_Speed_Bias_[0],                         para_Pose_[1], para_Speed_Bias_[1]}, 和标记边缘化掉的参数块的索引drop_set,如上vector<int>{0, 1}/*drop set*/,丢弃掉的参数为para_Pose_[0], para_Speed_Bias_[0]。

b.与最老帧关联的特征点(被最老帧观测到的特征点)

这一部分与加入视觉误差因子一致,唯一区别就是需标记要边缘化的参数,如ProjectionTwoFrameOneCamFactor 优化的参数为{para_Pose_[frame_i], para_Pose_[frame_j], para_Ex_Pose_[0], para_Features_[feature_index], para_Td_[0]};          要边缘化的参数为para_Pose_[frame_i], para_Features_[feature_index];                                   标记为vector<int>{0, 3}/*drop set*/。

其它类似。

c.计算残差和雅克比(preMarginalize)

计算残差对应的Jacobian,并将各参数块数据放在parameter_block_data中。

计算残差和雅克比:

it->Evaluate()

再将数据放到parameter_block_data中。

d.边缘化(marginlize)

多线程更新Ab,舒尔补更新线性化点x_{0}及其J_{0}e_{0}

e.重置状态量索引
std::unordered_map<long, double*> addr_shift;
for (int i = 0; i <= WINDOW_SIZE; i++) {
	if (i == WINDOW_SIZE - 1) {
		continue;
	}
	else if (i == WINDOW_SIZE) {
		addr_shift[reinterpret_cast<long>(para_Pose_[i])] = para_Pose_[i - 1];
		if(USE_IMU)
			addr_shift[reinterpret_cast<long>(para_Speed_Bias_[i])] = para_Speed_Bias_[i - 1];
	}
	else {
		addr_shift[reinterpret_cast<long>(para_Pose_[i])] = para_Pose_[i];
		if(USE_IMU)
			addr_shift[reinterpret_cast<long>(para_Speed_Bias_[i])] = para_Speed_Bias_[i];
	}
}
for (int i = 0; i < NUM_OF_CAM; i++) {
	addr_shift[reinterpret_cast<long>(para_Ex_Pose_[i])] = para_Ex_Pose_[i];
}
addr_shift[reinterpret_cast<long>(para_Td_[0])] = para_Td_[0];
last_marginalization_info = marginalization_info;
last_marginalization_parameter_blocks = parameter_blocks;
(2)边缘化次新帧

待更新。

至此,边缘化先验信息存储到last_marginalization_info 和last_marginalization_parameter_blocks ,在optimization之后进行slidewindow()操作。

四、滑窗slideWindow

滑窗过程:在滑动窗口中,总是保持窗口总体大小不变,当新进来一帧,通过函数addFeatureCheckParallax判断,如果属于关键帧,则去除窗口中最老帧,置标志MARGIN_OLD;如果不属于关键帧,则去除窗口中次新帧,置标志MARGIN_SECOND_NEW。通过该种策略完成滑窗过程。

根据文章“VINS-FUSION 基于视差Parallax关键帧”,判断新进帧是否为关键帧。

1.去掉最老帧

当边缘化标志flag_marglize_type_为MARGIN_OLD时:

(1)将优化变量左移一

a.将最老帧直接去掉,滑窗内最老帧位姿保留后,滑窗内帧优化变量左移一,预积分左移一,及每个特征点的共视帧索引左移一,深度左移一。

深度左移一说明如下:

//相机坐标系坐标 = 归一化相机平面坐标uv_i * 深度
Eigen::Vector3d pts_i = uv_i * it->estimated_depth;

//世界坐标系下特征点坐标p_w = R_wc * p_c
Eigen::Vector3d w_pts_i = marg_R * pts_i + marg_P;

//次老帧相机坐标系坐标 = (R_wc)^T * ((w_pts_i - new_P))
Eigen::Vector3d pts_j = new_R.transpose() * (w_pts_i - new_P);

//pts_j(2)即相机坐标系下坐标z_{c},及特征点深度
double dep_j = pts_j(2);

if (dep_j > 0)
	it->estimated_depth = dep_j;
else
	it->estimated_depth = INIT_DEPTH;

通过以上方式,将滑窗中最老的特征点深度信息转移给次老帧。

slideWindowOld()

//将特征点滑窗内共视帧索引减一

f_manager.removeBack()

//移除了最老帧,更新滑窗帧index,并将最老帧持有特征的深度信息转移给次老帧

f_manager.removeBackShiftDepth(marg_R, marg_P, new_R, new_P)

2.去掉次新帧

将最新帧替换为次新帧,次新帧直接去掉。将最新帧优化变量赋值给次新帧,并重新预积分。

主要函数

slideWindowNew()

f_manager.removeFront(frame_count)去除特征点与次新帧的共视关系

五、参考

1. 滑窗优化、边缘化、舒尔补、FEJ及fill-in问题_滑动窗口fej算法是啥-CSDN博客

2. VINS-MONO边缘化策略_边缘化先验误差-CSDN博客

3. 白话VINS-Mono之边缘化(五) - 知乎

标签:para,Pose,边缘化,FUSION,因子,先验,VINS,优化
From: https://blog.csdn.net/u010196944/article/details/136204629

相关文章

  • VINS-FUSION 优化-IMU预积分因子(三)
    在VINS-FUSION优化-IMU预积分因子(一)中介绍了IMU预积分及其于优化变量的全部雅克比矩阵的推导,(二)中文章结合VINS-FUSION源码,完成优化-IMU预积分因子的使用。本文介绍预积分中方差的计算。一、引出​方差作为调节各残差项的权重,方差计算如下:Fk、Gk是离散时间下的状态传递方程......
  • Stable Diffusion原理与代码实例讲解
    StableDiffusion原理与代码实例讲解1.背景介绍1.1问题的由来在深入探讨StableDiffusion之前,让我们先了解其应用背景。StableDiffusion主要出现在扩散模型领域,特别是在生成对抗网络(GAN)、变分自编码器(VAE)以及自回归模型中。这些模型通常用于生成高质量的样本,例如图像......
  • Debian12 AMD 显卡 7900XT 安装使用 stable-diffusion-webui 笔记
    简介由于AMD官方没有提供Debian12的驱动和ROCM,只好安装Ubuntu20.04的驱动和ROCM,必要软件git和python3-venv。添加i386仓库sudodpkg--add-architecturei386&&\sudoaptupgrade-y&&\aptupgrade-y下载驱动安装程序到AMD官网下载Ubuntu20.04驱动......
  • 2024最新的AI绘画工具 Stable Diffusion 整合包安装教程,SD安装分享(附整合包)
    大家好,我是灵魂画师向阳自从AI绘画开始进入大众视野之后,AI绘画工具StableDiffusion技术以其创新的人工智能能力而著称,它拥有根据用户输入的文字描述来创造细致且富有表现力的图像的独特本领。SD不仅能够生成图像,还能执行图像修复、扩展以及在文本指导下的图像变换等多样......
  • AI绘画Stable Diffusion ,3种方法精确控制人物姿势,总有一种适合你
    前言在AI绘画软件stablediffusion中,控制人物姿势的方法有很多,最简单的方法是在提示词中加入动作提示词,比如Sit,walk,run(坐、走、跑)等,但如果想要精确控制人物姿势就比较难了,首先想要用语言精确描述一个姿势比较困难,另外stablediffusion生图姿势图就像抽盲盒一样具体有......
  • Stable Diffusion【进阶篇】:真人漫改之图生图实现
    所谓真人漫改,就是把一张真人的图片生成一张新的二次元的图片,在StableDiffusion中,有很多方式实现,其中通过图生图的方式是最常用的方式,大概1-3分钟就可以完成。本文我们系统的讲解一下。下面我们来详细看一下图生图实现真人漫改的具体实现方式。【第一步】:图生图图片上......
  • stable diffusion教程:固定同套衣服,一秒快速换脸
    哈喽今天教大家用sd,做封面上的圣斗士女郎。文章使用的AI工具SD整合包、各种模型插件、提示词、AI人工智能学习资料都已经打包好放在网盘中了,无需自行查找,有需要的小伙伴下方扫码自行获取。昨天一位网友私信我,让我用这张圣斗士铠甲,画几个美女壁纸。特别强调铠甲不能变。......
  • AI绘画Stable Diffusion常用插件合集
    StableDiffusion常用插件,我已经给大家整理好了,下方扫码自取就好。拥有这些SD常用插件,让您的图像生成和编辑过程更加强大、直观、多样化。以下插件集成了一系列增强功能,覆盖从自动补全提示词到高分辨率图像放大,从双语界面到无边图像浏览,为用户提供了无缝的StableDiffusi......
  • AI绘画小白福音!Stable Diffusion 保姆级教程
    大家好,今天,我们就来进行AI绘画的文生图实战。(文末附籽料)unsetunset文生图实战unsetunset模型安装后之后,就可以开始激动人心的AI文生图了,下面我们以文生图为例,一边操作一边讲解提示词的语法和分类,以及出图参数的作用和使用方法。在开始之前,我们再来回顾一下,我们的需求......
  • Stable Diffusion【进阶篇】:真人漫改之IP-Adapter实现
    大家好,今天我分享真人漫改实现方式:借助ControlNet的IP-Adapter控制模型,IP-Adapter控制模型是由腾讯研究院出品的一个新的ControlNet模型,关于该模型可以理解为图片提示词,类似于MD垫图的效果,但是比tagger标签器提取出图片的元素构成效果更好。它不仅参考图片的风格、光影特效......