vins里config文件里的IMU的噪声和随机游走标定参数只实际影响IMU预积分权重,不参与实际IMU预积分运算。
BA三要素就是残差 雅可比 协方差,协方差实际起到一个权重的作用,vins里面重投影的协方差似乎给的一个定值,IMU预积分的协方差应该是来自于配置文件里写的标定参数,所以实际重投影误差和IMU预积分残差之间的比重应该是靠IMU预积分的协方差来定的。
视觉约束的噪声协方差与标定相机内参时的重投影误差,也就是偏离几个像素有关,代码对应为ProjectionTdFactor::sqrt_info,这里取的1.5个像素(也就是一个固定值),对应到归一化相机平面上的协方差矩阵需除以焦距f,则信息矩阵等于协方差矩阵的逆。( https://www.sohu.com/a/299376914_715754 )
config里的Imu标定参数都被读进一个noise的变量里,noise变量后面又赋值给covariance,变量名的含义就是协方差。 所以可以看到,配置文件里的IMU标定参数,实际只影响IMU预积分的协方差,也就是权重,不参与实际IMU预积分的计算,所以在湖州时助教说那些改为0 vins都可以跑。到港大的MARS数据集里都没提供IMU的标定参数了。现在让别人跑vins,可能就算他们没标定IMU或者标定得不好,可能也对vins影响得不大,关键还是把相机内参和相机和IMU外参标定好。
你自己之前也测试过,手动把config文件里的IMU标定参数对应值改大,也就是噪声和随机游走改大后,跑双目IMU的vins的效果就接近于跑双目的效果,拐弯的时候角度累计误差比较明显。
你自己后来标定D435i的时候,就基本没有重新单独标定IMU了,就一直用的最开始标定的D435i的IMU标定结果进行的双目IMU联合标定,当时觉得算是一种偷懒,只要最后双目IMU联合标定结果的重投影误差小于0.2就认为OK了,除非在没有重新标定imu的情况下,双目IMU联合标定的重投影误差始终达不到0.2,这个时候我才建议说去重新标定一下IMU,但是实际似乎用之前的IMU标定结果,双目IMU联合标定的重投影误差基本也都可以达到0.2,当然我后来真正亲手标定的次数也不是很多了。
VINS-Fusion/vins_estimator/src/estimator/parameters.cpp
if(USE_IMU) { fsSettings["imu_topic"] >> IMU_TOPIC; printf("IMU_TOPIC: %s\n", IMU_TOPIC.c_str()); ACC_N = fsSettings["acc_n"]; ACC_W = fsSettings["acc_w"]; GYR_N = fsSettings["gyr_n"]; GYR_W = fsSettings["gyr_w"]; G.z() = fsSettings["g_norm"]; }
VINS-Fusion/vins_estimator/src/factor/integration_base.h
noise = Eigen::Matrix<double, 18, 18>::Zero(); noise.block<3, 3>(0, 0) = (ACC_N * ACC_N) * Eigen::Matrix3d::Identity(); noise.block<3, 3>(3, 3) = (GYR_N * GYR_N) * Eigen::Matrix3d::Identity(); noise.block<3, 3>(6, 6) = (ACC_N * ACC_N) * Eigen::Matrix3d::Identity(); noise.block<3, 3>(9, 9) = (GYR_N * GYR_N) * Eigen::Matrix3d::Identity(); noise.block<3, 3>(12, 12) = (ACC_W * ACC_W) * Eigen::Matrix3d::Identity(); noise.block<3, 3>(15, 15) = (GYR_W * GYR_W) * Eigen::Matrix3d::Identity();
VINS-Fusion/vins_estimator/src/factor/integration_base.h
covariance = F * covariance * F.transpose() + V * noise * V.transpose();
下面这段代码别人也有相应解释( https://www.sohu.com/a/299376914_715754 ) 代码IMUFactor::Evaluate()中residual还乘以一个信息矩阵sqrt_info,这是因为真正的优化项其实是Mahalanobis 距离:d=r^TP^{-1}r,P是协方差,又因为Ceres只接受最小二乘优化,也就是, 所以把P^{-1}做LLT分解,即LL^{T}=P^{-1},则有:
令r'=L^Tr作为新的优化误差,这样就能用Ceres求解了。Mahalanobis距离其实相当于一个残差加权,协方差大的加权小, 协方差小的加权大, 着重优化那些比较确定的残差. 若写成“sqrt_info.setIdentity()”相当于不加权。
VINS-Fusion/vins_estimator/src/factor/imu_factor.h
Eigen::Map<Eigen::Matrix<double, 15, 1>> residual(residuals); residual = pre_integration->evaluate(Pi, Qi, Vi, Bai, Bgi, Pj, Qj, Vj, Baj, Bgj); Eigen::Matrix<double, 15, 15> sqrt_info = Eigen::LLT<Eigen::Matrix<double, 15, 15>>(pre_integration->covariance.inverse()).matrixL().transpose(); //sqrt_info.setIdentity(); residual = sqrt_info * residual;