vins里发布位姿话题是在pubOdometry这个函数里(VINS-Fusion/vins_estimator/src/utility/visualization.cpp),这个函数在void Estimator::processMeasurements()函数(VINS-Fusion/vins_estimator/src/estimator/estimator.cpp)里被调用,pubOdometry运行前会运行一个processImage(feature.second, feature.first)函数,这个函数里有pnp/IMU预积分得到初始位姿,三角化,滑窗优化,怪不得发出位姿延迟大。不像ORBSLAM前端就发出位姿话题了,vins虽然也有前端tracking,但是前端tracking输出的是比如特征点匹配结果,并没有相机帧初始位姿估计,相机帧初始位姿估计放在了后端estimator.cpp里。
Estimator::processMeasurements()函数
https://blog.csdn.net/shikaiaixuexi/article/details/139609769
//这个函数是用来处理测量数据的主要循环。它从 featureBuf 中获取特征数据,同时等待IMU数据(如果启用了IMU),然后对图像和IMU数据进行处理
void Estimator::processMeasurements()
{
//这里开始一个无限循环,一直等待处理测量数据。
while (1)
{
//printf("process measurments\n");
//定义了一个 feature 变量,其中包含时间戳和特征点数据的映射。
pair<double, map<int, vector<pair<int, Eigen::Matrix<double, 7, 1> > > > > feature;
//定义了用于存储IMU数据的向量。
vector<pair<double, Eigen::Vector3d>> accVector, gyrVector;
if(!featureBuf.empty())
{
//如果特征点缓冲区不为空,就从中获取下一个特征数据。
feature = featureBuf.front();
// 计算当前时间(特征数据的时间戳加上时间偏移)
curTime = feature.first + td;
// 等待IMU数据,直到IMU数据在当前时间戳可用
while(1)
{
// 如果不使用IMU或者IMU数据在当前时间戳处可用,则退出循环
if ((!USE_IMU || IMUAvailable(feature.first + td)))
break;
// 否则,等待IMU数据
else
{
printf("wait for imu ... \n");
// 如果没有启用多线程,直接返回
if (! MULTIPLE_THREAD)
return;
// 等待5毫秒
std::chrono::milliseconds dura(5);
std::this_thread::sleep_for(dura);
}
}
// 加锁,获取IMU数据并存储到accVector和gyrVector中
mBuf.lock();
if(USE_IMU)
getIMUInterval(prevTime, curTime, accVector, gyrVector);
// 从特征数据缓冲区中移除已处理的特征数据
featureBuf.pop();
mBuf.unlock();
// 如果使用IMU数据
if(USE_IMU)
{
// 如果尚未初始化第一个姿态,先初始化第一个IMU姿态
if(!initFirstPoseFlag)
initFirstIMUPose(accVector);
// 对每个时间间隔的IMU数据进行处理
for(size_t i = 0; i < accVector.size(); i++)
{
double dt;
// 计算时间间隔
if(i == 0)
dt = accVector[i].first - prevTime;// 第一个数据包的时间戳与上一个处理的时间戳之差
else if (i == accVector.size() - 1)
dt = curTime - accVector[i - 1].first;// 当前时间与最后一个数据包的时间戳之差
else
dt = accVector[i].first - accVector[i - 1].first;// 当前数据包的时间戳与前一个数据包的时间戳之差
// 调用processIMU处理IMU数据
processIMU(accVector[i].first, dt, accVector[i].second, gyrVector[i].second);
}
}
// 加锁,调用processImage函数处理图像数据
mProcess.lock();
processImage(feature.second, feature.first);
prevTime = curTime;
// 打印统计信息
printStatistics(*this, 0);
// 设置ROS消息头部,并发布相关数据
std_msgs::Header header;
header.frame_id = "world";
header.stamp = ros::Time(feature.first);
pubOdometry(*this, header);
pubKeyPoses(*this, header);
pubCameraPose(*this, header);
pubPointCloud(*this, header);
pubKeyframe(*this);
pubTF(*this, header);
mProcess.unlock();
}
// 如果没有启用多线程,退出主循环
if (! MULTIPLE_THREAD)
break;
// 短暂休眠以减少处理器资源的占用
std::chrono::milliseconds dura(2);
std::this_thread::sleep_for(dura);
}
}
processImage函数部分内容
VINS-Fusion/vins_estimator/src/estimator/estimator.cpp
if(!USE_IMU)
f_manager.initFramePoseByPnP(frame_count, Ps, Rs, tic, ric);
f_manager.triangulate(frame_count, Ps, Rs, tic, ric);
optimization();
set<int> removeIndex;
outliersRejection(removeIndex);
f_manager.removeOutlier(removeIndex);
if (! MULTIPLE_THREAD)
{
featureTracker.removeOutliers(removeIndex);
predictPtsInNextFrame();
}
ROS_DEBUG("solver costs: %fms", t_solve.toc());
if (failureDetection())
{
ROS_WARN("failure detection!");
failure_occur = 1;
clearState();
setParameter();
ROS_WARN("system reboot!");
return;
}
slideWindow();
f_manager.removeFailures();