1 设置相机位姿

void keyframe::set_cam_pose(const Mat44_t& cam_pose_cw) {
std::lock_guard<std::mutex> lock(mtx_pose_);
cam_pose_cw_ = cam_pose_cw;
const Mat33_t rot_cw = cam_pose_cw_.block<3, 3>(0, 0);
const Vec3_t trans_cw = cam_pose_cw_.block<3, 1>(0, 3);
const Mat33_t rot_wc = rot_cw.transpose();
cam_center_ = -rot_wc * trans_cw;
cam_pose_wc_ = Mat44_t::Identity();
cam_pose_wc_.block<3, 3>(0, 0) = rot_wc;
cam_pose_wc_.block<3, 1>(0, 3) = cam_center_;
}
2 地图尺度缩放

前两帧完成初始化
2-1 获取缩放scale
获取
const auto inv_median_depth = 1.0 / median_depth;
scale = inv_median_depth * scaling_factor_
深度计算
float keyframe::compute_median_depth(const bool abs) const {
std::vector<landmark*> landmarks;
Mat44_t cam_pose_cw;
{
std::lock_guard<std::mutex> lock1(mtx_observations_);
std::lock_guard<std::mutex> lock2(mtx_pose_);
landmarks = landmarks_;
cam_pose_cw = cam_pose_cw_;
}
std::vector<float> depths;
depths.reserve(num_keypts_);
const Vec3_t rot_cw_z_row = cam_pose_cw.block<1, 3>(2, 0);
const float trans_cw_z = cam_pose_cw(2, 3);
for (const auto lm : landmarks) {
if (!lm) {
continue;
}
const Vec3_t pos_w = lm->get_pos_in_world();
const auto pos_c_z = rot_cw_z_row.dot(pos_w) + trans_cw_z;
depths.push_back(abs ? std::abs(pos_c_z) : pos_c_z);
}
std::sort(depths.begin(), depths.end());
return depths.at((depths.size() - 1) / 2);
}
2-2 设置地图尺度
请注意这里是把 t = s*t
而在3D-3D sRt计算中 s*R*p1质心+t=p2 质心 s尺度是作用在R上的
void initializer::scale_map(data::keyframe* init_keyfrm, data::keyframe* curr_keyfrm, const double scale) {
// scaling keyframes
Mat44_t cam_pose_cw = curr_keyfrm->get_cam_pose();
cam_pose_cw.block<3, 1>(0, 3) *= scale;
curr_keyfrm->set_cam_pose(cam_pose_cw);
// scaling landmarks
const auto landmarks = init_keyfrm->get_landmarks();
for (auto lm : landmarks) {
if (!lm) {
continue;
}
lm->set_pos_in_world(lm->get_pos_in_world() * scale);
}
}
3局部BA结束
local_bundle_adjuster.cc
// 8. 情報を更新
{
std::lock_guard<std::mutex> lock(data::map_database::mtx_database_);
if (!outlier_observations.empty()) {
for (auto& outlier_obs : outlier_observations) {
auto keyfrm = outlier_obs.first;
auto lm = outlier_obs.second;
keyfrm->erase_landmark(lm);
lm->erase_observation(keyfrm);
}
}
for (auto id_local_keyfrm_pair : local_keyfrms) {
auto local_keyfrm = id_local_keyfrm_pair.second;
auto keyfrm_vtx = keyfrm_vtx_container.get_vertex(local_keyfrm);
local_keyfrm->set_cam_pose(keyfrm_vtx->estimate());
}
for (auto id_local_lm_pair : local_lms) {
auto local_lm = id_local_lm_pair.second;
auto lm_vtx = lm_vtx_container.get_vertex(local_lm);
local_lm->set_pos_in_world(lm_vtx->estimate());
local_lm->update_normal_and_depth();
}
}
3全局BA结束
global_bundle_adjuster.cc
const auto keyfrms = map_db_->get_all_keyframes();
const auto lms = map_db_->get_all_landmarks();
for (auto keyfrm : keyfrms) {
if (keyfrm->will_be_erased()) {
continue;
}
auto keyfrm_vtx = keyfrm_vtx_container.get_vertex(keyfrm);
const auto cam_pose_cw = util::converter::to_eigen_mat(keyfrm_vtx->estimate());
if (lead_keyfrm_id_in_global_BA == 0) {
keyfrm->set_cam_pose(cam_pose_cw);
}
else {
keyfrm->cam_pose_cw_after_loop_BA_ = cam_pose_cw;
keyfrm->loop_BA_identifier_ = lead_keyfrm_id_in_global_BA;
}
}
for (unsigned int i = 0; i < lms.size(); ++i) {
if (!is_optimized_lm.at(i)) {
continue;
}
auto lm = lms.at(i);
if (!lm) {
continue;
}
if (lm->will_be_erased()) {
continue;
}
auto lm_vtx = lm_vtx_container.get_vertex(lm);
const Vec3_t pos_w = lm_vtx->estimate();
if (lead_keyfrm_id_in_global_BA == 0) {
lm->set_pos_in_world(pos_w);
lm->update_normal_and_depth();
}
else {
lm->pos_w_after_global_BA_ = pos_w;
lm->loop_BA_identifier_ = lead_keyfrm_id_in_global_BA;
}
4 全局loop SIM3 BA优化结束 更新位姿和地图点
loop_bundle_adjuster.cc
位姿更新
// update the camera pose along the spanning tree from the origin
std::list<data::keyframe*> keyfrms_to_check;
keyfrms_to_check.push_back(map_db_->origin_keyfrm_);
while (!keyfrms_to_check.empty()) {
auto parent = keyfrms_to_check.front();
const Mat44_t cam_pose_wp = parent->get_cam_pose_inv();
const auto children = parent->graph_node_->get_spanning_children();
for (auto child : children) {
if (child->loop_BA_identifier_ != identifier) {
// if `child` is NOT optimized by the loop BA
// propagate the pose correction from the spanning parent
// parent->child
const Mat44_t cam_pose_cp = child->get_cam_pose() * cam_pose_wp;
// world->child AFTER correction = parent->child * world->parent AFTER correction
child->cam_pose_cw_after_loop_BA_ = cam_pose_cp * parent->cam_pose_cw_after_loop_BA_;
// check as `child` has been corrected
child->loop_BA_identifier_ = identifier;
}
// need updating
keyfrms_to_check.push_back(child);
}
// temporally store the camera pose BEFORE correction (for correction of landmark positions)
parent->cam_pose_cw_before_BA_ = parent->get_cam_pose();
// update the camera pose
parent->set_cam_pose(parent->cam_pose_cw_after_loop_BA_);
// finish updating
keyfrms_to_check.pop_front();
}
地图点
// update the positions of the landmarks
const auto landmarks = map_db_->get_all_landmarks();
for (auto lm : landmarks) {
if (lm->will_be_erased()) {
continue;
}
if (lm->loop_BA_identifier_ == identifier) {
// if `lm` is optimized by the loop BA
// update with the optimized position
lm->set_pos_in_world(lm->pos_w_after_global_BA_);
}
else {
// if `lm` is NOT optimized by the loop BA
// correct the position according to the move of the camera pose of the reference keyframe
auto ref_keyfrm = lm->get_ref_keyframe();
assert(ref_keyfrm->loop_BA_identifier_ == identifier);
// convert the position to the camera-reference using the camera pose BEFORE the correction
const Mat33_t rot_cw_before_BA = ref_keyfrm->cam_pose_cw_before_BA_.block<3, 3>(0, 0);
const Vec3_t trans_cw_before_BA = ref_keyfrm->cam_pose_cw_before_BA_.block<3, 1>(0, 3);
const Vec3_t pos_c = rot_cw_before_BA * lm->get_pos_in_world() + trans_cw_before_BA;
// convert the position to the world-reference using the camera pose AFTER the correction
const Mat44_t cam_pose_wc = ref_keyfrm->get_cam_pose_inv();
const Mat33_t rot_wc = cam_pose_wc.block<3, 3>(0, 0);
const Vec3_t trans_wc = cam_pose_wc.block<3, 1>(0, 3);
lm->set_pos_in_world(rot_wc * pos_c + trans_wc);
}
}
所有关键帧保存操作

void trajectory_io::save_keyframe_trajectory(const std::string& path, const std::string& format) const {
std::lock_guard<std::mutex> lock(data::map_database::mtx_database_);
// 1. acquire keyframes and sort them
assert(map_db_);
auto keyfrms = map_db_->get_all_keyframes();
std::sort(keyfrms.begin(), keyfrms.end(), [&](data::keyframe* keyfrm_1, data::keyframe* keyfrm_2) {
return *keyfrm_1 < *keyfrm_2;
});
// 2. save the keyframes
if (keyfrms.empty()) {
spdlog::warn("there are no valid keyframes, cannot dump keyframe trajectory");
return;
}
std::ofstream ofs(path, std::ios::out);
if (!ofs.is_open()) {
spdlog::critical("cannot create a file at {}", path);
throw std::runtime_error("cannot create a file at " + path);
}
spdlog::info("dump keyframe trajectory in \"{}\" format from keyframe {} to keyframe {} ({} keyframes)",
format, (*keyfrms.begin())->id_, (*keyfrms.rbegin())->id_, keyfrms.size());
for (const auto keyfrm : keyfrms) {
const Mat44_t cam_pose_cw = keyfrm->get_cam_pose();
const Mat44_t cam_pose_wc = cam_pose_cw.inverse();
const auto timestamp = keyfrm->timestamp_;
if (format == "KITTI") {
ofs << std::setprecision(9)
<< cam_pose_wc(0, 0) << " " << cam_pose_wc(0, 1) << " " << cam_pose_wc(0, 2) << " " << cam_pose_wc(0, 3) << " "
<< cam_pose_wc(1, 0) << " " << cam_pose_wc(1, 1) << " " << cam_pose_wc(1, 2) << " " << cam_pose_wc(1, 3) << " "
<< cam_pose_wc(2, 0) << " " << cam_pose_wc(2, 1) << " " << cam_pose_wc(2, 2) << " " << cam_pose_wc(2, 3) << std::endl;
}
else if (format == "TUM") {
const Mat33_t& rot_wc = cam_pose_wc.block<3, 3>(0, 0);
const Vec3_t& trans_wc = cam_pose_wc.block<3, 1>(0, 3);
const Quat_t quat_wc = Quat_t(rot_wc);
ofs << std::setprecision(15)
<< timestamp << " "
<< std::setprecision(9)
<< trans_wc(0) << " " << trans_wc(1) << " " << trans_wc(2) << " "
<< quat_wc.x() << " " << quat_wc.y() << " " << quat_wc.z() << " " << quat_wc.w() << std::endl;
}
else {
throw std::runtime_error("Not implemented: trajectory format \"" + format + "\"");
}
}
ofs.close();
}
} // namespace io
} // namespace openvslam
其他
1 与landmark相关

浙公网安备 33010602011771号