C++ 代码生成伪代码:保存关键帧和因子
函数 saveKeyFramesAndFactor():
'如果 saveFrame() 返回 false 并且 gnss_buffer 为空,直接返回。'
'添加激光里程计因子(输入是帧间位姿)。'
'添加 GPS 因子。'
'添加闭环因子(基于欧氏距离的检测)。'
'执行优化,如果有回环因子,多更新几次。'
'清空保存的因子图。'
'获取优化结果和当前帧位姿结果。'
'将当前帧位置加入 cloudKeyPoses3D 队列中。'
'将当前帧位姿加入 cloudKeyPoses6D 队列中。'
'获取位姿协方差。'
'更新 ESKF 状态和方差。'
'保存当前帧激光平面点,降采样集合。'
'更新路径可视化。
void saveKeyFramesAndFactor()
{
// 计算当前帧与前一帧位姿变换,如果变化太小,不设为关键帧,反之设为关键帧
if (saveFrame() == false && gnss_buffer.empty())
return;
// 激光里程计因子(from fast-lio), 输入的是frame_relative pose 帧间位姿(body 系下)
addOdomFactor();
// GPS因子 (UTM -> WGS84)
addGPSFactor();
// 闭环因子 (rs-loop-detect) 基于欧氏距离的检测
addLoopFactor();
// 执行优化
isam->update(gtSAMgraph, initialEstimate);
isam->update();
if (aLoopIsClosed == true) // 有回环因子,多update几次
{
isam->update();
isam->update();
isam->update();
isam->update();
isam->update();
}
// update之后要清空一下保存的因子图,注:历史数据不会清掉,ISAM保存起来了
gtSAMgraph.resize(0);
initialEstimate.clear();
PointType thisPose3D;
PointTypePose thisPose6D;
gtsam::Pose3 latestEstimate;
// 优化结果
isamCurrentEstimate = isam->calculateBestEstimate();
// 当前帧位姿结果
latestEstimate = isamCurrentEstimate.at<gtsam::Pose3>(isamCurrentEstimate.size() - 1);
// cloudKeyPoses3D加入当前帧位置
thisPose3D.x = latestEstimate.translation().x();
thisPose3D.y = latestEstimate.translation().y();
thisPose3D.z = latestEstimate.translation().z();
// 索引
thisPose3D.intensity = cloudKeyPoses3D->size(); // 使用intensity作为该帧点云的index
cloudKeyPoses3D->push_back(thisPose3D); // 新关键帧帧放入队列中
// cloudKeyPoses6D加入当前帧位姿
thisPose6D.x = thisPose3D.x;
thisPose6D.y = thisPose3D.y;
thisPose6D.z = thisPose3D.z;
thisPose6D.intensity = thisPose3D.intensity;
thisPose6D.roll = latestEstimate.rotation().roll();
thisPose6D.pitch = latestEstimate.rotation().pitch();
thisPose6D.yaw = latestEstimate.rotation().yaw();
thisPose6D.time = lidar_end_time;
cloudKeyPoses6D->push_back(thisPose6D);
// 位姿协方差
poseCovariance = isam->marginalCovariance(isamCurrentEstimate.size() - 1);
// ESKF状态和方差 更新
state_ikfom state_updated = kf.get_x(); // 获取cur_pose (还没修正)
Eigen::Vector3d pos(latestEstimate.translation().x(), latestEstimate.translation().y(), latestEstimate.translation().z());
Eigen::Quaterniond q = EulerToQuat(latestEstimate.rotation().roll(), latestEstimate.rotation().pitch(), latestEstimate.rotation().yaw());
// 更新状态量
state_updated.pos = pos;
state_updated.rot = q;
state_point = state_updated; // 对state_point进行更新,state_point可视化用到
// if(aLoopIsClosed == true )
kf.change_x(state_updated); // 对cur_pose 进行isam2优化后的修正
// TODO: P的修正有待考察,按照yanliangwang的做法,修改了p,会跑飞
// esekfom::esekf<state_ikfom, 12, input_ikfom>::cov P_updated = kf.get_P(); // 获取当前的状态估计的协方差矩阵
// P_updated.setIdentity();
// P_updated(6, 6) = P_updated(7, 7) = P_updated(8, 8) = 0.00001;
// P_updated(9, 9) = P_updated(10, 10) = P_updated(11, 11) = 0.00001;
// P_updated(15, 15) = P_updated(16, 16) = P_updated(17, 17) = 0.0001;
// P_updated(18, 18) = P_updated(19, 19) = P_updated(20, 20) = 0.001;
// P_updated(21, 21) = P_updated(22, 22) = 0.00001;
// kf.change_P(P_updated);
// 当前帧激光角点、平面点,降采样集合
// pcl::PointCloud<PointType>::Ptr thisCornerKeyFrame(new pcl::PointCloud<PointType>());
pcl::PointCloud<PointType>::Ptr thisSurfKeyFrame(new pcl::PointCloud<PointType>());
// pcl::copyPointCloud(*feats_undistort, *thisCornerKeyFrame);
pcl::copyPointCloud(*feats_undistort, *thisSurfKeyFrame); // 存储关键帧,没有降采样的点云
// 保存特征点降采样集合
// cornerCloudKeyFrames.push_back(thisCornerKeyFrame);
surfCloudKeyFrames.push_back(thisSurfKeyFrame);
updatePath(thisPose6D); // 可视化update后的path
}
原文地址: https://www.cveoy.top/t/topic/oIwC 著作权归作者所有。请勿转载和采集!