├── CMakeLists.txt
├── LICENSE.txt
├── README.md
├── cmake
│ └── FindSuiteSparse.cmake
├── config
│ ├── camchain-imucam-euroc-noextrinsics.yaml
│ ├── camchain-imucam-euroc.yaml
│ └── camchain-imucam-fla.yaml
├── include
│ └── msckf_vio
│ ├── cam_state.h
│ ├── feature.hpp
│ ├── image_processor.h
│ ├── image_processor_nodelet.h
│ ├── imu_state.h
│ ├── math_utils.hpp
│ ├── msckf_vio.h
│ ├── msckf_vio_nodelet.h
│ └── utils.h
├── launch
│ ├── image_processor_euroc.launch
│ ├── image_processor_fla.launch
│ ├── msckf_vio_euroc.launch
│ ├── msckf_vio_euroc_noextrinsics.launch
│ ├── msckf_vio_fla.launch
│ └── reset.launch
├── msg
│ ├── CameraMeasurement.msg
│ ├── FeatureMeasurement.msg
│ └── TrackingInfo.msg
├── nodelets.xml
├── package.xml
├── rviz
│ ├── rviz_euroc_config.rviz
│ └── rviz_fla_config.rviz
├── src
│ ├── image_processor.cpp
│ ├── image_processor_nodelet.cpp
│ ├── msckf_vio.cpp
│ ├── msckf_vio_nodelet.cpp
│ └── utils.cpp
└── test
├── feature_initialization_test.cpp
└── math_utils_test.cpp
本篇文章主要介绍src msckf_vio部分,也就是论文中关于状态向量的部分。
看过源码的同学可能已经知道,msckf_vio是目前msckf应用到双目vio中比较成熟的代码。他由两部分组成,分别是image_processor和msckf_vio两部分组成,image_processor 主要负责视觉数据的特征提取,匹配与跟踪,并且并且剔除外点。最后将结果发布到feature这个topic上。
这里的feature topic上的消息实际上对应一个camera state ,所以为了预测Filter State,并且计算卡尔曼增益K以及更新状态,代码中设计了msckf_vio_nodelet.cpp来,msckf_vio这个类就是通过msckf_vio_nodelet.cpp这个nodelet进行初始化。
所以msckf_vio部分是通过MsckfVioNodelet::onInit()这个函数初始化MsckfVio类,然后调用MsckfVio中的initialize()函数。对MsckfVio类进行初始化。
接下来请读者把目光放在msckf_vio.cpp上面。
这个函数被调用时主要发生以下事情:
createRosIO()这个函数很好理解,就是创建相关publisher以及subscriber。其中
每当imu topic有信息时,这个回调函数会被调用。
所有imu msg是会被push_back到imu_msg_buffer后面,而不是立即处理
然后判断gravity是否已经被初始化,若未被初始化,判断是否有足够的(imu_msg_buffer.size()==200)imu msg信息进行初始化.若足够。
调用
当imu_msg_buffer.size()==200时被调用,对gravity以及bias进行初始化。
对于state_server.imu_state.gyro_bias表示状态向量里的bg,这里主要是用imu_msg_buffer里面信息的平均值作为初始化值。同理gravity是用acc的平均值进行初始化。
值得一提的是此时得到的gravity并不是对应世界坐标下的重力加速度。所以
double gravity_norm = gravity_imu.norm();
IMUState::gravity = Vector3d(0.0, 0.0, -gravity_norm);
上述就是将重力加速度转化为世界坐标系下。
Quaterniond q0_i_w = Quaterniond::FromTwoVectors(gravity_imu, -IMUState::gravity);
state_server.imu_state.orientation =rotationToQuaternion(q0_i_w.toRotationMatrix().transpose());//初始化0时刻imustate的orientation部分
这是特征点(实际上是新一帧图片被track的特征点)
每当新进来一帧图像,该回调函数就会被调用。
该函数被调用时主要发生以下事情。
通过当前state_server.imu_state的时间判断当前imu_msg_buffer中哪些信息不被使用。并且用
int used_imu_msg_cntr = 0;这个变量来记录在imu_msg_buffer中已被使用的imu_msg的个数。
将imu_msg的转化成eigen形式。
然后调用MsckfVio::processModel函数
每当这个函数被调用时,状态向量的协方差矩阵(state_server.state_cov)以及imus_state
这个函数主要是对协方差进行增广
执行该函数时,会判断是否有新观测特征点,并将其加入到map_server中。
如函数名,删除跟踪丢失的feature
定义两个vector,invalid_feature_ids用来记录不合法的feature id,processed_feature_ids负责记录继续保留的feature id。
并且同时记录jacobian_row_size 雅可比矩阵的行数,对于每一个processed_feature_ids里的特征点执行。 jacobian_row_size += 4*feature.observations.size() - 3;
然后根据invalid_feature_ids里面的feature id ,从map_server里面删除掉。
循环遍历 processed_feature_ids,获取每一个特征点,然后调用featureJacobian这个函数,得到对于该特征点的H_xj以及r_j.并且根据计算结果更新H_x 和r
调用measurementUpdate函数,如函数名。更新measurement,对应论文中的update部分。
这里主要做的是对camstates进行瘦身
到此基本上结束,update发生在两处,camstates瘦身时,删除不再被跟踪特征点时。